/******************************************************************************** Copyright (C) 2012 Hugh Bailey This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ********************************************************************************/ #pragma once class Scene; #define NUM_RENDER_BUFFERS 2 static const int minClientWidth = 700; static const int minClientHeight = 200; #define OUTPUT_BUFFER_TIME 400 struct AudioDeviceInfo { String strID; String strName; inline void FreeData() {strID.Clear(); strName.Clear();} }; struct AudioDeviceList { List devices; inline ~AudioDeviceList() { FreeData(); } inline void FreeData() { for(UINT i=0; i &packets, List &packetTypes, DWORD timestamp, int &ctsOffset)=0; public: virtual ~VideoEncoder() {} virtual int GetBitRate() const=0; virtual bool DynamicBitrateSupported() const=0; virtual bool SetBitRate(DWORD maxBitrate, DWORD bufferSize)=0; virtual void GetHeaders(DataPacket &packet)=0; virtual String GetInfoString() const=0; }; //------------------------------------------------------------------- struct MonitorInfo { inline MonitorInfo() {zero(this, sizeof(MonitorInfo));} inline MonitorInfo(HMONITOR hMonitor, RECT *lpRect) { this->hMonitor = hMonitor; mcpy(&this->rect, lpRect, sizeof(rect)); } HMONITOR hMonitor; RECT rect; }; struct DeviceOutputData { String strDevice; List monitors; StringList monitorNameList; inline void ClearData() { strDevice.Clear(); monitors.Clear(); monitorNameList.Clear(); } }; struct DeviceOutputs { List devices; inline ~DeviceOutputs() { ClearData(); } inline void ClearData() { for(UINT i=0; i audioData; QWORD timestamp; }; //=============================================================================================== struct ClassInfo { String strClass; String strName; OBSCREATEPROC createProc; OBSCONFIGPROC configProc; inline void FreeData() {strClass.Clear(); strName.Clear();} }; //---------------------------- struct PluginInfo { String strFile; HMODULE hModule; }; //---------------------------- struct GlobalSourceInfo { String strName; XElement *element; ImageSource *source; inline void FreeData() {strName.Clear(); delete source; source = NULL;} }; //---------------------------- enum { ID_SETTINGS=5000, ID_STARTSTOP, ID_EXIT, ID_SCENEEDITOR, ID_DESKTOPVOLUME, ID_MICVOLUME, ID_DESKTOPVOLUMEMETER, ID_MICVOLUMEMETER, ID_STATUS, ID_SCENES, ID_SCENES_TEXT, ID_SOURCES, ID_SOURCES_TEXT, ID_TESTSTREAM, ID_GLOBALSOURCES, ID_PLUGINS, ID_DASHBOARD, ID_SWITCHPROFILE, }; enum { OBS_REQUESTSTOP=WM_USER+1, OBS_CALLHOTKEY, OBS_RECONNECT, OBS_SETSCENE, OBS_SETSOURCEORDER, OBS_SETSOURCERENDER, OBS_UPDATESTATUSBAR, }; //---------------------------- enum ItemModifyType { ItemModifyType_None, ItemModifyType_Move, ItemModifyType_ScaleBottomLeft, ItemModifyType_ScaleLeft, ItemModifyType_ScaleTopLeft, ItemModifyType_ScaleTop, ItemModifyType_ScaleTopRight, ItemModifyType_ScaleRight, ItemModifyType_ScaleBottomRight, ItemModifyType_ScaleBottom, }; //---------------------------- struct SceneHotkeyInfo { DWORD hotkeyID; DWORD hotkey; XElement *scene; }; //---------------------------- struct StreamInfo { UINT id; String strInfo; StreamInfoPriority priority; inline void FreeData() {strInfo.Clear();} }; //---------------------------- struct StatusBarDrawData { UINT bytesPerSec; double strain; }; //---------------------------- struct VideoPacketData { List data; PacketType type; inline void Clear() {data.Clear();} }; struct VideoSegment { List packets; DWORD timestamp; int ctsOffset; inline VideoSegment() : timestamp(0), ctsOffset(0) {} inline ~VideoSegment() {Clear();} inline void Clear() { for(UINT i=0; i auxAudioSources; AudioEncoder *audioEncoder; //--------------------------------------------------- // scene/encoder Scene *scene; VideoEncoder *videoEncoder; HDC hCaptureDC; List monitors; XConfig scenesConfig; List sceneHotkeys; XElement *sceneElement; inline void RemoveSceneHotkey(DWORD hotkey) { for(UINT i=0; iDeleteHotkey(sceneHotkeys[i].hotkeyID); sceneHotkeys.Remove(i); break; } } } void SelectSources(); void CheckSources(); void SetSourceRender(CTSTR sourceName, bool render); //--------------------------------------------------- // settings window int curSettingsSelection; HWND hwndSettings; HWND hwndCurrentSettings; bool bSettingsChanged; inline void SetChangedSettings(bool bChanged) { EnableWindow(GetDlgItem(hwndSettings, IDC_APPLY), (bSettingsChanged = bChanged)); } void ApplySettings(); void RefreshDownscales(HWND hwnd, int cx, int cy); static INT_PTR CALLBACK GeneralSettingsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK EncoderSettingsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK PublishSettingsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK VideoSettingsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK AudioSettingsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK AdvancedSettingsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); //--------------------------------------------------- // mainly manly main window stuff String strLanguage; bool bTestStream; bool bUseMultithreadedOptimizations; bool bRunning; int renderFrameWidth, renderFrameHeight; int borderXSize, borderYSize; int clientWidth, clientHeight; bool bSizeChanging; bool bResizeRenderView; bool bAutoReconnect; bool bRetrying; bool bReconnecting; UINT reconnectTimeout; bool bDisableSceneSwitching; bool bChangingSources; bool bAlwaysOnTop; bool bEditMode; bool bRenderViewEnabled; bool bShowFPS; bool bMouseMoved; bool bMouseDown; bool bItemWasSelected; Vect2 startMousePos, lastMousePos; ItemModifyType modifyType; SceneItem *scaleItem; int cpuInfo[4]; bool bSSE2Available; //--------------------------------------------------- // resolution/fps/downscale/etc settings int lastRenderTarget; UINT baseCX, baseCY; UINT scaleCX, scaleCY; UINT outputCX, outputCY; float downscale; UINT frameTime, fps; bool bUsing444; //--------------------------------------------------- // stats int ctsOffset; DWORD bytesPerSec; DWORD captureFPS; DWORD curFramesDropped; DWORD totalStreamTime; double curStrain; //--------------------------------------------------- // main capture loop stuff HANDLE hMainThread; HANDLE hSceneMutex; List bufferedVideo; List bufferedTimes; List ctsOffsets; bool bRecievedFirstAudioFrame, bSentHeaders, bFirstAudioPacket; DWORD lastAudioTimestamp; QWORD firstSceneTimestamp; QWORD latestVideoTime; bool bUseCFR; bool bWriteToFile; VideoFileStream *fileStream; static DWORD STDCALL MainCaptureThread(LPVOID lpUnused); bool BufferVideoData(const List &inputPackets, const List &inputTypes, DWORD timestamp, VideoSegment &segmentOut); bool ProcessFrame(FrameProcessInfo &frameInfo); void MainCaptureLoop(); //--------------------------------------------------- // main audio capture loop stuff HANDLE hSoundThread, hSoundDataMutex;//, hRequestAudioEvent; QWORD latestAudioTime; float desktopVol, micVol, curMicVol; float desktopPeak, micPeak; float desktopMax, micMax; float desktopMag, micMag; List pendingAudioFrames; bool bForceMicMono; float micBoost; HANDLE hAuxAudioMutex; //--------------------------------------------------- // hotkey stuff HANDLE hHotkeyMutex; HANDLE hHotkeyThread; bool bUsingPushToTalk, bPushToTalkDown, bPushToTalkOn; int pushToTalkDelay, pushToTalkTimeLeft; UINT pushToTalkHotkeyID; UINT muteMicHotkeyID; UINT muteDesktopHotkeyID; UINT startStreamHotkeyID; UINT stopStreamHotkeyID; bool bStartStreamHotkeyDown, bStopStreamHotkeyDown; static DWORD STDCALL MainAudioThread(LPVOID lpUnused); bool QueryNewAudio(QWORD ×tamp); void MainAudioLoop(); //--------------------------------------------------- // random bla-haa String streamReport; String strDashboard; List Icons; List Fonts; List sceneClasses; List imageSourceClasses; List globalSources; HANDLE hInfoMutex; List streamInfoList; UINT streamInfoIDCounter; //--------------------------------------------------- List plugins; bool bShuttingDown; inline void ClearStreamInfo() { for(UINT i=0; i &globalSourceNames); XElement* GetGlobalSourceElement(CTSTR lpName); static INT_PTR CALLBACK GlobalSourcesProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static bool STDCALL ConfigGlobalSource(XElement *element, bool bCreating); void CallHotkey(DWORD hotkeyID, bool bDown); static void ResetProfileMenu(); void SetStatusBarData(); static void ClearStatusBar(); static void DrawStatusBar(DRAWITEMSTRUCT &dis); void ReloadIniSettings(); public: OBS(); ~OBS(); void ResizeWindow(bool bRedrawRenderFrame); inline void AddAudioSource(AudioSource *source) { OSEnterMutex(hAuxAudioMutex); auxAudioSources << source; OSLeaveMutex(hAuxAudioMutex); } inline void RemoveAudioSource(AudioSource *source) { OSEnterMutex(hAuxAudioMutex); auxAudioSources.RemoveItem(source); OSLeaveMutex(hAuxAudioMutex); } inline QWORD GetAudioTime() const {return latestAudioTime;} inline QWORD GetVideoTime() const {return latestVideoTime;} char* EncMetaData(char *enc, char *pend, bool bFLVFile=false); inline void PostStopMessage() {if(hwndMain) PostMessage(hwndMain, OBS_REQUESTSTOP, 0, 0);} void GetBaseSize(UINT &width, UINT &height) const; inline void GetRenderFrameSize(UINT &width, UINT &height) const {width = renderFrameWidth; height = renderFrameHeight;} inline void GetOutputSize(UINT &width, UINT &height) const {width = outputCX; height = outputCY;} inline Vect2 GetBaseSize() const { UINT width, height; GetBaseSize(width, height); return Vect2(float(width), float(height)); } inline Vect2 GetOutputSize() const {return Vect2(float(outputCX), float(outputCY));} inline Vect2 GetRenderFrameSize() const {return Vect2(float(renderFrameWidth), float(renderFrameHeight));} inline bool SSE2Available() const {return bSSE2Available;} inline AudioEncoder* GetAudioEncoder() const {return audioEncoder;} inline VideoEncoder* GetVideoEncoder() const {return videoEncoder;} inline void EnterSceneMutex() {OSEnterMutex(hSceneMutex);} inline void LeaveSceneMutex() {OSLeaveMutex(hSceneMutex);} inline void EnableSceneSwitching(bool bEnable) {bDisableSceneSwitching = !bEnable;} inline bool IsRunning() const {return bRunning;} inline UINT GetFPS() const {return fps;} inline UINT GetFrameTime() const {return frameTime;} inline UINT NumMonitors() const {return monitors.Num();} inline const MonitorInfo& GetMonitor(UINT id) const {if(id < monitors.Num()) return monitors[id]; else return monitors[0];} inline XElement* GetSceneElement() const {return sceneElement;} virtual HICON GetIcon(HINSTANCE hInst, int resource); virtual HFONT GetFont(CTSTR lpFontFace, int fontSize, int fontWeight); inline void GetVideoHeaders(DataPacket &packet) {videoEncoder->GetHeaders(packet);} inline void GetAudioHeaders(DataPacket &packet) {audioEncoder->GetHeaders(packet);} inline void SetStreamReport(CTSTR lpStreamReport) {streamReport = lpStreamReport;} UINT AddStreamInfo(CTSTR lpInfo, StreamInfoPriority priority); void SetStreamInfo(UINT infoID, CTSTR lpInfo); void SetStreamInfoPriority(UINT infoID, StreamInfoPriority priority); void RemoveStreamInfo(UINT infoID); String GetMostImportantInfo(); inline QWORD GetSceneTimestamp() {return firstSceneTimestamp;} //--------------------------------------------------------------------------- inline static CTSTR GetCurrentProfile() {return GlobalConfig->GetStringPtr(TEXT("General"), TEXT("Profile"));} static void GetProfiles(StringList &profileList); //--------------------------------------------------------------------------- virtual void RegisterSceneClass(CTSTR lpClassName, CTSTR lpDisplayName, OBSCREATEPROC createProc, OBSCONFIGPROC configProc); virtual void RegisterImageSourceClass(CTSTR lpClassName, CTSTR lpDisplayName, OBSCREATEPROC createProc, OBSCONFIGPROC configProc); virtual ImageSource* CreateImageSource(CTSTR lpClassName, XElement *data); virtual bool SetScene(CTSTR lpScene); virtual void AddSourceItem(LPWSTR name, bool checked, UINT index); //--------------------------------------------------------------------------- // event stuff List triggerHandlers; //--------------------------------------------------------------------------- // add remove event listeners virtual void AddOBSEventListener(OBSTriggerHandler *handler); virtual void RemoveOBSEventListener(OBSTriggerHandler *handler); // event reporting functions virtual void ReportStartStreamTrigger(bool previewOnly); virtual void ReportStopStreamTrigger(bool previewOnly); virtual void ReportStreamStatus(bool streaming, bool previewOnly = false, UINT bytesPerSec = 0, double strain = 0, UINT totalStreamtime = 0, UINT numTotalFrames = 0, UINT numDroppedFrames = 0, UINT fps = 0); virtual void ReportSwitchScenes(CTSTR scene); virtual void ReportScenesChanged(); virtual void ReportSourceOrderChanged(); virtual void ReportSourceChanged(CTSTR sourceName, XElement* source); virtual void ReportSourcesAddedOrRemoved(); }; LONG CALLBACK OBSExceptionHandler (PEXCEPTION_POINTERS exceptionInfo);