Fixed crash when only one value per line was, added Scene Round Trip option

This commit is contained in:
WarmUpTill 2016-07-13 00:08:39 +02:00 committed by GitHub
parent 243a41d740
commit 9cd78a403c
5 changed files with 265 additions and 215 deletions

View File

@ -32,17 +32,18 @@ void saveKeybinding(string name, obs_data_array_t *hotkeyData) {
ofstream file;
file.open(string(configPath).append(name), ofstream::trunc);
//hotkeyData = obs_hotkey_save(pauseHotkeyId); //doesnt seem to work in obs_module_unload (hotkey data freed already (<- Jim))
size_t num = obs_data_array_count(hotkeyData);
for (size_t i = 0; i < num; i++) {
string temp = obs_data_get_json(obs_data_array_item(hotkeyData, i));
file << temp;
if (file.is_open()) {
size_t num = obs_data_array_count(hotkeyData);
for (size_t i = 0; i < num; i++) {
string temp = obs_data_get_json(obs_data_array_item(hotkeyData, i));
file << temp;
}
file.close();
}
file.close();
}
}
string loadConfigFile(string filename)
{
string loadConfigFile(string filename) {
ifstream settingsFile;
settingsFile.open(string(configPath).append(filename));
string value;
@ -52,8 +53,8 @@ string loadConfigFile(string filename)
value.reserve(settingsFile.tellg());
settingsFile.seekg(0, ios::beg);
value.assign((istreambuf_iterator<char>(settingsFile)), istreambuf_iterator<char>());
settingsFile.close();
}
settingsFile.close();
return value;
}
@ -70,8 +71,7 @@ void loadKeybinding(string name, obs_data_array_t *hotkeyData, obs_hotkey_id hot
OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("SceneSwitcher", "en-US")
void SceneSwitcherPauseHotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey, bool pressed)
{
void SceneSwitcherPauseHotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey, bool pressed) {
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(hotkey);
@ -91,8 +91,7 @@ void SceneSwitcherPauseHotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey
pauseHotkeyData = obs_hotkey_save(pauseHotkeyId);
}
const char *sceneSwitcherOptionsGetName(void *type_data)
{
const char *sceneSwitcherOptionsGetName(void *type_data) {
UNUSED_PARAMETER(type_data);
return "Scene Switcher Options";
}
@ -104,25 +103,21 @@ void *sceneSwitcherOptionsCreate(obs_data_t *settings, obs_source_t *source) {
void sceneSwitcherOptionsDestroy(void *data) {
UNUSED_PARAMETER(data);
}
uint32_t sceneSwitcherOptionsGetWidth(void *data)
{
uint32_t sceneSwitcherOptionsGetWidth(void *data) {
UNUSED_PARAMETER(data);
return 0;
}
uint32_t sceneSwitcherOptionsGetHeight(void *data)
{
uint32_t sceneSwitcherOptionsGetHeight(void *data) {
UNUSED_PARAMETER(data);
return 0;
}
void sceneSwitcherOptionsSourceGetDefaults(obs_data_t *settings)
{
void sceneSwitcherOptionsSourceGetDefaults(obs_data_t *settings) {
//load settings file
string temp = loadConfigFile("settings.txt");
//set values from file
obs_data_apply(settings, obs_data_create_from_json(temp.c_str()));
}
bool loadOldSettings(obs_properties_t *props, obs_property_t *property, void *data)
{
bool loadOldSettings(obs_properties_t *props, obs_property_t *property, void *data) {
//read old settings
string oldPath = "../../data/obs-plugins/SceneSwitcher/settings.txt";
ifstream oldSettingsFile;
@ -137,8 +132,8 @@ bool loadOldSettings(obs_properties_t *props, obs_property_t *property, void *da
{
getline(oldSettingsFile, line);
if (!line.empty()) {
newFormat += valueBeginning + line + "\"\n" + valueEnd;
}
newFormat += valueBeginning + line + "\"\n" + valueEnd;
}
}
oldSettingsFile.close();
//remove trailing ',' and newline
@ -148,10 +143,11 @@ bool loadOldSettings(obs_properties_t *props, obs_property_t *property, void *da
//check if there are useful new settings
if (newFormat != "{\n\t\"WindowList\": \n\t]\n}") {
//write to new settings file
ofstream file;
file.open(string(configPath).append("settings.txt"));
file << newFormat;
file.close();
ofstream file(string(configPath).append("settings.txt"));
if (file.is_open()) {
file << newFormat;
file.close();
}
//make sure not to overwrite the settings
oldSettingsLoaded = true;
if (switcher->getIsRunning()) {
@ -162,11 +158,10 @@ bool loadOldSettings(obs_properties_t *props, obs_property_t *property, void *da
}
return true;
}
obs_properties_t *sceneSwitcherOptionsSourceGetProperties(void *data)
{
obs_properties_t *sceneSwitcherOptionsSourceGetProperties(void *data) {
UNUSED_PARAMETER(data);
obs_properties_t *props = obs_properties_create();
obs_properties_add_bool(props,"StartMessageDisable","Disable Start Message");
obs_properties_add_bool(props, "StartMessageDisable", "Disable Start Message");
obs_properties_add_editable_list(props,
"WindowList", "",
(enum obs_editable_list_type)0, "",
@ -174,8 +169,7 @@ obs_properties_t *sceneSwitcherOptionsSourceGetProperties(void *data)
obs_properties_add_button(props, "LoadOldSettings", "Load settings from old version of this plugin (restart OBS after clicking this button)", &loadOldSettings);
return props;
}
void sceneSwitcherOptionsSourceSave(void *data, obs_data_t *settings)
{
void sceneSwitcherOptionsSourceSave(void *data, obs_data_t *settings) {
//check if user chose to load old settings
if (oldSettingsLoaded) {
//oldSettingsLoaded = false;
@ -184,16 +178,17 @@ void sceneSwitcherOptionsSourceSave(void *data, obs_data_t *settings)
//hang here if multiple instances of Scene Switcher Options are active (why?)
ofstream settingsFile;
settingsFile.open(string(configPath).append("settings.txt"), ofstream::trunc);
settingsFile << obs_data_get_json(settings);
settingsFile.close();
if (settingsFile.is_open()) {
settingsFile << obs_data_get_json(settings);
settingsFile.close();
}
if (switcher->getIsRunning())
switcher->stop();
switcher->load();
switcher->start();
}
}
void sceneSwitcherOptionsSourceLoad(void *data, obs_data_t *settings)
{
void sceneSwitcherOptionsSourceLoad(void *data, obs_data_t *settings) {
UNUSED_PARAMETER(data);
//load settings file
string temp = loadConfigFile("settings.txt");
@ -201,8 +196,7 @@ void sceneSwitcherOptionsSourceLoad(void *data, obs_data_t *settings)
obs_data_apply(settings, obs_data_create_from_json(temp.c_str()));
}
void sceneSwitcherOptionsSourceSetup()
{
void sceneSwitcherOptionsSourceSetup() {
sceneSwitcherOptionsSource.id = "Scene Switcher Options";
sceneSwitcherOptionsSource.type = OBS_SOURCE_TYPE_INPUT;
sceneSwitcherOptionsSource.get_name = sceneSwitcherOptionsGetName;
@ -212,14 +206,12 @@ void sceneSwitcherOptionsSourceSetup()
sceneSwitcherOptionsSource.get_height = sceneSwitcherOptionsGetHeight;
sceneSwitcherOptionsSource.get_defaults = sceneSwitcherOptionsSourceGetDefaults; //create settings file if not present
sceneSwitcherOptionsSource.get_properties = sceneSwitcherOptionsSourceGetProperties;
sceneSwitcherOptionsSource.save = sceneSwitcherOptionsSourceSave; //save new settings to file
sceneSwitcherOptionsSource.update = sceneSwitcherOptionsSourceSave; //save new settings to file
sceneSwitcherOptionsSource.load = sceneSwitcherOptionsSourceLoad; //read settings file
obs_register_source(&sceneSwitcherOptionsSource);
}
bool obs_module_load(void)
{
bool obs_module_load(void) {
//set config path and check if config dir was set up
configPath = obs_module_config_path("");
boost::filesystem::create_directories(configPath);
@ -246,17 +238,14 @@ void obs_module_unload(void) {
//saveKeybinding(OPTIONS_HOTKEY_NAME, optionsHotkeyData);
}
const char *obs_module_author(void)
{
const char *obs_module_author(void) {
return "WarmUpTill";
}
const char *obs_module_name(void)
{
const char *obs_module_name(void) {
return "Scene Switcher";
}
const char *obs_module_description(void)
{
const char *obs_module_description(void) {
return "Automatic scene switching";
}

View File

@ -19,8 +19,9 @@ void Settings::setSettingsFilePath(string path)
}
void Settings::load() {
//clear settings map
settings = map<string, Data> ();
//reset the settings
settings = map<string, Data>();
sceneRoundTrip = vector<string>();
//read the settings file
vector<string> settingsElements;
ifstream infile(settingsFilePath);
@ -39,59 +40,83 @@ void Settings::load() {
//disable the start message?
if (!startMessageDisableFound) {
pos = line.find("\"StartMessageDisable\": ");
if (pos != line.npos) {
startMessageDisableFound = true;
startMessageDisable = line.find("true") == line.npos ? false : true;
}
if (pos != line.npos) {
startMessageDisableFound = true;
startMessageDisable = line.find("true") == line.npos ? false : true;
}
}
//get switcher info
//read values of the "editable list" UI element
pos = line.find("\"value\":");
if (!line.empty() && pos != string::npos) {
string temp = line.substr(pos + 10, string::npos - 1);
temp.pop_back();
if (!line.empty() && pos != line.npos) {
string temp = line.substr(pos + 10, line.npos - 1);
stringstream lineStream = stringstream(temp);
numValues = 0;
while (lineStream.good()) {
//find Scene Round Trip
if (temp.find("Scene Round Trip") != temp.npos) {
//discard the first value ("Scene Round Trip")
getline(lineStream, value, ',');
settingsElements.push_back(value);
numValues++;
while (lineStream.good()) {
//Scene Round Trip,TriggerSceneHere,DelayHere,NextSceneHere,DelayHere,AnotherSceneHere,DelayHere,...
getline(lineStream, value, ',');
sceneRoundTrip.push_back(value);
}
//remove trailing /" of last value
if (sceneRoundTrip.size() > 0) {
sceneRoundTrip.back().pop_back();
}
if (sceneRoundTrip.size() == 0 || sceneRoundTrip.size() % 2 != 0) {
sceneRoundTrip.push_back("");
}
}
//two values per line are expected
//add missing value
if(numValues < 3) {
settingsElements.push_back("");
}
//discard additional values
for (numValues; numValues > 3; numValues--) {
//find values for Scene switching
else
{
//windowTitle,sceneName,isFullscreenValue
while (lineStream.good()) {
getline(lineStream, value, ',');
settingsElements.push_back(value);
numValues++;
}
//two values per line are expected
//add missing value
if (numValues < 3) {
settingsElements.push_back("");
}
//discard additional values
for (numValues; numValues > 3; numValues--) {
settingsElements.pop_back();
}
//assing to data
Data d = Data();
string isFullscreen = settingsElements.back();
d.isFullscreen = (isFullscreen.find("isFullscreen") != isFullscreen.npos) ? true : false;
//dont remove an element if isFullscreen was not found
if (d.isFullscreen) {
settingsElements.pop_back();
}
string sceneName = settingsElements.back();
d.sceneName = sceneName;
settingsElements.pop_back();
string windowName = settingsElements.back();
settings.insert(pair<string, Data>(windowName, d));
settingsElements.pop_back();
}
//assing to data
Data d = Data();
string isFullscreen = settingsElements.back();
d.isFullscreen = (isFullscreen.find("isFullscreen") == string::npos) ? false : true;
settingsElements.pop_back();
string sceneName = settingsElements.back();
d.sceneName = sceneName;
settingsElements.pop_back();
string windowName = settingsElements.back();
Settings::addToMap(windowName,d);
settingsElements.pop_back();
}
}
infile.close();
}
bool Settings::getStartMessageDisable()
{
bool Settings::getStartMessageDisable(){
return startMessageDisable;
}
void Settings::addToMap(string s1, Data s2) {
settings.insert(pair<string, Data>(s1, s2));
}
map<string, Data> Settings::getMap() {
return settings;
}
vector<string> Settings::getSceneRoundTrip(){
return sceneRoundTrip;
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <map>
#include <vector>
#include <string>
#include <obs-module.h>
@ -11,15 +12,16 @@ struct Data {
};
class Settings {
vector<string> sceneRoundTrip;
map<string, Data> settings;
bool startMessageDisable = false;
public:
void load();
bool getStartMessageDisable();
map<string, Data> getMap();
vector<string> getSceneRoundTrip();
string getSettingsFilePath();
void setSettingsFilePath(string path);
private:
string settingsFilePath = "";
void addToMap(string, Data);
};

View File

@ -7,85 +7,114 @@
#include <regex>
#include "switcher.h"
#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#define NOMINMAX
#include <windows.h>
#endif
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CoreFoundation.h>
#endif
using namespace std;
//scene switching is done in here
void Switcher::switcherThreadFunc() {
bool sceneRoundTripActive = false;
size_t roundTripPos = 0;
bool match = false;
string windowname = "";
string sceneName = "";
bool checkFullscreen = false;
while (isRunning) {
//get active window title
string windowname = GetActiveWindowTitle();
bool match = false;
string name = "";
bool checkFullscreen = false;
//first check if there is a direct match
map<string, Data>::iterator it = settingsMap.find(windowname);
if (it != settingsMap.end()) {
name = it->second.sceneName;
checkFullscreen = it->second.isFullscreen;
match = true;
//get Scene Name
obs_source_t * transitionUsed = obs_get_output_source(0);
obs_source_t * sceneUsed = obs_transition_get_active_source(transitionUsed);
const char *sceneUsedName = obs_source_get_name(sceneUsed);
//check if a Scene Round Trip should be started
if ((sceneUsedName) && strcmp(sceneUsedName, sceneRoundTrip.front().c_str()) == 0) {
sceneRoundTripActive = true;
roundTripPos = 1;
}
else {
for (map<string, Data>::iterator iter = settingsMap.begin(); iter != settingsMap.end(); ++iter)
{
try
{
regex e = regex(iter->first);
match = regex_match(windowname, e);
if (match) {
name = iter->second.sceneName;
checkFullscreen = iter->second.isFullscreen;
break;
}
}
catch (...)
{
}
if (sceneRoundTripActive) {
//get delay and wait
try {
this_thread::sleep_for(chrono::milliseconds(1000 * stoi(sceneRoundTrip.at(roundTripPos), nullptr, 10)));
}
}
//do we only switch if window is also fullscreen?
if (!checkFullscreen || (checkFullscreen && isWindowFullscreen())) {
//do we know the window title or is a fullscreen/backup Scene set?
if (!(settingsMap.find("Backup Scene Name") == settingsMap.end()) || match) {
if (!match && !(settingsMap.find("Backup Scene Name") == settingsMap.end())) {
name = settingsMap.find("Backup Scene Name")->second.sceneName;
}
catch (...) {
//just wait for 3 seconds if value was not set properly
this_thread::sleep_for(chrono::milliseconds(3000));
}
//are we done with the Scene Round trip?
if (roundTripPos + 1 >= sceneRoundTrip.size()) {
sceneRoundTripActive = false;
roundTripPos = 0;
}
else {
//switch scene
sceneName = sceneRoundTrip.at(roundTripPos + 1);
obs_source_t * transitionUsed = obs_get_output_source(0);
obs_source_t * sceneUsed = obs_transition_get_active_source(transitionUsed);
const char *sceneUsedName = obs_source_get_name(sceneUsed);
//check if current scene is already the desired scene
if ((sceneUsedName) && strcmp(sceneUsedName, name.c_str()) != 0) {
//switch scene
obs_source_t *source = obs_get_source_by_name(name.c_str());
if (source == NULL)
{
//warn("Source not found: \"%s\"", name);
;
}
else if (obs_scene_from_source(source) == NULL)
{
//warn("\"%s\" is not a scene", name);
;
}
else {
//create transition to new scene (otherwise UI wont work anymore)
//OBS_TRANSITION_MODE_AUTO uses the obs user settings for transitions
obs_transition_start(transitionUsed, OBS_TRANSITION_MODE_AUTO, 300, source);
}
obs_source_release(source);
obs_source_t *source = obs_get_source_by_name(sceneName.c_str());
if (source != NULL) {
//create transition to new scene
obs_transition_start(transitionUsed, OBS_TRANSITION_MODE_AUTO, 300, source); //OBS_TRANSITION_MODE_AUTO uses the obs user settings for transitions
}
obs_source_release(sceneUsed);
obs_source_release(transitionUsed);
obs_source_release(source);
//prepare for next sceneName,Delay pair
roundTripPos += 2;
}
}
//sleep for a bit
this_thread::sleep_for(chrono::milliseconds(1000));
//normal scene switching here
else {
//get active window title and reset values
windowname = GetActiveWindowTitle();
match = false;
sceneName = "";
checkFullscreen = false;
//first check if there is a direct match
map<string, Data>::iterator it = settingsMap.find(windowname);
if (it != settingsMap.end()) {
sceneName = it->second.sceneName;
checkFullscreen = it->second.isFullscreen;
match = true;
}
else {
//maybe there is a regular expression match
for (map<string, Data>::iterator iter = settingsMap.begin(); iter != settingsMap.end(); ++iter)
{
try {
regex e = regex(iter->first);
match = regex_match(windowname, e);
if (match) {
sceneName = iter->second.sceneName;
checkFullscreen = iter->second.isFullscreen;
break;
}
}
catch (...) {}
}
}
//do we only switch if window is also fullscreen?
if (!checkFullscreen || (checkFullscreen && isWindowFullscreen())) {
//do we know the window title or is a fullscreen/backup Scene set?
if (!(settingsMap.find("Backup Scene Name") == settingsMap.end()) || match) {
if (!match && !(settingsMap.find("Backup Scene Name") == settingsMap.end())) {
sceneName = settingsMap.find("Backup Scene Name")->second.sceneName;
}
//check if current scene is already the desired scene
if ((sceneUsedName) && strcmp(sceneUsedName, sceneName.c_str()) != 0) {
//switch scene
obs_source_t *source = obs_get_source_by_name(sceneName.c_str());
if (source != NULL) {
//create transition to new scene (otherwise UI wont work anymore)
obs_transition_start(transitionUsed, OBS_TRANSITION_MODE_AUTO, 300, source); //OBS_TRANSITION_MODE_AUTO uses the obs user settings for transitions
}
obs_source_release(source);
}
obs_source_release(sceneUsed);
obs_source_release(transitionUsed);
}
}
//sleep for a bit
this_thread::sleep_for(chrono::milliseconds(1000));
}
}
}
@ -93,6 +122,7 @@ void Switcher::switcherThreadFunc() {
void Switcher::firstLoad() {
settings.load();
settingsMap = settings.getMap();
sceneRoundTrip = settings.getSceneRoundTrip();
if (!settings.getStartMessageDisable()) {
string message = "The following settings were found for Scene Switcher:\n";
for (auto it = settingsMap.cbegin(); it != settingsMap.cend(); ++it)
@ -107,33 +137,34 @@ void Switcher::firstLoad() {
#ifdef __APPLE__
void Switcher::firstLoad() {
settings.load();
settingsMap = settings.getMap();
if (!settings.getStartMessageDisable()) {
string message = "The following settings were found for Scene Switcher:\n";
for (auto it = settingsMap.cbegin(); it != settingsMap.cend(); ++it)
{
message += (it->first) + " -> " + it->second.sceneName + "\n";
}
settings.load();
settingsMap = settings.getMap();
sceneRoundTrip = settings.getSceneRoundTrip();
if (!settings.getStartMessageDisable()) {
string message = "The following settings were found for Scene Switcher:\n";
for (auto it = settingsMap.cbegin(); it != settingsMap.cend(); ++it)
{
message += (it->first) + " -> " + it->second.sceneName + "\n";
}
message += "\n(settings file located at: " + settings.getSettingsFilePath() + ")";
SInt32 nRes = 0;
CFUserNotificationRef pDlg = NULL;
const void* keys[] = { kCFUserNotificationAlertHeaderKey,
kCFUserNotificationAlertMessageKey };
const void* vals[] = {
CFSTR("Test Foundation Message Box"),
CFStringCreateWithCString(kCFAllocatorDefault,message.c_str(),kCFStringEncodingMacRoman)
};
CFDictionaryRef dict = CFDictionaryCreate(0, keys, vals,
sizeof(keys)/sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
pDlg = CFUserNotificationCreate(kCFAllocatorDefault, 0,
kCFUserNotificationPlainAlertLevel,
&nRes, dict);
}
SInt32 nRes = 0;
CFUserNotificationRef pDlg = NULL;
const void* keys[] = { kCFUserNotificationAlertHeaderKey,
kCFUserNotificationAlertMessageKey };
const void* vals[] = {
CFSTR("Test Foundation Message Box"),
CFStringCreateWithCString(kCFAllocatorDefault,message.c_str(),kCFStringEncodingMacRoman)
};
CFDictionaryRef dict = CFDictionaryCreate(0, keys, vals,
sizeof(keys) / sizeof(*keys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
pDlg = CFUserNotificationCreate(kCFAllocatorDefault, 0,
kCFUserNotificationPlainAlertLevel,
&nRes, dict);
}
}
#endif
@ -141,6 +172,7 @@ void Switcher::firstLoad() {
//load the settings needed to start the thread
void Switcher::load() {
settings.load();
sceneRoundTrip = settings.getSceneRoundTrip();
settingsMap = settings.getMap();
}
@ -177,37 +209,37 @@ bool Switcher::isWindowFullscreen() {
//get screen resolution
string cmd = "osascript -e 'tell application \"Finder\" to get the bounds of the window of the desktop'";
char resolution[256];
FILE * f1 = popen(cmd.c_str(), "r");
fgets(resolution, 255, f1);
pclose(f1);
string resolutionString = string(resolution);
FILE * f1 = popen(cmd.c_str(), "r");
fgets(resolution, 255, f1);
pclose(f1);
string resolutionString = string(resolution);
//get window resolution
cmd = "osascript "
"-e 'global frontApp, frontAppName, windowTitle, boundsValue' "
"-e 'set windowTitle to \"\"' "
"-e 'tell application \"System Events\"' "
//get window resolution
cmd = "osascript "
"-e 'global frontApp, frontAppName, windowTitle, boundsValue' "
"-e 'set windowTitle to \"\"' "
"-e 'tell application \"System Events\"' "
"-e 'set frontApp to first application process whose frontmost is true' "
"-e 'set frontAppName to name of frontApp' "
"-e 'tell process frontAppName' "
"-e 'tell (1st window whose value of attribute \"AXMain\" is true)' "
"-e 'set windowTitle to value of attribute \"AXTitle\"' "
"-e 'end tell' "
"-e 'tell (1st window whose value of attribute \"AXMain\" is true)' "
"-e 'set windowTitle to value of attribute \"AXTitle\"' "
"-e 'end tell' "
"-e 'end tell' "
"-e 'tell application frontAppName' "
"-e 'end tell' "
"-e 'end tell' "
"-e 'tell application frontAppName' "
"-e 'set boundsValue to bounds of front window' "
"-e 'end tell' "
"-e 'return boundsValue' ";
"-e 'end tell' "
"-e 'return boundsValue' ";
char bounds[256];
FILE * f2 = popen(cmd.c_str(), "r");
fgets(bounds, 255, f2);
pclose(f2);
string boundsString = string(bounds);
FILE * f2 = popen(cmd.c_str(), "r");
fgets(bounds, 255, f2);
pclose(f2);
string boundsString = string(bounds);
return resolutionString.compare(boundsString) == 0;
return resolutionString.compare(boundsString) == 0;
}
#endif
@ -226,28 +258,28 @@ string Switcher::GetActiveWindowTitle()
#ifdef __APPLE__
string Switcher::GetActiveWindowTitle()
{
string cmd = "osascript "
"-e 'global frontApp, frontAppName, windowTitle' "
"-e 'set windowTitle to \"\"' "
"-e 'tell application \"System Events\"' "
string cmd = "osascript "
"-e 'global frontApp, frontAppName, windowTitle' "
"-e 'set windowTitle to \"\"' "
"-e 'tell application \"System Events\"' "
"-e 'set frontApp to first application process whose frontmost is true' "
"-e 'set frontAppName to name of frontApp' "
"-e 'tell process frontAppName' "
"-e 'tell (1st window whose value of attribute \"AXMain\" is true)' "
"-e 'set windowTitle to value of attribute \"AXTitle\"' "
"-e 'end tell' "
"-e 'tell (1st window whose value of attribute \"AXMain\" is true)' "
"-e 'set windowTitle to value of attribute \"AXTitle\"' "
"-e 'end tell' "
"-e 'end tell' "
"-e 'return windowTitle' ";
"-e 'end tell' "
"-e 'end tell' "
"-e 'return windowTitle' ";
char buffer[256];
FILE * f = popen(cmd.c_str(), "r");
fgets(buffer, 255, f);
pclose(f);
//osascript adds carriage return that we need to remove
string windowname = string(buffer);
windowname.pop_back();
return windowname;
char buffer[256];
FILE * f = popen(cmd.c_str(), "r");
fgets(buffer, 255, f);
pclose(f);
//osascript adds carriage return that we need to remove
string windowname = string(buffer);
windowname.pop_back();
return windowname;
}
#endif

View File

@ -1,6 +1,7 @@
#pragma once
#include "settings.h"
#include <map>
#include <vector>
#include <thread>
using namespace std;
@ -20,6 +21,7 @@ private:
bool isRunning = true;
Settings settings;
map<string, Data> settingsMap;
vector<string> sceneRoundTrip;
void switcherThreadFunc();
bool isWindowFullscreen();
string GetActiveWindowTitle();