Skip to content

Instantly share code, notes, and snippets.

@beauwest
Created February 21, 2013 20:52
Show Gist options
  • Save beauwest/5008143 to your computer and use it in GitHub Desktop.
Save beauwest/5008143 to your computer and use it in GitHub Desktop.
/********************************************************************************
Copyright (C) 2013 Christophe Jeannin <chris.j84@free.fr>
Hugh Bailey <obs.jim@gmail.com>
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()
{
timeToSleep = TTS_DEFAULT;
mainHwnd = NULL;
thread = 0;
startAuto = 0;
bKillThread = true;
mainSceneName.Clear();
altSceneName.Clear();
mainWndName.Clear();
String configFile;
configFile << API->GetPluginDataPath() << CONFIGFILENAME;
config.Open(configFile, true);
ReadSettings();
stopReq = CreateEvent(NULL, FALSE, FALSE, NULL);
if(startAuto)
{
mainHwnd = FindWindow(NULL, mainWndName);
StartThread();
}
}
SceneSwitcher::~SceneSwitcher()
{
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"));
if(!timeToSleep)
timeToSleep = TTS_DEFAULT;
else
if(timeToSleep < TTS_MIN) timeToSleep = TTS_MIN;
else if(timeToSleep > TTS_MAX) timeToSleep = TTS_MAX;
}
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);
}
DWORD SceneSwitcher::Run()
{
BOOL isMainScn;
BOOL isMainWnd;
HANDLE timer;
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);
//isMainWnd = (hwndCurrent == mainHwnd);
isMainWnd = (currentWindowText == mainWndName);
isMainScn = (mainSceneName == API->GetSceneName());
if(isMainScn && !isMainWnd)
API->SetScene(altSceneName, true);
else if(!isMainScn && isMainWnd)
API->SetScene(mainSceneName, true);
WaitForMultipleObjects(2, handles, FALSE, INFINITE);
}
CloseHandle(timer);
return 0;
}
void SceneSwitcher::StartThread(HWND hDialog)
{
if(!thread && CheckSettings())
{
bKillThread = false;
thread = CreateThread(NULL, 0, ThreadProc, (LPVOID)this, 0, NULL);
if(hDialog && thread)
{
SetWindowText(GetDlgItem(hDialog, IDC_RUN), TEXT("running"));
SetWindowText(GetDlgItem(hDialog, IDC_STOP), TEXT("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);
}
}
if(thread)
{
CloseHandle(thread);
thread = 0;
}
}
if(hDialog)
{
SetWindowText(GetDlgItem(hDialog, IDC_RUN), TEXT("not running"));
SetWindowText(GetDlgItem(hDialog, IDC_STOP), TEXT("Start"));
}
}
void SceneSwitcher::ApplyConfig(HWND hDialog)
{
if(!hDialog)
return;
HWND hwndMainScn = GetDlgItem(hDialog, IDC_MAINSCN);
HWND hwndAltScn = GetDlgItem(hDialog, IDC_ALTSCN);
HWND hwndAppList = GetDlgItem(hDialog, IDC_APPLIST);
bool needRestart = false;
String newMainSceneName = GetCBText(hwndMainScn, CB_ERR);
String newAltSceneName = GetCBText(hwndAltScn, CB_ERR);
String newMainWndName = GetCBText(hwndAppList, CB_ERR);
HWND newMainHwnd = (HWND)SendMessage(hwndAppList, CB_GETITEMDATA, SendMessage(hwndAppList, CB_GETCURSEL, 0, 0), 0);
DWORD newTimeToSleep = GetDlgItemInt(hDialog, IDC_FREQ, NULL, FALSE);
if(newTimeToSleep < TTS_MIN) newTimeToSleep = TTS_MIN;
else if(newTimeToSleep > TTS_MAX) newTimeToSleep = TTS_MAX;
if(newMainSceneName.IsEmpty() || newAltSceneName.IsEmpty() || newMainWndName.IsEmpty() || (newMainSceneName == newAltSceneName) || !newMainHwnd)
StopThread(hDialog); // if we're applying a bad config stop thread first
if((timeToSleep != newTimeToSleep) && thread)
needRestart = true;
timeToSleep = newTimeToSleep;
mainSceneName = newMainSceneName;
altSceneName = newAltSceneName;
mainWndName = newMainWndName;
mainHwnd = newMainHwnd;
if(IsDlgButtonChecked(hDialog, IDC_STARTAUTO) == BST_CHECKED)
startAuto = 1;
else
startAuto = 0;
if(needRestart)
{
StopThread();
StartThread();
}
WriteSettings();
}
/********************************************************************************
Copyright (C) 2013 Christophe Jeannin <chris.j84@free.fr>
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
#define CONFIGFILENAME TEXT("\\scenesw.ini")
#define TTS_DEFAULT 300
#define TTS_MIN 50
#define TTS_MAX 5000
class SceneSwitcher
{
HWND mainHwnd;
HANDLE thread;
HANDLE stopReq;
DWORD timeToSleep;
String mainSceneName;
String altSceneName;
String mainWndName;
int startAuto;
bool bKillThread;
ConfigFile config;
inline bool CheckSettings(){return (!mainSceneName.IsEmpty() && !altSceneName.IsEmpty() && !mainWndName.IsEmpty() && (mainSceneName != altSceneName));}
void ReadSettings();
void WriteSettings();
DWORD Run();
public:
inline CTSTR GetmainSceneName(){return mainSceneName;}
inline CTSTR GetaltSceneName() {return altSceneName;}
inline CTSTR GetmainWndName() {return mainWndName;}
inline DWORD GettimeToSleep() {return timeToSleep;}
inline bool IsRunning() {return thread!=0;}
inline bool IsStartAuto() {return startAuto!=0;}
static DWORD WINAPI ThreadProc(LPVOID pParam){return static_cast<SceneSwitcher*>(pParam)->Run();}
SceneSwitcher();
~SceneSwitcher();
void StartThread(HWND hDialog = NULL);
void StopThread (HWND hDialog = NULL);
void ApplyConfig(HWND hDialog);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment