Browse Source

add video settings code and set up default video setting values for the config

jp9000 12 năm trước cách đây
mục cha
commit
3d88a43520

+ 5 - 2
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:"

+ 33 - 2
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<MonitorInfo> 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;
 }
 

+ 1 - 1
obs/obs-app.hpp

@@ -32,7 +32,7 @@ class OBSApp : public OBSAppBase {
 	wxFrame *dummyWindow;
 
 	bool InitGlobalConfig();
-	void InitGlobalConfigDefaults();
+	bool InitGlobalConfigDefaults();
 	bool InitConfigDefaults();
 	bool InitLocale();
 

+ 3 - 3
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()

+ 307 - 14
obs/settings-basic-video.cpp

@@ -15,15 +15,37 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
 
+#include <util/lexer.h>
+
 #include "obs-app.hpp"
 #include "settings-basic.hpp"
 #include "window-settings-basic.hpp"
 #include "wx-wrappers.hpp"
+#include "platform.hpp"
+
+#include <sstream>
+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<MonitorInfo> 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);
 }