diff --git a/OBS.vcxproj b/OBS.vcxproj index dcb8e31a..ddb204b6 100644 --- a/OBS.vcxproj +++ b/OBS.vcxproj @@ -301,6 +301,7 @@ + diff --git a/OBS.vcxproj.filters b/OBS.vcxproj.filters index a24cea48..97e43b43 100644 --- a/OBS.vcxproj.filters +++ b/OBS.vcxproj.filters @@ -160,6 +160,9 @@ Source + + Source + diff --git a/Source/Main.cpp b/Source/Main.cpp index d5bde1e6..3911cb6e 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -588,6 +588,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if(!OSFileExists(strUpdatePath) && !OSCreateDirectory(strUpdatePath)) CrashError(TEXT("Couldn't create directory '%s'"), strUpdatePath.Array()); + String servicesPath = strAppDataPath + L"\\services"; + if (!OSFileExists(servicesPath) && !OSCreateDirectory(servicesPath)) + CrashError(TEXT("Couldn't create directory '%s'"), servicesPath.Array()); + LoadGlobalIni(); String strAllocator = GlobalConfig->GetString(TEXT("General"), TEXT("Allocator")); diff --git a/Source/OBS.h b/Source/OBS.h index ec4eb259..a8b78d9f 100644 --- a/Source/OBS.h +++ b/Source/OBS.h @@ -16,6 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ********************************************************************************/ +#include #pragma once @@ -521,6 +522,24 @@ struct StreamInfo //---------------------------- +struct ServiceIdentifier +{ + int id; + String file; + + ServiceIdentifier(int id, String file) : id(id), file(file) {} + bool operator==(const ServiceIdentifier &sid) { return id == sid.id && file == sid.file; } + bool operator!=(const ServiceIdentifier &sid) { return !(*this == sid); } +}; + +std::vector LoadServiceIdentifiers(); +void EnumerateServices(std::function); +std::pair, XElement*> LoadService(const ServiceIdentifier&, String *failReason=nullptr); +std::pair, XElement*> LoadService(String *failReason=nullptr); +ServiceIdentifier GetCurrentService(); + +//---------------------------- + struct StatusBarDrawData { UINT bytesPerSec; diff --git a/Source/RTMPPublisher.cpp b/Source/RTMPPublisher.cpp index 652f675e..f90ff527 100644 --- a/Source/RTMPPublisher.cpp +++ b/Source/RTMPPublisher.cpp @@ -830,7 +830,6 @@ DWORD WINAPI RTMPPublisher::CreateConnectionThread(RTMPPublisher *publisher) String failReason; String strBindIP; - int serviceID = AppConfig->GetInt (TEXT("Publish"), TEXT("Service")); String strURL = AppConfig->GetString(TEXT("Publish"), TEXT("URL")); String strPlayPath = AppConfig->GetString(TEXT("Publish"), TEXT("PlayPath")); @@ -851,6 +850,10 @@ DWORD WINAPI RTMPPublisher::CreateConnectionThread(RTMPPublisher *publisher) //-------------------------------- + ServiceIdentifier sid = GetCurrentService(); + + //-------------------------------- + if(!strURL.IsValid()) { failReason = TEXT("No server specified to connect to"); @@ -858,38 +861,15 @@ DWORD WINAPI RTMPPublisher::CreateConnectionThread(RTMPPublisher *publisher) } // A service ID implies the settings have come from the xconfig file. - if(serviceID != 0) + if(sid.id != 0 || sid.file.IsValid()) { - XConfig serverData; - if (!serverData.Open(FormattedString(L"%s\\services.xconfig", API->GetAppPath()))) - { - failReason = TEXT("Could not open services.xconfig"); - goto end; - } - - XElement *services = serverData.GetElement(TEXT("services")); - if(!services) - { - failReason = TEXT("Could not find any services in services.xconfig"); - goto end; - } - - XElement *service = NULL; - DWORD numServices = services->NumElements(); - for(UINT i=0; iGetElementByID(i); - if(curService->GetInt(TEXT("id")) == serviceID) - { - // Found the service in the xconfig file. - service = curService; - break; - } - } + auto serviceData = LoadService(&failReason); + auto service = serviceData.second; if(!service) { - failReason = TEXT("Could not find the service specified in services.xconfig"); + if (failReason.IsEmpty()) + failReason = TEXT("Could not find the service specified in services.xconfig"); goto end; } diff --git a/Source/Service.cpp b/Source/Service.cpp new file mode 100644 index 00000000..76aa3e58 --- /dev/null +++ b/Source/Service.cpp @@ -0,0 +1,188 @@ +/******************************************************************************** + Copyright (C) 2014 Ruwen Hahn + + 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" + +#include + +using namespace std; + +static inline void LoadBuiltinServices(vector &services_) +{ + XConfig serverData; + if (serverData.Open(FormattedString(L"%s\\services.xconfig", API->GetAppPath()))) + { + XElement *services = serverData.GetElement(TEXT("services")); + if (services) + { + auto numServices = services->NumElements(); + + for (decltype(numServices) i = 0; i < numServices; i++) + { + auto service = services->GetElementByID(i); + if (!service) + continue; + + services_.emplace_back(service->GetInt(L"id"), String()); + } + } + } +} + +static inline void LoadUserServices(vector &services) +{ + OSFindData findData; + String servicesDir = FormattedString(L"%s/services/", API->GetAppDataPath()); + if (HANDLE find = OSFindFirstFile(FormattedString(L"%s/*.xconfig", servicesDir.Array()), findData)) + { + do + { + if (findData.bDirectory) + continue; + + XConfig service(servicesDir + findData.fileName); + if (!service.IsOpen()) + continue; + + services.emplace_back(0, findData.fileName); + } while (OSFindNextFile(find, findData)); + + OSFindClose(find); + } +} + +vector LoadServiceIdentifiers() +{ + vector services; + + LoadBuiltinServices(services); + LoadUserServices(services); + + return services; +} + +static inline bool EnumerateBuiltinServices(function &func) +{ + + XConfig serverData; + if (serverData.Open(FormattedString(L"%s\\services.xconfig", API->GetAppPath()))) + { + XElement *services = serverData.GetElement(TEXT("services")); + if (services) + { + auto numServices = services->NumElements(); + + for (decltype(numServices) i = 0; i < numServices; i++) + { + auto service = services->GetElementByID(i); + if (!service) + continue; + + if (!func({ service->GetInt(L"id"), String() }, service)) + return false; + } + } + } + return true; +} + +static inline void EnumerateUserServices(function &func) +{ + OSFindData findData; + String servicesDir = FormattedString(L"%s/services/", API->GetAppDataPath()); + if (HANDLE find = OSFindFirstFile(FormattedString(L"%s/*.xconfig", servicesDir.Array()), findData)) + { + do + { + if (findData.bDirectory) + continue; + + XConfig service(servicesDir + findData.fileName); + if (!service.IsOpen()) + continue; + + func({ 0, findData.fileName }, service.GetElementByID(0)); + } while (OSFindNextFile(find, findData)); + + OSFindClose(find); + } +} + +void EnumerateServices(function func) +{ + if (!EnumerateBuiltinServices(func)) + return; + + EnumerateUserServices(func); +} + +std::pair, XElement*> LoadService(const ServiceIdentifier& sid, String *failReason) +{ + auto fail = [&](CTSTR reason) + { + if (failReason) + *failReason = reason; + return make_pair(std::unique_ptr(), nullptr); + }; + + auto serverData = make_unique(); + + if (sid.file.IsEmpty()) + { + if (!serverData->Open(FormattedString(L"%s\\services.xconfig", API->GetAppPath()))) + return fail(L"Could not open services.xconfig"); + + XElement *services = serverData->GetElement(TEXT("services")); + if (!services) + return fail(L"Could not find any services in services.xconfig"); + + XElement *service = NULL; + auto numServices = services->NumElements(); + for (decltype(numServices) i = 0; i < numServices; i++) + { + XElement *curService = services->GetElementByID(i); + if (!curService) + continue; + + if (curService->GetInt(L"id") == sid.id) + return { move(serverData), curService }; + } + } + else + { + if (serverData->Open(FormattedString(L"%s/services/%s", API->GetAppDataPath(), sid.file.Array()))) + return { move(serverData), serverData->GetElementByID(sid.id) }; + else + return fail(FormattedString(L"Could not open service file '%s'", sid.file.Array())); + } + + return make_pair(std::unique_ptr(), nullptr); +} + +std::pair, XElement*> LoadService(String *failReason) +{ + return LoadService(GetCurrentService(), failReason); +} + +ServiceIdentifier GetCurrentService() +{ + int serviceID = AppConfig->GetInt(L"Publish", L"Service", 0); + String serviceFile = AppConfig->GetString(L"Publish", L"ServiceFile"); + return { serviceID, serviceFile }; +} \ No newline at end of file diff --git a/Source/Settings.h b/Source/Settings.h index e09697f7..e4210da8 100644 --- a/Source/Settings.h +++ b/Source/Settings.h @@ -102,6 +102,7 @@ private: //----------------------------------------------------------------------- // Private members + std::vector services; private: void SetWarningInfo(); diff --git a/Source/SettingsPublish.cpp b/Source/SettingsPublish.cpp index 77e7e706..1283c82d 100644 --- a/Source/SettingsPublish.cpp +++ b/Source/SettingsPublish.cpp @@ -21,7 +21,10 @@ #pragma warning(disable: 4530) #include +#include +#include #include +#include //============================================================================ // Helpers @@ -109,10 +112,11 @@ void SettingsPublish::ApplySettings() AppConfig->SetInt(TEXT("Publish"), TEXT("Mode"), curSel); int serviceID = (int)SendMessage(GetDlgItem(hwnd, IDC_SERVICE), CB_GETCURSEL, 0, 0); - if(serviceID != CB_ERR) + if(serviceID != CB_ERR && serviceID >= 0 && serviceID < (int)services.size()) { - serviceID = (int)SendMessage(GetDlgItem(hwnd, IDC_SERVICE), CB_GETITEMDATA, serviceID, 0); - AppConfig->SetInt(TEXT("Publish"), TEXT("Service"), serviceID); + auto sid = services[serviceID]; + AppConfig->SetInt(TEXT("Publish"), TEXT("Service"), sid.id); + AppConfig->SetString(L"Publish", L"ServiceFile", sid.file); } String strTemp = GetEditText(GetDlgItem(hwnd, IDC_PLAYPATH)); @@ -198,7 +202,7 @@ bool SettingsPublish::HasDefaults() const void SettingsPublish::SetWarningInfo() { - int serviceID = (int)SendMessage(GetDlgItem(hwnd, IDC_SERVICE), CB_GETITEMDATA, SendMessage(GetDlgItem(hwnd, IDC_SERVICE), CB_GETCURSEL, 0, 0), 0); + int serviceID = (int)SendMessage(GetDlgItem(hwnd, IDC_SERVICE), CB_GETCURSEL, 0, 0); bool bUseCBR = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("UseCBR"), 1) != 0; int maxBitRate = AppConfig->GetInt(TEXT("Video Encoding"), TEXT("MaxBitrate"), 1000); @@ -219,135 +223,127 @@ void SettingsPublish::SetWarningInfo() bool canOptimize = false; String strWarnings; - XConfig serverData; - if (serverData.Open(FormattedString(L"%s\\services.xconfig", API->GetAppPath()))) + if (serviceID >= 0 && serviceID < (int)services.size()) { - XElement *services = serverData.GetElement(TEXT("services")); - if(services) + auto serviceData = LoadService(services[serviceID]); + auto service = serviceData.second; + if (service) { - UINT numServices = services->NumElements(); - - for(UINT i=0; iGetInt(TEXT("id")) == serviceID) { - XElement *service = services->GetElementByID(i); - if (service->GetInt(TEXT("id")) == serviceID) + strWarnings = FormattedString(Str("Settings.Publish.Warning.BadSettings"), service->GetName()); + + //check to see if the service we're using has recommendations + if (!service->HasItem(TEXT("recommended"))) { - strWarnings = FormattedString(Str("Settings.Publish.Warning.BadSettings"), service->GetName()); + SetDlgItemText(hwnd, IDC_WARNINGS, TEXT("")); + return; + } - //check to see if the service we're using has recommendations - if (!service->HasItem(TEXT("recommended"))) + XElement *r = service->GetElement(TEXT("recommended")); + + if (r->HasItem(TEXT("ratecontrol"))) + { + CTSTR rc = r->GetString(TEXT("ratecontrol")); + if (!scmp(rc, TEXT("cbr")) && !bUseCBR) { - SetDlgItemText(hwnd, IDC_WARNINGS, TEXT("")); - return; + hasErrors = true; + canOptimize = true; + strWarnings << Str("Settings.Publish.Warning.UseCBR"); } + } - XElement *r = service->GetElement(TEXT("recommended")); - - if (r->HasItem(TEXT("ratecontrol"))) + if (r->HasItem(TEXT("max bitrate"))) + { + int max_bitrate = r->GetInt(TEXT("max bitrate")); + if (maxBitRate > max_bitrate) { - CTSTR rc = r->GetString(TEXT("ratecontrol")); - if (!scmp (rc, TEXT("cbr")) && !bUseCBR) - { - hasErrors = true; - canOptimize = true; - strWarnings << Str("Settings.Publish.Warning.UseCBR"); - } + hasErrors = true; + canOptimize = true; + strWarnings << FormattedString(Str("Settings.Publish.Warning.Maxbitrate"), max_bitrate); } + } - if (r->HasItem(TEXT("max bitrate"))) + if (r->HasItem(L"supported audio codec")) + { + StringList codecs; + r->GetStringList(L"supported audio codec", codecs); + if (codecs.FindValueIndex(currentAudioCodec) == INVALID) { - int max_bitrate = r->GetInt(TEXT("max bitrate")); - if (maxBitRate > max_bitrate) - { - hasErrors = true; - canOptimize = true; - strWarnings << FormattedString(Str("Settings.Publish.Warning.Maxbitrate"), max_bitrate); - } + String msg = Str("Settings.Publish.Warning.UnsupportedAudioCodec"); //good thing OBS only supports MP3 (and AAC), otherwise I'd have to come up with a better translation solution + msg.FindReplace(L"$1", codecs[0].Array()); + msg.FindReplace(L"$2", currentAudioCodec.Array()); + hasErrors = true; + canOptimize = true; + strWarnings << msg; } + } - if (r->HasItem(L"supported audio codec")) + if (r->HasItem(TEXT("max audio bitrate aac")) && (!scmp(currentAudioCodec, TEXT("AAC")))) + { + int maxaudioaac = r->GetInt(TEXT("max audio bitrate aac")); + if (audioBitRate > maxaudioaac) { - StringList codecs; - r->GetStringList(L"supported audio codec", codecs); - if (codecs.FindValueIndex(currentAudioCodec) == INVALID) + hasErrors = true; + canOptimize = true; + strWarnings << FormattedString(Str("Settings.Publish.Warning.MaxAudiobitrate"), maxaudioaac); + } + } + + if (r->HasItem(TEXT("max audio bitrate mp3")) && (!scmp(currentAudioCodec, TEXT("MP3")))) + { + int maxaudiomp3 = r->GetInt(TEXT("max audio bitrate mp3")); + if (audioBitRate > maxaudiomp3) + { + hasErrors = true; + canOptimize = true; + strWarnings << FormattedString(Str("Settings.Publish.Warning.MaxAudiobitrate"), maxaudiomp3); + } + } + + if (r->HasItem(L"video aspect ratio")) + { + String aspectRatio = r->GetString(L"video aspect ratio"); + StringList numbers; + aspectRatio.GetTokenList(numbers, ':'); + if (numbers.Num() == 2) + { + float aspect = numbers[0].ToInt() / max(1.f, numbers[1].ToFloat()); + if (!CloseFloat(aspect, currentAspect)) { - String msg = Str("Settings.Publish.Warning.UnsupportedAudioCodec"); //good thing OBS only supports MP3 (and AAC), otherwise I'd have to come up with a better translation solution - msg.FindReplace(L"$1", codecs[0].Array()); - msg.FindReplace(L"$2", currentAudioCodec.Array()); - hasErrors = true; - canOptimize = true; + String aspectLocalized = Str("Settings.Video.AspectRatioFormat"); + aspectLocalized.FindReplace(L"$1", UIntString(numbers[0].ToInt())); + aspectLocalized.FindReplace(L"$2", UIntString(numbers[1].ToInt())); + + String msg = Str("Settings.Publish.Warning.VideoAspectRatio"); + msg.FindReplace(L"$1", aspectLocalized); strWarnings << msg; - } - } - - if (r->HasItem(TEXT("max audio bitrate aac")) && (!scmp(currentAudioCodec, TEXT("AAC")))) - { - int maxaudioaac = r->GetInt(TEXT("max audio bitrate aac")); - if (audioBitRate > maxaudioaac) - { hasErrors = true; - canOptimize = true; - strWarnings << FormattedString(Str("Settings.Publish.Warning.MaxAudiobitrate"), maxaudioaac); } } + } - if (r->HasItem(TEXT("max audio bitrate mp3")) && (!scmp(currentAudioCodec, TEXT("MP3")))) + if (r->HasItem(TEXT("profile"))) + { + String expectedProfile = r->GetString(TEXT("profile")); + + if (!expectedProfile.CompareI(currentx264Profile)) { - int maxaudiomp3 = r->GetInt(TEXT("max audio bitrate mp3")); - if (audioBitRate > maxaudiomp3) - { - hasErrors = true; - canOptimize = true; - strWarnings << FormattedString(Str("Settings.Publish.Warning.MaxAudiobitrate"), maxaudiomp3); - } + hasErrors = true; + canOptimize = true; + strWarnings << Str("Settings.Publish.Warning.RecommendMainProfile"); } + } - if (r->HasItem(L"video aspect ratio")) + if (r->HasItem(TEXT("keyint"))) + { + int keyint = r->GetInt(TEXT("keyint")); + if (!keyframeInt || keyframeInt * 1000 > keyint) { - String aspectRatio = r->GetString(L"video aspect ratio"); - StringList numbers; - aspectRatio.GetTokenList(numbers, ':'); - if (numbers.Num() == 2) - { - float aspect = numbers[0].ToInt() / max(1.f, numbers[1].ToFloat()); - if (!CloseFloat(aspect, currentAspect)) - { - String aspectLocalized = Str("Settings.Video.AspectRatioFormat"); - aspectLocalized.FindReplace(L"$1", UIntString(numbers[0].ToInt())); - aspectLocalized.FindReplace(L"$2", UIntString(numbers[1].ToInt())); - - String msg = Str("Settings.Publish.Warning.VideoAspectRatio"); - msg.FindReplace(L"$1", aspectLocalized); - strWarnings << msg; - hasErrors = true; - } - } + hasErrors = true; + canOptimize = true; + strWarnings << FormattedString(Str("Settings.Publish.Warning.Keyint"), keyint / 1000); } - - if (r->HasItem(TEXT("profile"))) - { - String expectedProfile = r->GetString(TEXT("profile")); - - if (!expectedProfile.CompareI(currentx264Profile)) - { - hasErrors = true; - canOptimize = true; - strWarnings << Str("Settings.Publish.Warning.RecommendMainProfile"); - } - } - - if (r->HasItem(TEXT("keyint"))) - { - int keyint = r->GetInt(TEXT("keyint")); - if (!keyframeInt || keyframeInt * 1000 > keyint) - { - hasErrors = true; - canOptimize = true; - strWarnings << FormattedString(Str("Settings.Publish.Warning.Keyint"), keyint / 1000); - } - } - - break; } } } @@ -390,32 +386,21 @@ static void UpdateMemoryUsage(HWND hwnd) void SettingsPublish::OptimizeSettings() { auto refresh_on_exit = GuardScope([&] { SetWarningInfo(); UpdateMemoryUsage(hwnd); }); - XConfig serverData; - if (!serverData.Open(FormattedString(L"%s\\services.xconfig", API->GetAppPath()))) + + int serviceID = (int)SendMessage(GetDlgItem(hwnd, IDC_SERVICE), CB_GETCURSEL, 0, 0); + if (serviceID < 0 || serviceID >= (int)services.size()) return; - XElement *services = serverData.GetElement(L"services"); - if (!services) + auto serviceData = LoadService(services[serviceID]); + auto service = serviceData.second; + if (!service) + return; + + //check to see if the service we're using has recommendations + if (!service->HasItem(L"recommended")) return; - UINT numServices = services->NumElements(); - - int serviceID = (int)SendMessage(GetDlgItem(hwnd, IDC_SERVICE), CB_GETITEMDATA, SendMessage(GetDlgItem(hwnd, IDC_SERVICE), CB_GETCURSEL, 0, 0), 0); - XElement *r = nullptr; - for (UINT i = 0; i < numServices; i++) - { - XElement *service = services->GetElementByID(i); - if (service->GetInt(L"id") != serviceID) - continue; - - //check to see if the service we're using has recommendations - if (!service->HasItem(L"recommended")) - return; - - r = service->GetElement(L"recommended"); - break; - } - + XElement *r = service->GetElement(L"recommended"); if (!r) return; @@ -544,27 +529,53 @@ INT_PTR SettingsPublish::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) hwndTemp = GetDlgItem(hwnd, IDC_SERVICE); int itemId = (int)SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("Custom")); SendMessage(hwndTemp, CB_SETITEMDATA, itemId, 0); + services.emplace_back(0, String()); - UINT numServices = 0; - - XConfig serverData; - if (serverData.Open(FormattedString(L"%s\\services.xconfig", API->GetAppPath()))) + ServiceIdentifier current = GetCurrentService(); + std::unordered_map duplicates; + + EnumerateServices([&](ServiceIdentifier sid, XElement *service) { - XElement *services = serverData.GetElement(TEXT("services")); - if(services) + services.emplace_back(sid); + auto pos = duplicates.find(service->GetName()); + int id; + if (pos != end(duplicates)) { - numServices = services->NumElements(); - - for(UINT i=0; isecond]; + if (first.file.IsValid()) { - XElement *service = services->GetElementByID(i); - itemId = (int)SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)service->GetName()); - SendMessage(hwndTemp, CB_SETITEMDATA, itemId, service->GetInt(TEXT("id"))); + SendMessage(hwndTemp, CB_DELETESTRING, pos->second, 0); + SendMessage(hwndTemp, CB_INSERTSTRING, pos->second, (LPARAM)FormattedString(L"%s [%s]", service->GetName(), services[pos->second].file.Array()).Array()); } + id = (int)SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)(sid.file.IsValid() ? FormattedString(L"%s [%s]", service->GetName(), sid.file.Array()).Array() : service->GetName())); + } + else + { + id = (int)SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)service->GetName()); + duplicates[service->GetName()] = id; } - } - int serviceID = AppConfig->GetInt(TEXT("Publish"), TEXT("Service"), 0); + [&]() + { + if (sid != current) + return; + + SendDlgItemMessage(hwnd, IDC_SERVICE, CB_SETCURSEL, id, 0); + + XElement *servers = service->GetElement(L"servers"); + if (!servers) + return; + + UINT numServers = servers->NumDataItems(); + for (UINT i = 0; i < numServers; i++) + { + XDataItem *server = servers->GetDataItemByID(i); + SendMessage(GetDlgItem(hwnd, IDC_SERVERLIST), CB_ADDSTRING, 0, (LPARAM)server->GetName()); + } + + }(); + return true; + }); if(mode != 0) ShowWindow(hwndTemp, SW_HIDE); @@ -574,7 +585,7 @@ INT_PTR SettingsPublish::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) LoadSettingEditString(hwndTemp, TEXT("Publish"), TEXT("PlayPath"), NULL); if(mode != 0) ShowWindow(hwndTemp, SW_HIDE); - if(serviceID == 0) //custom + if(current.file.IsEmpty() && current.id == 0) //custom { ShowWindow(GetDlgItem(hwnd, IDC_SERVERLIST), SW_HIDE); hwndTemp = GetDlgItem(hwnd, IDC_URL); @@ -585,38 +596,6 @@ INT_PTR SettingsPublish::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) { ShowWindow(GetDlgItem(hwnd, IDC_URL), SW_HIDE); hwndTemp = GetDlgItem(hwnd, IDC_SERVERLIST); - - XElement *services = serverData.GetElement(TEXT("services")); - if(services) - { - XElement *service = NULL; - numServices = services->NumElements(); - for(UINT i=0; iGetElementByID(i); - if(curService->GetInt(TEXT("id")) == serviceID) - { - SendDlgItemMessage(hwnd, IDC_SERVICE, CB_SETCURSEL, i+1, 0); - service = curService; - break; - } - } - - if(service) - { - XElement *servers = service->GetElement(TEXT("servers")); - if(servers) - { - UINT numServers = servers->NumDataItems(); - for(UINT i=0; iGetDataItemByID(i); - SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)server->GetName()); - } - } - } - } - LoadSettingComboString(hwndTemp, TEXT("Publish"), TEXT("URL"), NULL); } @@ -937,24 +916,20 @@ INT_PTR SettingsPublish::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam) ShowWindow(hwndTemp, SW_SHOW); SendMessage(hwndTemp, CB_RESETCONTENT, 0, 0); - XConfig serverData; - if (serverData.Open(FormattedString(L"%s\\services.xconfig", API->GetAppPath()))) + if (serviceID >= 0 && serviceID < (int)services.size()) { - XElement *services = serverData.GetElement(TEXT("services")); - if(services) + auto serviceData = LoadService(services[serviceID]); + auto service = serviceData.second; + if (service) { - XElement *service = services->GetElementByID(serviceID-1); - if(service) + XElement *servers = service->GetElement(TEXT("servers")); + if (servers) { - XElement *servers = service->GetElement(TEXT("servers")); - if(servers) + UINT numServers = servers->NumDataItems(); + for (UINT i = 0; i < numServers; i++) { - UINT numServers = servers->NumDataItems(); - for(UINT i=0; iGetDataItemByID(i); - SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)server->GetName()); - } + XDataItem *server = servers->GetDataItemByID(i); + SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)server->GetName()); } } }