From 3d88a4352092d2d2c8fbb7d84e2c1df2a25b3491 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Mon, 16 Dec 2013 00:07:08 -0700 Subject: [PATCH] add video settings code and set up default video setting values for the config --- build/data/obs-studio/locale/en.txt | 7 +- obs/obs-app.cpp | 35 ++- obs/obs-app.hpp | 2 +- obs/settings-basic-general.cpp | 6 +- obs/settings-basic-video.cpp | 321 ++++++++++++++++++++++++++-- 5 files changed, 349 insertions(+), 22 deletions(-) diff --git a/build/data/obs-studio/locale/en.txt b/build/data/obs-studio/locale/en.txt index 5eb58a4e4..4187c2700 100644 --- a/build/data/obs-studio/locale/en.txt +++ b/build/data/obs-studio/locale/en.txt @@ -1,4 +1,4 @@ -Lanuage="English (United States)" +Lanuage="English" OK="OK" Cancel="Cancel" @@ -23,6 +23,8 @@ MainWindow.Volume="Volume:" Settings="Settings" +Settings.StreamRestart="All streaming/recording must be stopped in order for these changes to take effect" + Settings.General="General" Settings.General.Language="Language:" Settings.General.LanguageChanged="The program must be restarted in order to change the language" @@ -32,7 +34,7 @@ Settings.Outputs="Outputs" Settings.Video="Video" Settings.Video.Adapter="Video Adapter:" Settings.Video.BaseRes="Base Resolution:" -Settings.Video.DownscaleRes="Downscale Resolution:" +Settings.Video.DownscaleRes="Output Resolution:" Settings.Video.DownscaleFilter="Downscale Filter:" Settings.Video.DisableAeroWindows="Disable Aero (Windows only)" Settings.Video.FPS="FPS:" @@ -42,6 +44,7 @@ Settings.VIdeo.FPS.Fraction="Frame Interval (fraction)" Settings.Video.FPS.Nanoseconds="Frame Interval (nanoseconds)" Settings.Video.FPS.Numerator="Numerator:" Settings.Video.FPS.Denominator="Denominator:" +Settings.Video.InvalidResolution="Invalid base resolution value. Must be [width]x[height] (i.e. 1920x1080)" Settings.Audio="Audio" Settings.Audio.DesktopAudioDevice="Desktop Audio Device:" diff --git a/obs/obs-app.cpp b/obs/obs-app.cpp index 25b480ee2..ca2288c0e 100644 --- a/obs/obs-app.cpp +++ b/obs/obs-app.cpp @@ -49,13 +49,42 @@ static void do_log(enum log_type type, const char *msg, va_list args) #endif } -void OBSApp::InitGlobalConfigDefaults() +bool OBSApp::InitGlobalConfigDefaults() { config_set_default_string(globalConfig, "General", "Language", "en"); config_set_default_int(globalConfig, "Window", "PosX", -1); config_set_default_int(globalConfig, "Window", "PosY", -1); config_set_default_int(globalConfig, "Window", "SizeX", -1); config_set_default_int(globalConfig, "Window", "SizeY", -1); + + vector monitors; + GetMonitors(monitors); + + if (!monitors.size()) { + OBSErrorBox(NULL, "There appears to be no monitors. Er, this " + "technically shouldn't be possible."); + return false; + } + + uint32_t cx = monitors[0].cx; + uint32_t cy = monitors[0].cy; + + config_set_default_uint(globalConfig, "Video", "BaseCX", cx); + config_set_default_uint(globalConfig, "Video", "BaseCY", cy); + + cx = cx * 10 / 15; + cy = cy * 10 / 15; + config_set_default_uint(globalConfig, "Video", "OutputCX", cx); + config_set_default_uint(globalConfig, "Video", "OutputCY", cy); + + config_set_default_string(globalConfig, "Video", "FPSType", "Common"); + config_set_default_string(globalConfig, "Video", "FPSCommon", "30"); + config_set_default_uint(globalConfig, "Video", "FPSInt", 30); + config_set_default_uint(globalConfig, "Video", "FPSNum", 30); + config_set_default_uint(globalConfig, "Video", "FPSDen", 1); + config_set_default_uint(globalConfig, "Video", "FPSNS", 33333333); + + return true; } static bool do_mkdir(const char *path) @@ -99,7 +128,9 @@ bool OBSApp::InitGlobalConfig() return false; } - InitGlobalConfigDefaults(); + if (!InitGlobalConfigDefaults()) + return false; + return true; } diff --git a/obs/obs-app.hpp b/obs/obs-app.hpp index 8fb12ebce..1c400c0ad 100644 --- a/obs/obs-app.hpp +++ b/obs/obs-app.hpp @@ -32,7 +32,7 @@ class OBSApp : public OBSAppBase { wxFrame *dummyWindow; bool InitGlobalConfig(); - void InitGlobalConfigDefaults(); + bool InitGlobalConfigDefaults(); bool InitConfigDefaults(); bool InitLocale(); diff --git a/obs/settings-basic-general.cpp b/obs/settings-basic-general.cpp index 8cb547741..1eb7b63c5 100644 --- a/obs/settings-basic-general.cpp +++ b/obs/settings-basic-general.cpp @@ -94,15 +94,15 @@ BasicGenData::BasicGenData(OBSBasicSettings *window) NULL, this); - window->generalText->Hide(); + window->generalChangedText->Hide(); } void BasicGenData::LanguageChanged(wxCommandEvent &event) { dataChanged = true; - window->generalText->SetLabel( + window->generalChangedText->SetLabel( WXStr("Settings.General.LanguageChanged")); - window->generalText->Show(); + window->generalChangedText->Show(); } void BasicGenData::Apply() diff --git a/obs/settings-basic-video.cpp b/obs/settings-basic-video.cpp index 4cdba1cf8..36ce69f35 100644 --- a/obs/settings-basic-video.cpp +++ b/obs/settings-basic-video.cpp @@ -15,15 +15,37 @@ along with this program. If not, see . ******************************************************************************/ +#include + #include "obs-app.hpp" #include "settings-basic.hpp" #include "window-settings-basic.hpp" #include "wx-wrappers.hpp" +#include "platform.hpp" + +#include +using namespace std; class BasicVideoData : public BasicSettingsData { ConnectorList connections; + int AddRes(uint32_t cx, uint32_t cy); + void LoadResolutionData(); + void LoadFPSData(); + void LoadFPSCommon(); + void LoadFPSInteger(); + void LoadFPSFraction(); + void LoadFPSNanoseconds(); + void ResetScaleList(uint32_t cx, uint32_t cy); + void BaseResListChanged(wxCommandEvent &event); + void OutputResListChanged(wxCommandEvent &event); + + void SaveFPSData(); + void SaveFPSCommon(); + void SaveFPSInteger(); + void SaveFPSFraction(); + void SaveFPSNanoseconds(); public: BasicVideoData(OBSBasicSettings *window); @@ -31,39 +53,310 @@ public: void Apply(); }; +struct BaseLexer { + lexer lex; +public: + inline BaseLexer() {lexer_init(&lex);} + inline ~BaseLexer() {lexer_free(&lex);} + operator lexer*() {return &lex;} +}; + +/* parses "[width]x[height]", string, i.e. 1024x768 */ +static bool ConvertTextRes(wxComboBox *combo, uint32_t &cx, uint32_t &cy) +{ + string str = combo->GetValue().ToStdString(); + + BaseLexer lex; + lexer_start(lex, str.c_str()); + + base_token token; + + /* parse width */ + if (!lexer_getbasetoken(lex, &token, IGNORE_WHITESPACE)) + return false; + if (token.type != BASETOKEN_DIGIT) + return false; + + cx = std::stoul(token.text.array); + + /* parse 'x' */ + if (!lexer_getbasetoken(lex, &token, IGNORE_WHITESPACE)) + return false; + if (strref_cmpi(&token.text, "x") != 0) + return false; + + /* parse height */ + if (!lexer_getbasetoken(lex, &token, IGNORE_WHITESPACE)) + return false; + if (token.type != BASETOKEN_DIGIT) + return false; + + cy = std::stoul(token.text.array); + + /* shouldn't be any more tokens after this */ + if (lexer_getbasetoken(lex, &token, IGNORE_WHITESPACE)) + return false; + + return true; +} + +int BasicVideoData::AddRes(uint32_t cx, uint32_t cy) +{ + stringstream res; + res << cx << "x" << cy; + return window->baseResList->Append(res.str().c_str()); +} + +void BasicVideoData::LoadResolutionData() +{ + window->baseResList->Clear(); + + uint32_t cx = config_get_uint(GetGlobalConfig(), "Video", "BaseCX"); + uint32_t cy = config_get_uint(GetGlobalConfig(), "Video", "BaseCY"); + + vector monitors; + GetMonitors(monitors); + for (size_t i = 0; i < monitors.size(); i++) + AddRes(monitors[i].cx, monitors[i].cy); + + stringstream res; + res << cx << "x" << cy; + window->baseResList->SetValue(res.str()); + + ResetScaleList(cx, cy); + + cx = config_get_uint(GetGlobalConfig(), "Video", "OutputCX"); + cy = config_get_uint(GetGlobalConfig(), "Video", "OutputCY"); + + res.str(string()); + res.clear(); + res << cx << "x" << cy; + window->outputResList->SetValue(res.str()); +} + +void BasicVideoData::LoadFPSData() +{ + const char *fpsType = config_get_string(GetGlobalConfig(), "Video", + "FPSType"); + + LoadFPSCommon(); + LoadFPSInteger(); + LoadFPSFraction(); + LoadFPSNanoseconds(); + + if (!fpsType) + return; + else if (strcmp(fpsType, "Common") == 0) + window->fpsTypeList->SetSelection(0); + else if (strcmp(fpsType, "Integer") == 0) + window->fpsTypeList->SetSelection(1); + else if (strcmp(fpsType, "Fraction") == 0) + window->fpsTypeList->SetSelection(2); + else if (strcmp(fpsType, "Nanoseconds") == 0) + window->fpsTypeList->SetSelection(3); +} + +void BasicVideoData::LoadFPSCommon() +{ + const char *str = config_get_string(GetGlobalConfig(), "Video", + "FPSCommon"); + + int val = 3; + if (strcmp(str, "10") == 0) + val = 0; + else if (strcmp(str, "20") == 0) + val = 1; + else if (strcmp(str, "29.97") == 0) + val = 2; + else if (strcmp(str, "30") == 0) + val = 3; + else if (strcmp(str, "48") == 0) + val = 4; + else if (strcmp(str, "59.94") == 0) + val = 5; + else if (strcmp(str, "60") == 0) + val = 6; + + window->fpsCommonList->SetSelection(val); +} + +void BasicVideoData::LoadFPSInteger() +{ + window->fpsTypeList->SetSelection(1); + + int val = config_get_int(GetGlobalConfig(), "Video", "FPSInt"); + window->fpsIntegerScroller->SetValue(val); +} + +void BasicVideoData::LoadFPSFraction() +{ + window->fpsTypeList->SetSelection(2); + + int num = config_get_int(GetGlobalConfig(), "Video", "FPSNum"); + int den = config_get_int(GetGlobalConfig(), "Video", "FPSDen"); + + window->fpsNumeratorScroller->SetValue(num); + window->fpsDenominatorScroller->SetValue(den); +} + +void BasicVideoData::LoadFPSNanoseconds() +{ + window->fpsTypeList->SetSelection(3); + + int val = config_get_int(GetGlobalConfig(), "Video", "FPSNS"); + window->fpsNanosecondsScroller->SetValue(val); +} + +/* some nice default output resolution vals */ +static const double vals[] = +{ + 1.0, + 1.25, + (1.0/0.75), + 1.5, + (1.0/0.6), + 1.75, + 2.0, + 2.25, + 2.5, + 2.75, + 3.0 +}; + +static const size_t numVals = sizeof(vals)/sizeof(double); + +void BasicVideoData::ResetScaleList(uint32_t cx, uint32_t cy) +{ + window->outputResList->Clear(); + + for (size_t i = 0; i < numVals; i++) { + stringstream res; + res << uint32_t(double(cx) / vals[i]); + res << "x"; + res << uint32_t(double(cy) / vals[i]); + window->outputResList->Append(res.str().c_str()); + } +} + BasicVideoData::BasicVideoData(OBSBasicSettings *window) : BasicSettingsData(window) { + LoadResolutionData(); + LoadFPSData(); + + /* load connectors after loading data to prevent them from triggering */ connections.Add(window->baseResList, wxEVT_TEXT, wxCommandEventHandler( BasicVideoData::BaseResListChanged), NULL, this); + connections.Add(window->outputResList, wxEVT_TEXT, + wxCommandEventHandler( + BasicVideoData::OutputResListChanged), + NULL, this); - window->baseResList->Clear(); - window->baseResList->Append("640x480"); - window->baseResList->Append("800x600"); - window->baseResList->Append("1024x768"); - window->baseResList->Append("1280x720"); - window->baseResList->Append("1920x1080"); + window->videoChangedText->Hide(); } void BasicVideoData::BaseResListChanged(wxCommandEvent &event) { + uint32_t cx, cy; + if (!ConvertTextRes(window->baseResList, cx, cy)) { + window->videoChangedText->SetLabel( + WXStr("Settings.Video.InvalidResolution")); + window->videoChangedText->Show(); + return; + } + + dataChanged = true; + window->videoChangedText->SetLabel(WXStr("Settings.StreamRestart")); + window->videoChangedText->Show(); + + ResetScaleList(cx, cy); } -void BasicVideoData::Apply() +void BasicVideoData::OutputResListChanged(wxCommandEvent &event) { + uint32_t cx, cy; + if (!ConvertTextRes(window->outputResList, cx, cy)) { + window->videoChangedText->SetLabel( + WXStr("Settings.Video.InvalidResolution")); + window->videoChangedText->Show(); + return; + } + + dataChanged = true; + window->videoChangedText->SetLabel(WXStr("Settings.StreamRestart")); + window->videoChangedText->Show(); } -BasicSettingsData *CreateBasicVideoSettings(OBSBasicSettings *window) +void BasicVideoData::SaveFPSData() +{ + int id = window->fpsTypeList->GetCurrentPage()->GetId(); + + const char *type; + switch (id) { + case ID_FPSPANEL_COMMON: type = "Common"; break; + case ID_FPSPANEL_INTEGER: type = "Integer"; break; + case ID_FPSPANEL_FRACTION: type = "Fraction"; break; + case ID_FPSPANEL_NANOSECONDS: type = "Nanoseconds"; break; + } + + config_set_string(GetGlobalConfig(), "Video", "FPSType", type); + SaveFPSCommon(); + SaveFPSInteger(); + SaveFPSFraction(); + SaveFPSNanoseconds(); +} + +void BasicVideoData::SaveFPSCommon() +{ + int sel = window->fpsCommonList->GetSelection(); + wxString str = window->fpsCommonList->GetString(sel); + + config_set_string(GetGlobalConfig(), "Video", "FPSCommon", str.c_str()); +} + +void BasicVideoData::SaveFPSInteger() +{ + int val = window->fpsIntegerScroller->GetValue(); + + config_set_int(GetGlobalConfig(), "Video", "FPSInt", val); +} + +void BasicVideoData::SaveFPSFraction() +{ + int num = window->fpsNumeratorScroller->GetValue(); + int den = window->fpsDenominatorScroller->GetValue(); + + config_set_int(GetGlobalConfig(), "Video", "FPSNum", num); + config_set_int(GetGlobalConfig(), "Video", "FPSDen", den); +} + +void BasicVideoData::SaveFPSNanoseconds() +{ + int val = window->fpsNanosecondsScroller->GetValue(); + + config_set_int(GetGlobalConfig(), "Video", "FPSNS", val); +} + +void BasicVideoData::Apply() { - BasicSettingsData *data = NULL; + uint32_t cx, cy; - try { - data = new BasicVideoData(window); - } catch (const char *error) { - blog(LOG_ERROR, "CreateBasicVideoSettings failed: %s", error); + if (!ConvertTextRes(window->baseResList, cx, cy)) { + config_set_uint(GetGlobalConfig(), "Video", "BaseCX", cx); + config_set_uint(GetGlobalConfig(), "Video", "BaseCY", cy); } - return data; + if (ConvertTextRes(window->outputResList, cx, cy)) { + config_set_uint(GetGlobalConfig(), "Video", "OutputCX", cx); + config_set_uint(GetGlobalConfig(), "Video", "OutputCY", cy); + } + + SaveFPSData(); +} + +BasicSettingsData *CreateBasicVideoSettings(OBSBasicSettings *window) +{ + return new BasicVideoData(window); } -- GitLab