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());
}
}
}