diff --git a/OBS.vcxproj b/OBS.vcxproj index d99f5fc3..edc6daf4 100644 --- a/OBS.vcxproj +++ b/OBS.vcxproj @@ -287,6 +287,7 @@ + diff --git a/OBS.vcxproj.filters b/OBS.vcxproj.filters index ac768857..549720a3 100644 --- a/OBS.vcxproj.filters +++ b/OBS.vcxproj.filters @@ -160,6 +160,9 @@ Source + + Source + diff --git a/Source/InstallService.cpp b/Source/InstallService.cpp new file mode 100644 index 00000000..4beaa8e2 --- /dev/null +++ b/Source/InstallService.cpp @@ -0,0 +1,154 @@ +/******************************************************************************** +Copyright (C) 2015 Richard Stanway + +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 "Main.h" + +bool InstallUserService(TCHAR *path) +{ + XConfig serverData; + if (serverData.Open(path)) + { + XElement *services = serverData.GetRootElement(); + if (services) + { + auto numServices = services->NumElements(); + + if (numServices != 1) + return false; + + auto service = services->GetElementByID(0); + if (!service) + return false; + + CTSTR name = service->GetName(); + + auto servers = service->GetElement(TEXT("servers")); + if (!servers || !servers->NumDataItems()) + return false; + + String confirmMessage = FormattedString(Str("InstallServiceConfirm"), name); + confirmMessage.FindReplace(TEXT("$1"), name); + + String uninstallMessage = FormattedString(Str("InstallServiceAlreadyInstalled"), name); + uninstallMessage.FindReplace(TEXT("$1"), name); + + serverData.Close(); + + CTSTR serviceFileName = srchr(path, '\\'); + if (serviceFileName) + serviceFileName++; + else + return false; + + String baseFilename = serviceFileName; + baseFilename.FindReplace(TEXT(".obs-service"), TEXT("")); + + String destination = FormattedString(TEXT("%s\\services\\%s.xconfig"), lpAppDataPath, baseFilename.Array()); + + if (OSFileExists(destination.Array())) + { + if (OBSMessageBox(NULL, uninstallMessage.Array(), L"Open Broadcaster Software", MB_ICONQUESTION | MB_YESNO) == IDYES) + OSDeleteFile(destination.Array()); + return true; + } + + if (OBSMessageBox(NULL, confirmMessage.Array(), L"Open Broadcaster Software", MB_ICONQUESTION | MB_YESNO) == IDYES) + { + if (!OSCopyFile(destination.Array(), path)) + { + OBSMessageBox(NULL, FormattedString(TEXT("Failed to copy service file: error %d"), GetLastError()), L"Open Broadcaster Software", MB_ICONERROR); + return false; + } + else + { + OBSMessageBox(NULL, Str("InstallServiceInstalled"), L"Open Broadcaster Software", MB_ICONINFORMATION); + return true; + } + } + else + return false; + } + else + return false; + } + return false; +} + +void RegisterServiceFileHandler(void) +{ + // the Win32 API seems to be lacking a nice way to register file extensions + // so we just try to register it every time. + + HKEY hk, newKey; + + if (RegOpenCurrentUser(KEY_WRITE, &hk) != ERROR_SUCCESS) + return; + + if (RegCreateKeyEx(hk, L"Software\\Classes\\.obs-service", 0, NULL, 0, KEY_WRITE, NULL, &newKey, NULL) != ERROR_SUCCESS) + { + RegCloseKey(hk); + return; + } + + RegSetValue(newKey, NULL, REG_SZ, L"OpenBroadcasterSoftware", 0); + RegSetValue(newKey, L"Content Type", REG_SZ, L"application/x-obs-service", 0); + RegCloseKey(newKey); + + if (RegCreateKeyEx(hk, L"Software\\Classes\\OpenBroadcasterSoftware\\Content Type", 0, NULL, 0, KEY_WRITE, NULL, &newKey, NULL) != ERROR_SUCCESS) + { + RegCloseKey(hk); + return; + } + + RegSetValue(newKey, NULL, REG_SZ, L"application/x-obs-service", 0); + RegCloseKey(newKey); + + if (RegCreateKeyEx(hk, L"Software\\Classes\\OpenBroadcasterSoftware\\shell", 0, NULL, 0, KEY_WRITE, NULL, &newKey, NULL) != ERROR_SUCCESS) + { + RegCloseKey(hk); + return; + } + + RegSetValue(newKey, NULL, REG_SZ, L"install", 0); + RegCloseKey(newKey); + + if (RegCreateKeyEx(hk, L"Software\\Classes\\OpenBroadcasterSoftware\\shell\\install", 0, NULL, 0, KEY_WRITE, NULL, &newKey, NULL) != ERROR_SUCCESS) + { + RegCloseKey(hk); + return; + } + + RegSetValue(newKey, NULL, REG_SZ, L"Install Service", 0); + RegCloseKey(newKey); + + if (RegCreateKeyEx(hk, L"Software\\Classes\\OpenBroadcasterSoftware\\shell\\install\\command", 0, NULL, 0, KEY_WRITE, NULL, &newKey, NULL) != ERROR_SUCCESS) + { + RegCloseKey(hk); + return; + } + + String modulePath; + modulePath.SetLength(MAX_PATH); + + if (GetModuleFileName(NULL, modulePath, modulePath.Length() - 1)) + RegSetValue(newKey, NULL, REG_SZ, FormattedString(TEXT("\"%s\" -installservice \"%%1\""), modulePath.Array()), 0); + + RegCloseKey(newKey); + RegCloseKey(hk); +} diff --git a/Source/Main.cpp b/Source/Main.cpp index 3911cb6e..8fe64231 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -471,6 +471,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine LPWSTR *args = CommandLineToArgvW(GetCommandLineW(), &numArgs); LPWSTR profile = NULL; LPWSTR sceneCollection = NULL; + LPWSTR userService = NULL; bool bDisableMutex = false; @@ -492,6 +493,14 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if (++i < numArgs) sceneCollection = args[i]; } + else if (scmpi(args[i], L"-installservice") == 0) + { + if (++i < numArgs) + { + bDisableMutex = true; + userService = args[i]; + } + } } //------------------------------------------------------------ @@ -601,6 +610,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine lpAllocator = (TSTR)malloc(size); mcpy(lpAllocator, strAllocator.Array(), size); } + + RegisterServiceFileHandler(); } if(lpAllocator) @@ -615,6 +626,30 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine //EnableMemoryTracking(true, 8961); + //----------------------------------------------------- + // load locale + + if (!locale->LoadStringFile(TEXT("locale/en.txt"))) + AppWarning(TEXT("Could not open locale string file '%s'"), TEXT("locale/en.txt")); + + String strLanguage = GlobalConfig->GetString(TEXT("General"), TEXT("Language"), TEXT("en")); + if (!strLanguage.CompareI(TEXT("en"))) + { + String langFile; + langFile << TEXT("locale/") << strLanguage << TEXT(".txt"); + + if (!locale->LoadStringFile(langFile)) + AppWarning(TEXT("Could not open locale string file '%s'"), langFile.Array()); + } + + // install user service here after we've loaded XT and locale + if (userService) + { + if (!InstallUserService(userService)) + return 1; + return 0; + } + //-------------------------------------------- GlobalConfig->SetString(TEXT("General"), TEXT("LastAppDirectory"), lpAppPath); diff --git a/Source/OBS.cpp b/Source/OBS.cpp index f6cf782c..595549c6 100644 --- a/Source/OBS.cpp +++ b/Source/OBS.cpp @@ -150,21 +150,8 @@ OBS::OBS() InitVolumeControl(hinstMain); InitVolumeMeter(hinstMain); - //----------------------------------------------------- - // load locale - - if(!locale->LoadStringFile(TEXT("locale/en.txt"))) - AppWarning(TEXT("Could not open locale string file '%s'"), TEXT("locale/en.txt")); - + // still need this here for API strLanguage = GlobalConfig->GetString(TEXT("General"), TEXT("Language"), TEXT("en")); - if(!strLanguage.CompareI(TEXT("en"))) - { - String langFile; - langFile << TEXT("locale/") << strLanguage << TEXT(".txt"); - - if(!locale->LoadStringFile(langFile)) - AppWarning(TEXT("Could not open locale string file '%s'"), langFile.Array()); - } //----------------------------------------------------- // load classes diff --git a/Source/OBS.h b/Source/OBS.h index caad5026..4496f1ad 100644 --- a/Source/OBS.h +++ b/Source/OBS.h @@ -556,6 +556,9 @@ std::pair, XElement*> LoadService(const ServiceIdentifi std::pair, XElement*> LoadService(String *failReason=nullptr); ServiceIdentifier GetCurrentService(); +bool InstallUserService(TCHAR *path); +void RegisterServiceFileHandler(void); + //---------------------------- struct StatusBarDrawData diff --git a/Source/SettingsPublish.cpp b/Source/SettingsPublish.cpp index 4ab874c2..7e70aa11 100644 --- a/Source/SettingsPublish.cpp +++ b/Source/SettingsPublish.cpp @@ -543,6 +543,7 @@ INT_PTR SettingsPublish::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) data.mode = mode; //-------------------------------------------- + services.empty(); hwndTemp = GetDlgItem(hwnd, IDC_SERVICE); int itemId = (int)SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("Custom")); @@ -554,6 +555,9 @@ INT_PTR SettingsPublish::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) EnumerateServices([&](ServiceIdentifier sid, XElement *service) { + if (!service) + return true; + services.emplace_back(sid); auto pos = duplicates.find(service->GetName()); int id; diff --git a/rundir/locale/en.txt b/rundir/locale/en.txt index acfc4c96..d896f91e 100644 --- a/rundir/locale/en.txt +++ b/rundir/locale/en.txt @@ -44,6 +44,9 @@ StreamReport="Stream Report" MessageBoxWarningCaption="Warning" NoSourcesFound="You haven't added any sources! Are you sure you want to stream a black screen?" StreamClosePending="Stream or file output unfinished, closing OBS may cause the stream to end prematurely or the file to be corrupted. Do you want to wait another 15 seconds for the output to finish?" +InstallServiceConfirm="Do you want to add streaming service '$1' to the OBS services list?" +InstallServiceAlreadyInstalled="Streaming service '$1' is already installed. Would you like to uninstall it?" +InstallServiceInstalled="The streaming service has been installed. You can find it in Settings / Broadcast Settings." ImportGlobalSourceNameExists="The global source '$1' already exists in the current scene collection." ImportGlobalSources="Import Global Sources"