diff --git a/OBS-All.sln b/OBS-All.sln index 9b5aab31..e98060fd 100644 --- a/OBS-All.sln +++ b/OBS-All.sln @@ -59,6 +59,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ObsNvenc", "ObsNvenc\ObsNve EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libMinHook", "minhook\build\libMinHook.vcxproj", "{65021938-D251-46FA-BC3D-85C385D4C06D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scenesw", "scenesw\scenesw.vcxproj", "{6AC307E3-7D59-4DB2-944F-961E299F063A}" + ProjectSection(ProjectDependencies) = postProject + {11A35235-DD48-41E2-8F40-825C78024BC0} = {11A35235-DD48-41E2-8F40-825C78024BC0} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -187,6 +192,14 @@ Global {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|Win32.Build.0 = Release|Win32 {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.ActiveCfg = Release|x64 {65021938-D251-46FA-BC3D-85C385D4C06D}.Release|x64.Build.0 = Release|x64 + {6AC307E3-7D59-4DB2-944F-961E299F063A}.Debug|Win32.ActiveCfg = Debug|Win32 + {6AC307E3-7D59-4DB2-944F-961E299F063A}.Debug|Win32.Build.0 = Debug|Win32 + {6AC307E3-7D59-4DB2-944F-961E299F063A}.Debug|x64.ActiveCfg = Debug|x64 + {6AC307E3-7D59-4DB2-944F-961E299F063A}.Debug|x64.Build.0 = Debug|x64 + {6AC307E3-7D59-4DB2-944F-961E299F063A}.Release|Win32.ActiveCfg = Release|Win32 + {6AC307E3-7D59-4DB2-944F-961E299F063A}.Release|Win32.Build.0 = Release|Win32 + {6AC307E3-7D59-4DB2-944F-961E299F063A}.Release|x64.ActiveCfg = Release|x64 + {6AC307E3-7D59-4DB2-944F-961E299F063A}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/installer/generate_binaries.bat b/installer/generate_binaries.bat index 2bbfbb0e..c4971f53 100644 --- a/installer/generate_binaries.bat +++ b/installer/generate_binaries.bat @@ -9,6 +9,8 @@ mkdir 32bit\plugins\DShowPlugin\shaders mkdir 32bit\plugins\GraphicsCapture mkdir 32bit\plugins\PSVPlugin mkdir 32bit\plugins\PSVPlugin\locale +mkdir 32bit\plugins\scenesw +mkdir 32bit\plugins\scenesw\locale mkdir 64bit mkdir 64bit\locale @@ -20,6 +22,8 @@ mkdir 64bit\plugins\DShowPlugin\shaders mkdir 64bit\plugins\GraphicsCapture mkdir 64bit\plugins\PSVPlugin mkdir 64bit\plugins\PSVPlugin\locale +mkdir 64bit\plugins\scenesw +mkdir 64bit\plugins\scenesw\locale mkdir pdbs mkdir pdbs\32bit @@ -35,9 +39,11 @@ copy ..\rundir\shaders\*.?Shader .\32bit\shaders\ copy ..\dshowplugin\release\dshowplugin.dll .\32bit\plugins copy ..\noisegate\release\noisegate.dll .\32bit\plugins copy ..\psvplugin\release\psvplugin.dll .\32bit\plugins +copy ..\scenesw\release\scenesw.dll .\32bit\plugins copy ..\rundir\plugins\dshowplugin\locale\*.txt .\32bit\plugins\dshowplugin\locale\ copy ..\rundir\plugins\dshowplugin\shaders\*.?Shader .\32bit\plugins\dshowplugin\shaders\ copy ..\rundir\plugins\psvplugin\locale\*.txt .\32bit\plugins\psvplugin\locale\ +copy ..\rundir\plugins\scenesw\locale\*.txt .\32bit\plugins\scenesw\locale\ copy ..\graphicscapture\release\graphicscapture.dll .\32bit\plugins copy ..\graphicscapture\graphicscapturehook\release\graphicscapturehook.dll .\32bit\plugins\graphicscapture copy ..\graphicscapture\graphicscapturehook\x64\release\graphicscapturehook64.dll .\32bit\plugins\graphicscapture @@ -58,9 +64,11 @@ copy ..\rundir\shaders\*.?Shader .\64bit\shaders\ copy ..\dshowplugin\x64\release\dshowplugin.dll .\64bit\plugins copy ..\noisegate\x64\release\noisegate.dll .\64bit\plugins copy ..\psvplugin\x64\release\psvplugin.dll .\64bit\plugins +copy ..\scenesw\x64\release\scenesw.dll .\64bit\plugins copy ..\rundir\plugins\dshowplugin\locale\*.txt .\64bit\plugins\dshowplugin\locale\ copy ..\rundir\plugins\dshowplugin\shaders\*.?Shader .\64bit\plugins\dshowplugin\shaders\ copy ..\rundir\plugins\psvplugin\locale\*.txt .\64bit\plugins\psvplugin\locale\ +copy ..\rundir\plugins\scenesw\locale\*.txt .\64bit\plugins\scenesw\locale\ copy ..\graphicscapture\x64\release\graphicscapture.dll .\64bit\plugins copy ..\graphicscapture\graphicscapturehook\release\graphicscapturehook.dll .\64bit\plugins\graphicscapture copy ..\graphicscapture\graphicscapturehook\x64\release\graphicscapturehook64.dll .\64bit\plugins\graphicscapture @@ -97,6 +105,11 @@ mkdir upload\PSVPlugin\32bit mkdir upload\PSVPlugin\32bit\PSVPlugin\locale mkdir upload\PSVPlugin\64bit mkdir upload\PSVPlugin\64bit\PSVPlugin\locale +mkdir upload\scenesw +mkdir upload\scenesw\32bit +mkdir upload\scenesw\32bit\scenesw\locale +mkdir upload\scenesw\64bit +mkdir upload\scenesw\64bit\scenesw\locale mkdir upload\OBS mkdir upload\OBS\32bit mkdir upload\OBS\64bit @@ -133,6 +146,12 @@ copy 32bit\plugins\psvplugin\locale\*.txt .\upload\PSVPlugin\32bit\PSVPlugin\loc copy 64bit\plugins\psvplugin.dll .\upload\PSVPlugin\64bit\ copy 64bit\plugins\psvplugin\locale\*.txt .\upload\PSVPlugin\64bit\PSVPlugin\locale\ +copy 32bit\plugins\scenesw.dll .\upload\scenesw\32bit\ +copy 32bit\plugins\scenesw\locale\*.txt .\upload\scenesw\32bit\scenesw\locale\ + +copy 64bit\plugins\scenesw.dll .\upload\scenesw\64bit\ +copy 64bit\plugins\scenesw\locale\*.txt .\upload\scenesw\64bit\scenesw\locale\ + copy 32bit\obs.exe .\upload\OBS\32bit\ copy 32bit\obsapi.dll .\upload\OBS\32bit\ copy 32bit\*.pdb .\upload\OBS\32bit\ diff --git a/installer/generate_binaries_test.bat b/installer/generate_binaries_test.bat index 529af33c..9615bf62 100644 --- a/installer/generate_binaries_test.bat +++ b/installer/generate_binaries_test.bat @@ -9,6 +9,8 @@ mkdir 32bit\plugins\DShowPlugin\shaders mkdir 32bit\plugins\GraphicsCapture mkdir 32bit\plugins\PSVPlugin mkdir 32bit\plugins\PSVPlugin\locale +mkdir 32bit\plugins\scenesw +mkdir 32bit\plugins\scenesw\locale mkdir 64bit mkdir 64bit\locale @@ -20,6 +22,8 @@ mkdir 64bit\plugins\DShowPlugin\shaders mkdir 64bit\plugins\GraphicsCapture mkdir 64bit\plugins\PSVPlugin mkdir 64bit\plugins\PSVPlugin\locale +mkdir 64bit\plugins\scenesw +mkdir 64bit\plugins\scenesw\locale copy ..\release\obs.exe .\32bit\ copy ..\obsapi\release\obsapi.dll .\32bit\ @@ -30,14 +34,17 @@ copy ..\rundir\pdb32\DShowPlugin.pdb .\32bit\plugins\ copy ..\rundir\pdb32\GraphicsCapture.pdb .\32bit\plugins\ copy ..\rundir\pdb32\NoiseGate.pdb .\32bit\plugins\ copy ..\rundir\pdb32\PSVPlugin.pdb .\32bit\plugins\ +copy ..\rundir\pdb32\scenesw.pdb .\32bit\plugins\ copy ..\rundir\locale\*.txt .\32bit\locale\ copy ..\rundir\shaders\*.?Shader .\32bit\shaders\ copy ..\dshowplugin\release\dshowplugin.dll .\32bit\plugins copy ..\noisegate\release\noisegate.dll .\32bit\plugins copy ..\psvplugin\release\psvplugin.dll .\32bit\plugins +copy ..\scenesw\release\scenesw.dll .\32bit\plugins copy ..\rundir\plugins\dshowplugin\locale\*.txt .\32bit\plugins\dshowplugin\locale\ copy ..\rundir\plugins\dshowplugin\shaders\*.?Shader .\32bit\plugins\dshowplugin\shaders\ copy ..\rundir\plugins\psvplugin\locale\*.txt .\32bit\plugins\psvplugin\locale\ +copy ..\rundir\plugins\scenesw\locale\*.txt .\32bit\plugins\scenesw\locale\ copy ..\graphicscapture\release\graphicscapture.dll .\32bit\plugins copy ..\graphicscapture\graphicscapturehook\release\graphicscapturehook.dll .\32bit\plugins\graphicscapture copy ..\graphicscapture\graphicscapturehook\x64\release\graphicscapturehook64.dll .\32bit\plugins\graphicscapture @@ -57,14 +64,17 @@ copy ..\rundir\pdb64\DShowPlugin.pdb .\64bit\plugins\ copy ..\rundir\pdb64\GraphicsCapture.pdb .\64bit\plugins\ copy ..\rundir\pdb64\NoiseGate.pdb .\64bit\plugins\ copy ..\rundir\pdb64\PSVPlugin.pdb .\64bit\plugins\ +copy ..\rundir\pdb64\scenesw.pdb .\64bit\plugins\ copy ..\rundir\locale\*.txt .\64bit\locale\ copy ..\rundir\shaders\*.?Shader .\64bit\shaders\ copy ..\dshowplugin\x64\release\dshowplugin.dll .\64bit\plugins copy ..\noisegate\x64\release\noisegate.dll .\64bit\plugins copy ..\psvplugin\x64\release\psvplugin.dll .\64bit\plugins +copy ..\scenesw\x64\release\scenesw.dll .\64bit\plugins copy ..\rundir\plugins\dshowplugin\locale\*.txt .\64bit\plugins\dshowplugin\locale\ copy ..\rundir\plugins\dshowplugin\shaders\*.?Shader .\64bit\plugins\dshowplugin\shaders\ copy ..\rundir\plugins\psvplugin\locale\*.txt .\64bit\plugins\psvplugin\locale\ +copy ..\rundir\plugins\scenesw\locale\*.txt .\64bit\plugins\scenesw\locale\ copy ..\graphicscapture\x64\release\graphicscapture.dll .\64bit\plugins copy ..\graphicscapture\graphicscapturehook\release\graphicscapturehook.dll .\64bit\plugins\graphicscapture copy ..\graphicscapture\graphicscapturehook\x64\release\graphicscapturehook64.dll .\64bit\plugins\graphicscapture diff --git a/installer/installer.nsi b/installer/installer.nsi index 75f47700..f1e4f8ac 100644 --- a/installer/installer.nsi +++ b/installer/installer.nsi @@ -155,6 +155,9 @@ Section "Open Broadcaster Software" Section1 File "32bit\plugins\PSVPlugin.dll" SetOutPath "$PROGRAMFILES32\OBS\plugins\PSVPlugin\locale\" File "32bit\plugins\PSVPlugin\locale\*.txt" + File "32bit\plugins\scenesw.dll" + SetOutPath "$PROGRAMFILES32\OBS\plugins\scenesw\locale\" + File "32bit\plugins\scenesw\locale\*.txt" SetOutPath "$PROGRAMFILES32\OBS\plugins\DShowPlugin\locale\" File "32bit\plugins\DShowPlugin\locale\*.txt" SetOutPath "$PROGRAMFILES32\OBS\plugins\DShowPlugin\shaders\" @@ -193,6 +196,9 @@ Section "Open Broadcaster Software" Section1 File "64bit\plugins\PSVPlugin.dll" SetOutPath "$PROGRAMFILES64\OBS\plugins\PSVPlugin\locale\" File "64bit\plugins\PSVPlugin\locale\*.txt" + File "64bit\plugins\scenesw.dll" + SetOutPath "$PROGRAMFILES64\OBS\plugins\scenesw\locale\" + File "64bit\plugins\scenesw\locale\*.txt" SetOutPath "$PROGRAMFILES64\OBS\plugins\DShowPlugin\locale\" File "64bit\plugins\DShowPlugin\locale\*.txt" SetOutPath "$PROGRAMFILES64\OBS\plugins\DShowPlugin\shaders\" @@ -280,6 +286,8 @@ Section "un.OBS Program Files" Delete "$PROGRAMFILES32\OBS\plugins\NoiseGate.dll" Delete "$PROGRAMFILES32\OBS\plugins\PSVPlugin.dll" Delete "$PROGRAMFILES32\OBS\plugins\PSVPlugin\locale\*.txt" + Delete "$PROGRAMFILES32\OBS\plugins\scenesw.dll" + Delete "$PROGRAMFILES32\OBS\plugins\scenesw\locale\*.txt" Delete "$PROGRAMFILES32\OBS\plugins\DShowPlugin\locale\*.txt" Delete "$PROGRAMFILES32\OBS\plugins\DShowPlugin\shaders\*.?Shader" Delete "$PROGRAMFILES32\OBS\plugins\GraphicsCapture\*.dll" @@ -301,6 +309,8 @@ Section "un.OBS Program Files" Delete "$PROGRAMFILES64\OBS\plugins\NoiseGate.dll" Delete "$PROGRAMFILES64\OBS\plugins\PSVPlugin.dll" Delete "$PROGRAMFILES64\OBS\plugins\PSVPlugin\locale\*.txt" + Delete "$PROGRAMFILES64\OBS\plugins\scenesw.dll" + Delete "$PROGRAMFILES64\OBS\plugins\scenesw\locale\*.txt" Delete "$PROGRAMFILES64\OBS\plugins\DShowPlugin\locale\*.txt" Delete "$PROGRAMFILES64\OBS\plugins\DShowPlugin\shaders\*.?Shader" Delete "$PROGRAMFILES64\OBS\plugins\GraphicsCapture\*.dll" @@ -315,6 +325,8 @@ Section "un.OBS Program Files" RMDir "$PROGRAMFILES32\OBS\plugins\DShowPlugin\" RMDir "$PROGRAMFILES32\OBS\plugins\PSVPlugin\locale\" RMDir "$PROGRAMFILES32\OBS\plugins\PSVPlugin\" + RMDir "$PROGRAMFILES32\OBS\plugins\scenesw\locale\" + RMDir "$PROGRAMFILES32\OBS\plugins\scenesw\" RMDir "$PROGRAMFILES32\OBS\plugins" RMDir "$PROGRAMFILES32\OBS\locale" RMDir "$PROGRAMFILES32\OBS\shaders" @@ -325,6 +337,8 @@ Section "un.OBS Program Files" RMDir "$PROGRAMFILES64\OBS\plugins\DShowPlugin\" RMDir "$PROGRAMFILES64\OBS\plugins\PSVPlugin\locale\" RMDir "$PROGRAMFILES64\OBS\plugins\PSVPlugin\" + RMDir "$PROGRAMFILES64\OBS\plugins\scenesw\locale\" + RMDir "$PROGRAMFILES64\OBS\plugins\scenesw\" RMDir "$PROGRAMFILES64\OBS\plugins" RMDir "$PROGRAMFILES64\OBS\locale" RMDir "$PROGRAMFILES64\OBS\shaders" diff --git a/rundir/copydebug.bat b/rundir/copydebug.bat index c4d44dd7..48cb3fbc 100644 --- a/rundir/copydebug.bat +++ b/rundir/copydebug.bat @@ -7,6 +7,7 @@ copy ..\graphicscapture\graphicscapturehook\debug\graphicscapturehook.dll .\plug copy ..\graphicscapture\graphicscapturehook\x64\debug\graphicscapturehook64.dll .\plugins\graphicscapture copy ..\noisegate\debug\noisegate.dll .\plugins copy ..\psvplugin\debug\psvplugin.dll .\plugins +copy ..\scenesw\debug\scenesw.dll .\plugins copy ..\x264\libs\32bit\libx264-142.dll .\ copy ..\injectHelper\Release\injectHelper.exe .\plugins\graphicscapture copy ..\injectHelper\x64\Release\injectHelper64.exe .\plugins\graphicscapture diff --git a/rundir/copydebug64.bat b/rundir/copydebug64.bat index 01f82e71..0f9560dc 100644 --- a/rundir/copydebug64.bat +++ b/rundir/copydebug64.bat @@ -7,6 +7,7 @@ copy ..\graphicscapture\graphicscapturehook\debug\graphicscapturehook.dll .\plug copy ..\graphicscapture\graphicscapturehook\x64\debug\graphicscapturehook64.dll .\plugins\graphicscapture copy ..\noisegate\x64\debug\noisegate.dll .\plugins copy ..\psvplugin\x64\debug\psvplugin.dll .\plugins +copy ..\scenesw\x64\debug\scenesw.dll .\plugins copy ..\x264\libs\64bit\libx264-142.dll .\ copy ..\injectHelper\Release\injectHelper.exe .\plugins\graphicscapture copy ..\injectHelper\x64\Release\injectHelper64.exe .\plugins\graphicscapture diff --git a/rundir/copyrelease.bat b/rundir/copyrelease.bat index 192b7f99..e71fd306 100644 --- a/rundir/copyrelease.bat +++ b/rundir/copyrelease.bat @@ -7,6 +7,7 @@ copy ..\graphicscapture\graphicscapturehook\release\graphicscapturehook.dll .\pl copy ..\graphicscapture\graphicscapturehook\x64\release\graphicscapturehook64.dll .\plugins\graphicscapture copy ..\noisegate\release\noisegate.dll .\plugins copy ..\psvplugin\release\psvplugin.dll .\plugins +copy ..\scenesw\release\scenesw.dll .\plugins copy ..\x264\libs\32bit\libx264-142.dll .\ copy ..\injectHelper\Release\injectHelper.exe .\plugins\graphicscapture copy ..\injectHelper\x64\Release\injectHelper64.exe .\plugins\graphicscapture diff --git a/rundir/copyrelease64.bat b/rundir/copyrelease64.bat index f38b4ef5..1d0c0ef8 100644 --- a/rundir/copyrelease64.bat +++ b/rundir/copyrelease64.bat @@ -7,6 +7,7 @@ copy ..\graphicscapture\graphicscapturehook\release\graphicscapturehook.dll .\pl copy ..\graphicscapture\graphicscapturehook\x64\release\graphicscapturehook64.dll .\plugins\graphicscapture copy ..\noisegate\x64\release\noisegate.dll .\plugins copy ..\psvplugin\x64\release\psvplugin.dll .\plugins +copy ..\scenesw\x64\release\scenesw.dll .\plugins copy ..\x264\libs\64bit\libx264-142.dll .\ copy ..\injectHelper\Release\injectHelper.exe .\plugins\graphicscapture copy ..\injectHelper\x64\Release\injectHelper64.exe .\plugins\graphicscapture diff --git a/rundir/plugins/scenesw/locale/en.txt b/rundir/plugins/scenesw/locale/en.txt new file mode 100644 index 00000000..9e8e11a1 --- /dev/null +++ b/rundir/plugins/scenesw/locale/en.txt @@ -0,0 +1,26 @@ +Settings.MainWndTitle="Window title to check for:" +Settings.MainWndScene="Scene to switch to on window title:" +Settings.WindowTitle="Window Title" +Settings.Scene="Scene" +Settings.MatchExact="Match exact window name" +Settings.SetToggleHotkey="Set a hotkey to toggle Scene Switcher:" +Settings.NoMatch="When no window title matches" +Settings.SwitchTo="switch to:" +Settings.DontSwitch="don't switch" +Settings.ClearHotkey="Clear Hotkey" +Settings.Up="Up" +Settings.Down="Down" +Settings.Add="Add" +Settings.Remove="Remove" +Settings.CheckEvery="Check active window title every" +Settings.Milliseconds="milliseconds." +Settings.PluginIs="Plugin is" +Settings.Running="running" +Settings.NotRunning="not running" +Settings.Start="Start" +Settings.Stop="Stop" +Settings.StartLaunch="Start at launch if possible" + +Plugin.Description="Simple scene switcher. It will switch between several scenes according to your active window.\n\nThe settings can be found in the OBS settings window." +Plugin.Name="OBS Scene switcher" +Plugin.SettingsName="Scene Switcher" \ No newline at end of file diff --git a/scenesw/SceneSwitcher.cpp b/scenesw/SceneSwitcher.cpp new file mode 100644 index 00000000..c75d0310 --- /dev/null +++ b/scenesw/SceneSwitcher.cpp @@ -0,0 +1,300 @@ +/******************************************************************************** + Copyright (C) 2013 Christophe Jeannin + Hugh Bailey + Eric Bataille + + 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. +********************************************************************************/ + +#include "scenesw.h" + +SceneSwitcher::SceneSwitcher(HINSTANCE hinstMain, OBSHOTKEYPROC ToggleHotkeyProc) +{ + hinstDll = hinstMain; + + // The localization part + pluginLocale = new LocaleStringLookup; + + if(!pluginLocale->LoadStringFile(TEXT("plugins/scenesw/locale/en.txt"))) + AppWarning(TEXT("Could not open locale string file '%s'"), TEXT("plugins/scenesw/locale/en.txt")); + + if(scmpi(API->GetLanguage(), TEXT("en")) != 0) + { + String pluginStringFile; + pluginStringFile << TEXT("plugins/scenesw/locale/") << API->GetLanguage() << TEXT(".txt"); + if(!pluginLocale->LoadStringFile(pluginStringFile)) + AppWarning(TEXT("Could not open locale string file '%s'"), pluginStringFile.Array()); + } + + timeToSleep = TTS_DEFAULT; + thread = 0; + timer = 0; + bKillThread = true; + mainSceneName.Clear(); + altSceneName.Clear(); + mainWndName.Clear(); + altDoSwitch = 1; + matchExact = 1; + + // Start with an empty list of window-scene assignments + nWindowsDefined = 0; + scenes.Clear(); + windows.Clear(); + + config.Open(OBSGetPluginDataPath() + CONFIGFILENAME, true); + ReadSettings(); + + stopReq = CreateEvent(NULL, FALSE, FALSE, NULL); + + if(startAuto) + { + StartThread(); + } + + settings = new SceneSwitcherSettings(this, ToggleHotkeyProc); + OBSAddSettingsPane(settings); +} + +SceneSwitcher::~SceneSwitcher() +{ + OBSRemoveSettingsPane(settings); + delete settings; + + delete pluginLocale; + + StopThread(); + config.Close(); + CloseHandle(stopReq); +} + + +void SceneSwitcher::ReadSettings() +{ + mainWndName = config.GetString(TEXT("General"), TEXT("MainWindow")); + mainSceneName = config.GetString(TEXT("General"), TEXT("MainScene")); + altSceneName = config.GetString(TEXT("General"), TEXT("AltScene")); + startAuto = config.GetInt(TEXT("General"), TEXT("StartAuto")); + timeToSleep = (DWORD)config.GetInt(TEXT("General"), TEXT("CheckFrequency")); + nWindowsDefined = config.GetInt(TEXT("GENERAL"), TEXT("nWindows")); + altDoSwitch = config.GetInt(TEXT("GENERAL"), TEXT("AltDoSwitch")); + toggleHotkey = (DWORD)config.GetInt(TEXT("GENERAL"), TEXT("ToggleHotkey")); + matchExact = config.GetInt(TEXT("GENERAL"), TEXT("MatchExact"), 1); + scenes.Clear(); + windows.Clear(); + config.GetStringList(TEXT("SceneDef"), TEXT("window"), windows); + config.GetStringList(TEXT("SceneDef"), TEXT("scene"), scenes); + if ((int)windows.Num() < nWindowsDefined) nWindowsDefined = windows.Num(); + if ((int)scenes.Num() < nWindowsDefined) nWindowsDefined = scenes.Num(); + + if(!timeToSleep) + timeToSleep = TTS_DEFAULT; + else + TTS_CLAMP(timeToSleep); +} + + +void SceneSwitcher::WriteSettings() +{ + config.SetString(TEXT("General"), TEXT("MainWindow"), mainWndName); + config.SetString(TEXT("General"), TEXT("MainScene"), mainSceneName); + config.SetString(TEXT("General"), TEXT("AltScene"), altSceneName); + config.SetInt(TEXT("General"), TEXT("StartAuto"), startAuto); + config.SetInt(TEXT("General"), TEXT("CheckFrequency"), timeToSleep); + config.SetInt(TEXT("General"), TEXT("nWindows"), nWindowsDefined); + config.SetInt(TEXT("General"), TEXT("AltDoSwitch"), altDoSwitch); + config.SetInt(TEXT("General"), TEXT("ToggleHotkey"), toggleHotkey); + config.SetInt(TEXT("General"), TEXT("MatchExact"), matchExact); + config.SetStringList(TEXT("SceneDef"), TEXT("window"), windows); + config.SetStringList(TEXT("SceneDef"), TEXT("scene"), scenes); +} + + + +DWORD SceneSwitcher::Run() +{ + LARGE_INTEGER dueTime; + + if((timer = CreateWaitableTimer(NULL, FALSE, NULL)) == NULL) + return -1; + dueTime.QuadPart=0; + SetWaitableTimer(timer, &dueTime, timeToSleep, NULL, NULL, FALSE); + HANDLE handles[] = { timer, stopReq }; + + String currentWindowText; + while(!bKillThread) + { + HWND hwndCurrent = GetForegroundWindow(); + currentWindowText.SetLength(GetWindowTextLength(hwndCurrent)); + GetWindowText(hwndCurrent, currentWindowText, currentWindowText.Length() + 1); + + String currentScene = OBSGetSceneName(); + String sceneToSwitch; + + // See if we get matches + bool found = false; + for (int i = 0; i < nWindowsDefined; i++) + { + bool match = false; + String toCheck = GetWindow(i); + if (currentWindowText == toCheck) match = true; + TCHAR *cwt = currentWindowText.Array(); + TCHAR *tch = toCheck.Array(); + if (cwt && tch) + if (!IsMatchExact() && sstr(cwt, tch)) match = true; + + if (match) + { + sceneToSwitch = GetScene(i); + found = true; + break; // take the first one + } + } + if (!found) // Otherwise, take the alternate scene + sceneToSwitch = altSceneName; + + // Make the switch if it isnt already selected + if (sceneToSwitch != currentScene && (found || altDoSwitch != 0)) + OBSSetScene(sceneToSwitch, true); + + WaitForMultipleObjects(2, handles, FALSE, INFINITE); + } + + CloseHandle(timer); + return 0; +} + + +void SceneSwitcher::StartThread(HWND hDialog) +{ + if(!thread) + { + bKillThread = false; + thread = CreateThread(NULL, 0, ThreadProc, (LPVOID)this, 0, NULL); + + if(hDialog && thread) + { + SetWindowText(GetDlgItem(hDialog, IDC_RUN), pluginLocale->LookupString(TEXT("Settings.Running"))); + SetWindowText(GetDlgItem(hDialog, IDC_STOP), pluginLocale->LookupString(TEXT("Settings.Stop"))); + } + } +} + + +void SceneSwitcher::StopThread(HWND hDialog) +{ + if(thread) + { + bKillThread = true; + + DWORD retv; + MSG msg; + HANDLE handles[] = {thread}; + SetEvent(stopReq); + //process messages while waiting for the thread to complete, otherwise the thread will be locked forever + while((retv = MsgWaitForMultipleObjects(1, handles, FALSE, INFINITE, QS_ALLINPUT)) != WAIT_FAILED) + { + if(retv == WAIT_OBJECT_0) + break; + else if(retv == WAIT_OBJECT_0+1) + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + ResetEvent(stopReq); + + if(thread) + { + CloseHandle(thread); + thread = 0; + } + } + + if(hDialog) + { + SetWindowText(GetDlgItem(hDialog, IDC_RUN), pluginLocale->LookupString(TEXT("Settings.NotRunning"))); + SetWindowText(GetDlgItem(hDialog, IDC_STOP), pluginLocale->LookupString(TEXT("Settings.Start"))); + } +} + + +void SceneSwitcher::ApplyConfig(HWND hDialog) +{ + if(!hDialog) // Noes.. Dialog don't exist? + return; + + // Get the listbox control handles + HWND hwndMainScn = GetDlgItem(hDialog, IDC_MAINSCN); + HWND hwndAltScn = GetDlgItem(hDialog, IDC_ALTSCN); + HWND hwndAppList = GetDlgItem(hDialog, IDC_APPLIST); + HWND hwndWSMap = GetDlgItem(hDialog, IDC_WSMAP); + HWND hwndHotkey = GetDlgItem(hDialog, IDC_TOGGLEHOTKEY); + + // Get the options names from the controls + String newMainSceneName = GetCBText(hwndMainScn, CB_ERR); + String newAltSceneName = GetCBText(hwndAltScn, CB_ERR); + String newMainWndName = GetCBText(hwndAppList, CB_ERR); + + // Get the new frequency from the frequency control + DWORD newTimeToSleep = GetDlgItemInt(hDialog, IDC_FREQ, NULL, FALSE); + TTS_CLAMP(newTimeToSleep); + + // Get the toggle hotkey if any + toggleHotkey = (DWORD)SendMessage(hwndHotkey, HKM_GETHOTKEY, 0, 0); + + // Get the checkboxes state + altDoSwitch = IsDlgButtonChecked(hDialog, IDC_ALTSWITCH); + matchExact = IsDlgButtonChecked(hDialog, IDC_EXACT); + startAuto = IsDlgButtonChecked(hDialog, IDC_STARTAUTO); + + if(newAltSceneName.IsEmpty() && IsAltDoSwitch()) + StopThread(hDialog); // if we're applying a bad config stop thread first + + if((timeToSleep != newTimeToSleep) && thread && timer) + { // reset timer with new value + LARGE_INTEGER dueTime; + dueTime.QuadPart=0; + SetWaitableTimer(timer, &dueTime, newTimeToSleep, NULL, NULL, FALSE); + } + + + nWindowsDefined = SendMessage(hwndWSMap, LVM_GETITEMCOUNT, 0, 0); + scenes.Clear(); + windows.Clear(); + for (int i = 0; i < nWindowsDefined; i++) + { + // Get the window name + String wnd; + wnd.SetLength(256); + ListView_GetItemText(hwndWSMap, i, 0, wnd, 256); + windows.Add(wnd); + + // Get the scene name + String scn; + scn.SetLength(256); + ListView_GetItemText(hwndWSMap, i, 1, scn, 256); + scenes.Add(scn); + } + + // Set the new global values + timeToSleep = newTimeToSleep; + mainSceneName = newMainSceneName; + altSceneName = newAltSceneName; + mainWndName = newMainWndName; + + WriteSettings(); // Write the settings to config +} + diff --git a/scenesw/SceneSwitcher.h b/scenesw/SceneSwitcher.h new file mode 100644 index 00000000..b4377bb0 --- /dev/null +++ b/scenesw/SceneSwitcher.h @@ -0,0 +1,134 @@ +/******************************************************************************** + Copyright (C) 2013 Christophe Jeannin + Eric Bataille + + 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. +********************************************************************************/ + +#include "SettingsPane.h" + +#pragma once + +#define CONFIGFILENAME TEXT("\\scenesw.ini") +#define TTS_DEFAULT 300 +#define TTS_MIN 50 +#define TTS_MAX 5000 +#define TTS_CLAMP(x) x = (x < TTS_MIN ? TTS_MIN : (x > TTS_MAX ? TTS_MAX : x)) + +#define PluginStr(text) thePlugin->pluginLocale->LookupString(TEXT2(text)) + +class SceneSwitcher; + +class SceneSwitcherSettings : public SettingsPane { +private: + SceneSwitcher * thePlugin; + OBSHOTKEYPROC ToggleHotkeyProc; + bool pChange; + + //----------------------------------------------------------------------- + // Constructor/destructor +public: + SceneSwitcherSettings(SceneSwitcher *thePlugin, OBSHOTKEYPROC ToggleHotkeyProc); + virtual ~SceneSwitcherSettings(); + + //----------------------------------------------------------------------- + // Fields +public: + UINT hotkeyID; + DWORD hotkey; + + //----------------------------------------------------------------------- + // Methods +private: + void RefreshConfig(); + void ApplyConfig(HWND hWnd); + void EditItem(bool selChange); + + // Message processing + void MsgInitDialog(); + void MsgDestroy(); + INT_PTR MsgClicked(int controlId, int code, HWND controlHwnd); + +public: + // Interface + virtual CTSTR GetCategory() const; + virtual HWND CreatePane(HWND parentHwnd); + virtual void DestroyPane(); + virtual INT_PTR ProcMessage(UINT message, WPARAM wParam, LPARAM lParam); + virtual void ApplySettings(); + virtual void CancelSettings(); + virtual bool HasDefaults() const; +}; + + +class SceneSwitcher +{ + friend class SceneSwitcherSettings; + + HANDLE thread; + HANDLE timer; + HANDLE stopReq; + DWORD timeToSleep; + String mainSceneName; + String altSceneName; + String mainWndName; + int startAuto; + int matchExact; + bool bKillThread; + ConfigFile config; + int altDoSwitch; + DWORD toggleHotkey; + + SceneSwitcherSettings * settings; + + int nWindowsDefined; + StringList windows; + StringList scenes; + + inline bool CheckSettings() const {return (!altSceneName.IsEmpty());} + void ReadSettings(); + void WriteSettings(); + + DWORD Run(); + static DWORD WINAPI ThreadProc(LPVOID pParam){return static_cast(pParam)->Run();} + +public: + LocaleStringLookup *pluginLocale; + + HINSTANCE hinstDll; + + inline CTSTR GetmainSceneName() const {return mainSceneName;} + inline CTSTR GetaltSceneName() const {return altSceneName;} + inline CTSTR GetmainWndName() const {return mainWndName;} + inline DWORD GettimeToSleep() const {return timeToSleep;} + inline bool IsRunning() const {return thread!=0;} + inline bool IsStartAuto() const {return startAuto!=0;} + inline bool IsAltDoSwitch() const {return altDoSwitch!=0;} + inline bool IsMatchExact() const {return matchExact!=0;} + inline int GetToggleHotkey() const {return toggleHotkey;} + + inline int GetnWindowsDefined() const {return nWindowsDefined;} + inline String GetWindow(int i) const {return windows[i];} + inline String GetScene(int i) const {return scenes[i];} + + inline SceneSwitcherSettings* GetSettings() const { return settings; } + + SceneSwitcher(HINSTANCE hinstMain, OBSHOTKEYPROC ToggleHotkeyProc); + ~SceneSwitcher(); + + void StartThread(HWND hDialog = NULL); + void StopThread (HWND hDialog = NULL); + void ApplyConfig(HWND hDialog); +}; \ No newline at end of file diff --git a/scenesw/SceneSwitcherSettings.cpp b/scenesw/SceneSwitcherSettings.cpp new file mode 100644 index 00000000..2185b815 --- /dev/null +++ b/scenesw/SceneSwitcherSettings.cpp @@ -0,0 +1,489 @@ +/******************************************************************************** + Copyright (C) 2013 Christophe Jeannin + Eric Bataille + + 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. +********************************************************************************/ + +#include "scenesw.h" + +SceneSwitcherSettings::SceneSwitcherSettings(SceneSwitcher *thePlugin, OBSHOTKEYPROC ToggleHotkeyProc): + SettingsPane(), + thePlugin(thePlugin), + ToggleHotkeyProc(ToggleHotkeyProc) +{ + pChange = false; +} + +SceneSwitcherSettings::~SceneSwitcherSettings() +{ +} + +CTSTR SceneSwitcherSettings::GetCategory() const +{ + return PluginStr("Plugin.SettingsName"); +} + +HWND SceneSwitcherSettings::CreatePane(HWND parentHwnd) +{ + hwnd = CreateDialogParam(thePlugin->hinstDll, MAKEINTRESOURCE(IDD_SETTINGS_SCENESW), + parentHwnd, (DLGPROC)DialogProc, (LPARAM)this); + return hwnd; +} + +void SceneSwitcherSettings::DestroyPane() +{ + DestroyWindow(hwnd); + hwnd = NULL; +} + +INT_PTR SceneSwitcherSettings::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) + { + case WM_INITDIALOG: + MsgInitDialog(); + return TRUE; + case WM_COMMAND: + return MsgClicked(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); + case WM_CTLCOLORSTATIC: + if(GetWindowLong((HWND)lParam, GWL_ID) == IDC_RUN) + { + HDC hdc = (HDC)wParam; + SetTextColor(hdc, thePlugin->IsRunning() ? RGB(0,255,0) : RGB(255,0,0)); + SetBkColor(hdc, GetSysColor(COLOR_3DFACE)); + return (INT_PTR)GetSysColorBrush(COLOR_3DFACE); + } + break; + case WM_NOTIFY: + switch (LOWORD(wParam)) { + case IDC_WSMAP: + { + const NMITEMACTIVATE* lpnmitem = (LPNMITEMACTIVATE)lParam; + if(lpnmitem->hdr.idFrom == IDC_WSMAP && lpnmitem->hdr.code == NM_CLICK) + { + const int sel = lpnmitem->iItem; + if(sel >= 0) + { + HWND wsMap = GetDlgItem(hwnd, IDC_WSMAP); + HWND hwndAppList = GetDlgItem(hwnd, IDC_APPLIST); + HWND hwndMainScn = GetDlgItem(hwnd, IDC_MAINSCN); + + // Get the text from the item + String wnd; + wnd.SetLength(256); + ListView_GetItemText(wsMap, sel, 0, wnd, 256); + String scn; + scn.SetLength(256); + ListView_GetItemText(wsMap, sel, 1, scn, 256); + + // Set the combos + SetWindowText(hwndAppList, wnd); + SendMessage(hwndMainScn, CB_SETCURSEL, SendMessage(hwndMainScn, CB_FINDSTRINGEXACT, -1, (LPARAM)scn.Array()), 0); + } + } + return TRUE; + } + break; + } + } + return FALSE; +} + +void SceneSwitcherSettings::MsgInitDialog() +{ + LocalizeWindow(hwnd, thePlugin->pluginLocale); + + HWND hwndAppList = GetDlgItem(hwnd, IDC_APPLIST); + HWND hwndMainScn = GetDlgItem(hwnd, IDC_MAINSCN); + HWND hwndAltScn = GetDlgItem(hwnd, IDC_ALTSCN); + HWND hwndWSMap = GetDlgItem(hwnd, IDC_WSMAP); + HWND hwndSwButton = GetDlgItem(hwnd, IDC_ALTSWITCH); + HWND hwndNoswButton = GetDlgItem(hwnd, IDC_ALTNOSWITCH); + HWND hwndCurrent = GetWindow(GetDesktopWindow(), GW_CHILD); // The top child of the desktop + + // let's fill the listcontrol + SendMessage(hwndWSMap, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + LVCOLUMN col1; + col1.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; + col1.fmt = LVCFMT_RIGHT | LVCFMT_FIXED_WIDTH; + col1.cx = 307; + col1.pszText = (LPWSTR)PluginStr("Settings.WindowTitle"); + LVCOLUMN col2; + col2.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; + col2.fmt = LVCFMT_LEFT | LVCFMT_FIXED_WIDTH; + col2.cx = 307; + col2.pszText = (LPWSTR)PluginStr("Settings.Scene"); + SendMessage(hwndWSMap, LVM_INSERTCOLUMN, 0, (LPARAM) (LPLVCOLUMN) &col1); + SendMessage(hwndWSMap, LVM_INSERTCOLUMN, 1, (LPARAM) (LPLVCOLUMN) &col2); + // Add the items + for (int i = 0; i < thePlugin->GetnWindowsDefined(); i++) + { + String window = thePlugin->GetWindow(i); + String scene = thePlugin->GetScene(i); + LVITEM item; + item.iItem = 0; + item.iSubItem = 0; + item.mask = LVIF_TEXT; + item.pszText = window; + + LVITEM subItem; + subItem.iItem = 0; + subItem.iSubItem = 1; + subItem.mask = LVIF_TEXT; + subItem.pszText = scene; + + SendMessage(hwndWSMap, LVM_INSERTITEM, 0, (LPARAM) &item); + SendMessage(hwndWSMap, LVM_SETITEM, 0, (LPARAM) &subItem); + } + // Set the radio buttons and alt scene combo state + SendMessage(hwndSwButton, BM_SETCHECK, (thePlugin->IsAltDoSwitch() ? BST_CHECKED : BST_UNCHECKED), 0); + SendMessage(hwndNoswButton, BM_SETCHECK, (thePlugin->IsAltDoSwitch() ? BST_UNCHECKED : BST_CHECKED), 0); + EnableWindow(hwndAltScn, thePlugin->IsAltDoSwitch()); + + if(thePlugin->IsMatchExact()) // Match exact window name checkbox + CheckDlgButton(hwnd, IDC_EXACT, BST_CHECKED); + + do + { + if(IsWindowVisible(hwndCurrent)) + { + // Get the styles for the window + DWORD exStyles = (DWORD)GetWindowLongPtr(hwndCurrent, GWL_EXSTYLE); + DWORD styles = (DWORD)GetWindowLongPtr(hwndCurrent, GWL_STYLE); + + if( (exStyles & WS_EX_TOOLWINDOW) == 0 && (styles & WS_CHILD) == 0) + { + // The window is not a toolwindow, and not a child window + String strWindowName; + + // Get the name of the window + strWindowName.SetLength(GetWindowTextLength(hwndCurrent)); + GetWindowText(hwndCurrent, strWindowName, strWindowName.Length()+1); + // Add the Name of the window to the appList + const int id = (int)SendMessage(hwndAppList, CB_ADDSTRING, 0, (LPARAM)strWindowName.Array()); + // Set the data for the added item to be the window handle + SendMessage(hwndAppList, CB_SETITEMDATA, id, (LPARAM)hwndCurrent); + } + } + } // Move down the windows in z-order + while (hwndCurrent = GetNextWindow(hwndCurrent, GW_HWNDNEXT)); + + // Get the list of scenes from OBS + XElement* scnList = OBSGetSceneListElement(); + if(scnList) + { + const DWORD numScn = scnList->NumElements(); + for(DWORD i=0; iGetElementByID(i))->GetName(); + // Add the scene name to both scene lists + SendMessage(hwndMainScn, CB_ADDSTRING, 0, (LPARAM)sceneName); + SendMessage(hwndAltScn, CB_ADDSTRING, 0, (LPARAM)sceneName); + } + } + + // Set the selected list items to be the ones from settings + SendMessage(hwndMainScn, CB_SETCURSEL, SendMessage(hwndMainScn, CB_FINDSTRINGEXACT, -1, (LPARAM)thePlugin->GetmainSceneName()), 0); + SendMessage(hwndAltScn, CB_SETCURSEL, SendMessage(hwndAltScn, CB_FINDSTRINGEXACT, -1, (LPARAM)thePlugin->GetaltSceneName()), 0); + SendMessage(hwndAppList, CB_SETCURSEL, SendMessage(hwndAppList, CB_FINDSTRINGEXACT, -1, (LPARAM)thePlugin->GetmainWndName()), 0); + + // Set the frequency from the settings + SetDlgItemInt(hwnd, IDC_FREQ, thePlugin->GettimeToSleep(), FALSE); + + // Set the autostart checkbox value from the settings + if(thePlugin->IsStartAuto()) + CheckDlgButton(hwnd, IDC_STARTAUTO, BST_CHECKED); + + // Set the toggle hotkey control + SendMessage(GetDlgItem(hwnd, IDC_TOGGLEHOTKEY), HKM_SETHOTKEY, thePlugin->GetToggleHotkey(), 0); + + // If the plugin is running, update the text values + if(thePlugin->IsRunning()) + { + SetWindowText(GetDlgItem(hwnd, IDC_RUN), PluginStr("Settings.Running")); + SetWindowText(GetDlgItem(hwnd, IDC_STOP), PluginStr("Settings.Stop")); + } +} + +INT_PTR SceneSwitcherSettings::MsgClicked(int controlId, int code, HWND controlHwnd) +{ + switch(controlId) + { + case IDC_CLEAR_HOTKEY: + if(code == BN_CLICKED) { + SendMessage(GetDlgItem(hwnd, IDC_TOGGLEHOTKEY), HKM_SETHOTKEY, 0, 0); + SetChangedSettings(pChange = true); + return TRUE; + } + break; + + case IDC_STOP: + if(code == BN_CLICKED) // Stop button clicked + { + if(thePlugin->IsRunning()) + thePlugin->StopThread(hwnd); + else + { + ApplyConfig(hwnd); + pChange = false; + thePlugin->StartThread(hwnd); + } + SetChangedSettings(pChange); + return TRUE; + } + break; + + case IDUP: + { + HWND wsMap = GetDlgItem(hwnd, IDC_WSMAP); + const int sel = SendMessage(wsMap, LVM_GETSELECTIONMARK, 0, 0); + if (sel > 0) + { + // Get the text from the item + String wnd; + wnd.SetLength(256); + ListView_GetItemText(wsMap, sel, 0, wnd, 256); + String scn; + scn.SetLength(256); + ListView_GetItemText(wsMap, sel, 1, scn, 256); + + // Delete it + SendMessage(wsMap, LVM_DELETEITEM, sel, 0); + + // Add it above + LVITEM lv1; + lv1.mask = LVIF_TEXT; + lv1.iItem = sel - 1; + lv1.iSubItem = 0; + lv1.pszText = wnd; + LVITEM lv2; + lv2.mask = LVIF_TEXT; + lv2.iItem = sel - 1; + lv2.iSubItem = 1; + lv2.pszText = scn; + SendMessage(wsMap, LVM_INSERTITEM, sel - 1, (LPARAM) &lv1); + SendMessage(wsMap, LVM_SETITEM, sel - 1, (LPARAM) &lv2); + + // Update the selection mark + SendMessage(wsMap, LVM_SETSELECTIONMARK, 0, sel - 1); + SetChangedSettings(pChange = true); + return TRUE; + } + break; + } + + + case IDDOWN: + { + HWND wsMap = GetDlgItem(hwnd, IDC_WSMAP); + const int sel = SendMessage(wsMap, LVM_GETSELECTIONMARK, 0, 0); + const int max = SendMessage(wsMap, LVM_GETITEMCOUNT, 0, 0) - 1; + if (sel > -1 && sel < max) + { + // Get the text from the item + String wnd; + wnd.SetLength(256); + ListView_GetItemText(wsMap, sel, 0, wnd, 256); + String scn; + scn.SetLength(256); + ListView_GetItemText(wsMap, sel, 1, scn, 256); + + // Delete it + SendMessage(wsMap, LVM_DELETEITEM, sel, 0); + + // Add it below + LVITEM lv1; + lv1.mask = LVIF_TEXT; + lv1.iItem = sel + 1; + lv1.iSubItem = 0; + lv1.pszText = wnd; + LVITEM lv2; + lv2.mask = LVIF_TEXT; + lv2.iItem = sel + 1; + lv2.iSubItem = 1; + lv2.pszText = scn; + SendMessage(wsMap, LVM_INSERTITEM, sel + 1, (LPARAM) &lv1); + SendMessage(wsMap, LVM_SETITEM, sel + 1, (LPARAM) &lv2); + + // Update the selection mark + SendMessage(wsMap, LVM_SETSELECTIONMARK, 0, sel + 1); + SetChangedSettings(pChange = true); + return TRUE; + } + break; + } + + case IDADD: + { + HWND wsMap = GetDlgItem(hwnd, IDC_WSMAP); + HWND appList = GetDlgItem(hwnd, IDC_APPLIST); + HWND scnList = GetDlgItem(hwnd, IDC_MAINSCN); + + String wnd = GetEditText(appList); + // First column + LVITEM lv1; + lv1.mask = LVIF_TEXT; + lv1.iItem = 0; + lv1.iSubItem = 0; + lv1.pszText = wnd; + // Second column + String scn = GetCBText(scnList, CB_ERR); + LVITEM lv2; + lv2.mask = LVIF_TEXT; + lv2.iItem = 0; + lv2.iSubItem = 1; + lv2.pszText = scn; + // Add first column then set second + SendMessage(wsMap, LVM_INSERTITEM, 0, (LPARAM)&lv1); + SendMessage(wsMap, LVM_SETITEM, 0, (LPARAM)&lv2); + SetChangedSettings(pChange = true); + return TRUE; + } + break; + + case IDREM: + { + // Remove the item + HWND wsMap = GetDlgItem(hwnd, IDC_WSMAP); + const int sel = SendMessage(wsMap, LVM_GETSELECTIONMARK, 0, 0); + if (sel > -1) + SendMessage(wsMap, LVM_DELETEITEM, sel, 0); + + SetChangedSettings(pChange = true); + return TRUE; + } + break; + + case IDC_ALTSWITCH: + case IDC_ALTNOSWITCH: + if (code == BN_CLICKED) + { + HWND swButton = GetDlgItem(hwnd, IDC_ALTSWITCH); + HWND altCombo = GetDlgItem(hwnd, IDC_ALTSCN); + const bool swChecked = (SendMessage(swButton, BM_GETSTATE, 0, 0) & BST_CHECKED) != 0; + EnableWindow(altCombo, swChecked); + pChange = pChange || (swChecked != thePlugin->IsAltDoSwitch()); + SetChangedSettings(pChange); + return TRUE; + } + break; + + case IDC_STARTAUTO: + { + HWND control = GetDlgItem(hwnd, IDC_STARTAUTO); + bool newState = (SendMessage(control, BM_GETSTATE, 0, 0) & BST_CHECKED) != 0; + pChange = pChange || (newState != thePlugin->IsStartAuto()); + SetChangedSettings(pChange); + return TRUE; + } + break; + case IDC_EXACT: + { + HWND control = GetDlgItem(hwnd, IDC_EXACT); + bool newState = (SendMessage(control, BM_GETSTATE, 0, 0) & BST_CHECKED) != 0; + pChange = pChange || (newState != thePlugin->IsMatchExact()); + SetChangedSettings(pChange); + return TRUE; + } + break; + case IDC_TOGGLEHOTKEY: + if (code == EN_CHANGE) { + SetChangedSettings(pChange = true); + return TRUE; + } + break; + case IDC_FREQ: + if(code == EN_CHANGE) + { + DWORD newFreq = GetDlgItemInt(hwnd, IDC_FREQ, NULL, FALSE); + DWORD oldFreq = thePlugin->GettimeToSleep(); + pChange = pChange || newFreq != oldFreq; + SetChangedSettings(pChange); + return TRUE; + } + break; + case IDC_APPLIST: + case IDC_MAINSCN: + if (code == CBN_SELCHANGE || code == CBN_EDITCHANGE) { + EditItem(code == CBN_SELCHANGE); + return TRUE; + } + break; + case IDC_ALTSCN: + if (code == CBN_SELCHANGE) { + SetChangedSettings(pChange = true); + return TRUE; + } + break; + } + return FALSE; +} + +void SceneSwitcherSettings::EditItem(bool selChange) { + HWND wsMap = GetDlgItem(hwnd, IDC_WSMAP); + HWND appList = GetDlgItem(hwnd, IDC_APPLIST); + HWND scnList = GetDlgItem(hwnd, IDC_MAINSCN); + + const int sel = SendMessage(wsMap, LVM_GETSELECTIONMARK, 0, 0); + if (sel < 0) return; + + String wnd = selChange ? GetCBText(appList, CB_ERR) : GetEditText(appList); + // First column + LVITEM lv1; + lv1.mask = LVIF_TEXT; + lv1.iItem = sel; + lv1.iSubItem = 0; + lv1.pszText = wnd; + String scn = GetCBText(scnList, CB_ERR); + // Second column + LVITEM lv2; + lv2.mask = LVIF_TEXT; + lv2.iItem = sel; + lv2.iSubItem = 1; + lv2.pszText = scn; + + // Set the text + SendMessage(wsMap, LVM_SETITEM, 0, (LPARAM)&lv1); + SendMessage(wsMap, LVM_SETITEM, 0, (LPARAM)&lv2); + SetChangedSettings(pChange = true); +} + +void SceneSwitcherSettings::ApplyConfig(HWND hWnd) { + thePlugin->ApplyConfig(hWnd); + + // Redefine the hotkey + if (hotkeyID) + OBSDeleteHotkey(hotkeyID); + + if (thePlugin->GetToggleHotkey() != 0) + hotkeyID = OBSCreateHotkey((DWORD)thePlugin->GetToggleHotkey(), ToggleHotkeyProc, 0); +} + +void SceneSwitcherSettings::ApplySettings() +{ + pChange = false; + ApplyConfig(hwnd); +} + +void SceneSwitcherSettings::CancelSettings() +{ + pChange = false; +} + +bool SceneSwitcherSettings::HasDefaults() const +{ + return false; +} \ No newline at end of file diff --git a/scenesw/resource.h b/scenesw/resource.h new file mode 100644 index 00000000..dd777b70 Binary files /dev/null and b/scenesw/resource.h differ diff --git a/scenesw/scenesw.cpp b/scenesw/scenesw.cpp new file mode 100644 index 00000000..52356e8e --- /dev/null +++ b/scenesw/scenesw.cpp @@ -0,0 +1,87 @@ +/******************************************************************************** + Copyright (C) 2013 Christophe Jeannin + Eric Bataille + + 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. +********************************************************************************/ + +#include "scenesw.h" + +extern "C" __declspec(dllexport) bool LoadPlugin(); +extern "C" __declspec(dllexport) bool LoadPluginEx(UINT apiVer); +extern "C" __declspec(dllexport) void UnloadPlugin(); +extern "C" __declspec(dllexport) CTSTR GetPluginName(); +extern "C" __declspec(dllexport) CTSTR GetPluginDescription(); + +HINSTANCE hinstMain = NULL; +SceneSwitcher* thePlugin = NULL; + +void STDCALL HotkeyToggle(DWORD hotkey, UPARAM param, bool bDown) +{ + if (!bDown) { + if (thePlugin->IsRunning()) { + thePlugin->StopThread(); + } else { + thePlugin->StartThread(); + } + } +} + +bool LoadPluginEx(UINT apiVer) +{ + return (apiVer == 0x0103) && LoadPlugin(); +} + +bool LoadPlugin() +{ + InitHotkeyExControl(hinstMain); + thePlugin = new SceneSwitcher(hinstMain, HotkeyToggle); + if (thePlugin == 0) return false; + + if (thePlugin->GetToggleHotkey() != 0) + thePlugin->GetSettings()->hotkeyID = OBSCreateHotkey(thePlugin->GetToggleHotkey(), HotkeyToggle, 0); + + return true; +} + +void UnloadPlugin() +{ + if (thePlugin->GetSettings()->hotkeyID) + OBSDeleteHotkey(thePlugin->GetSettings()->hotkeyID); + + if(thePlugin) + { + delete thePlugin; + thePlugin = NULL; + } +} + +CTSTR GetPluginName() +{ + return PluginStr("Plugin.Name"); +} + +CTSTR GetPluginDescription() +{ + return PluginStr("Plugin.Description"); +} + +BOOL CALLBACK DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpBla) +{ + if(dwReason == DLL_PROCESS_ATTACH) + hinstMain = hInst; + + return TRUE; +} \ No newline at end of file diff --git a/scenesw/scenesw.h b/scenesw/scenesw.h new file mode 100644 index 00000000..a51b1aa8 --- /dev/null +++ b/scenesw/scenesw.h @@ -0,0 +1,25 @@ +/******************************************************************************** + Copyright (C) 2013 Christophe Jeannin + Eric Bataille + + 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 + +#include "OBSApi.h" +#include "SceneSwitcher.h" + +#include "resource.h" diff --git a/scenesw/scenesw.rc b/scenesw/scenesw.rc new file mode 100644 index 00000000..c39f146a Binary files /dev/null and b/scenesw/scenesw.rc differ diff --git a/scenesw/scenesw.vcxproj b/scenesw/scenesw.vcxproj new file mode 100644 index 00000000..e0585b61 --- /dev/null +++ b/scenesw/scenesw.vcxproj @@ -0,0 +1,211 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {6AC307E3-7D59-4DB2-944F-961E299F063A} + Win32Proj + scenesw + + + + DynamicLibrary + true + Unicode + v120 + + + DynamicLibrary + true + Unicode + v120 + + + DynamicLibrary + false + true + Unicode + v120 + + + DynamicLibrary + false + true + Unicode + v120 + + + + + + + + + + + + + + + + + + C:\Program Files (x86)\Windows Kits\8.0\ + $(WindowsSdkDir) + + + true + $(Configuration)\ + $(WindowsSDK80Path)Include\um;$(WindowsSDK80Path)Include\shared;$(DXSDK_DIR)Include;$(IncludePath) + $(WindowsSDK80Path)Lib\win8\um\x86;$(DXSDK_DIR)Lib\x86;$(LibraryPath) + + + true + $(Platform)\$(Configuration)\ + $(WindowsSDK80Path)Include\um;$(WindowsSDK80Path)Include\shared;$(DXSDK_DIR)Include;$(IncludePath) + $(WindowsSDK80Path)Lib\win8\um\x64;$(DXSDK_DIR)Lib\x64;$(LibraryPath) + + + false + $(Configuration)\ + $(WindowsSDK80Path)Include\um;$(WindowsSDK80Path)Include\shared;$(DXSDK_DIR)Include;$(IncludePath) + $(WindowsSDK80Path)Lib\win8\um\x86;$(DXSDK_DIR)Lib\x86;$(LibraryPath) + + + false + $(Platform)\$(Configuration)\ + $(WindowsSDK80Path)Include\um;$(WindowsSDK80Path)Include\shared;$(DXSDK_DIR)Include;$(IncludePath) + $(WindowsSDK80Path)Lib\win8\um\x64;$(DXSDK_DIR)Lib\x64;$(LibraryPath) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SCENESW_EXPORTS;%(PreprocessorDefinitions) + ../OBSApi;%(AdditionalIncludeDirectories) + MultiThreadedDebug + + + Windows + true + ../OBSApi/Debug;%(AdditionalLibraryDirectories) + OBSApi.lib;%(AdditionalDependencies) + ..\rundir\pdb32\$(TargetName).pdb + ..\rundir\pdb32\stripped\$(TargetName).pdb + + + copy $(OutDir)$(ProjectName).dll ..\rundir\plugins + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;SCENESW_EXPORTS;%(PreprocessorDefinitions) + ../OBSApi;%(AdditionalIncludeDirectories) + false + MultiThreadedDebug + + + Windows + true + ../OBSApi/x64/Debug;%(AdditionalLibraryDirectories) + OBSApi.lib;%(AdditionalDependencies) + ..\rundir\pdb64\$(TargetName).pdb + ..\rundir\pdb64\stripped\$(TargetName).pdb + + + copy $(OutDir)$(ProjectName).dll ..\rundir\plugins + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;SCENESW_EXPORTS;%(PreprocessorDefinitions) + ../OBSApi;%(AdditionalIncludeDirectories) + MultiThreaded + /Zo %(AdditionalOptions) + + + Windows + true + true + true + ../OBSApi/Release;%(AdditionalLibraryDirectories) + OBSApi.lib;%(AdditionalDependencies) + ..\rundir\pdb32\$(TargetName).pdb + ..\rundir\pdb32\stripped\$(TargetName).pdb + + + copy $(OutDir)$(ProjectName).dll ..\rundir\plugins + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;SCENESW_EXPORTS;%(PreprocessorDefinitions) + ../OBSApi;%(AdditionalIncludeDirectories) + MultiThreaded + /d2Zi+ %(AdditionalOptions) + + + Windows + true + true + true + OBSApi.lib;%(AdditionalDependencies) + ../OBSApi/x64/Release;%(AdditionalLibraryDirectories) + ..\rundir\pdb64\$(TargetName).pdb + ..\rundir\pdb64\stripped\$(TargetName).pdb + + + copy $(OutDir)$(ProjectName).dll ..\rundir\plugins + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scenesw/scenesw.vcxproj.filters b/scenesw/scenesw.vcxproj.filters new file mode 100644 index 00000000..21cfda46 --- /dev/null +++ b/scenesw/scenesw.vcxproj.filters @@ -0,0 +1,44 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file