From 9116be8d9c562c9d62931e4c664af6f79fd44404 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 28 Jan 2014 18:41:24 -0700 Subject: [PATCH] Improve safety for settings usage - Add 'set_default' functions to obs-data.*. These functions ensure that a paramter exists and that the parameter is of a specific type. If not, it will create or overwrite the value with the default setting instead. These functions are meant to be explicitly called before using any of the 'get' functions. The reason why it was designed this way is to encourage defaults to be set in a single place/function. For example, ideal usage is to create one function for your data, "set_my_defaults(obs_data_t data)", set all the default values within that function, and then call that function on create/update, that way all defaults are centralized to a single place. - Ensure that data passed to sources/encoders/outputs/etc is always valid, and not a null value. - While I'm remembering, fix a few defaults of the main program config file data. --- libobs/obs-data.c | 93 ++++++++++++++++++++++++++--------- libobs/obs-data.h | 36 +++++++++----- libobs/obs-encoder.c | 9 ++-- libobs/obs-output.c | 10 ++-- libobs/obs-scene.c | 6 ++- libobs/obs-source.c | 17 +++---- libobs/obs-source.h | 2 +- obs/obs-app.cpp | 2 +- obs/window-basic-settings.cpp | 16 +++--- 9 files changed, 127 insertions(+), 64 deletions(-) diff --git a/libobs/obs-data.c b/libobs/obs-data.c index 497143b4f..f8055b398 100644 --- a/libobs/obs-data.c +++ b/libobs/obs-data.c @@ -298,13 +298,10 @@ static inline struct obs_data_item *get_item_of(struct obs_data *data, return (item && item->type == type) ? item : NULL; } -static void set_item(struct obs_data *data, const char *name, const void *ptr, - size_t size, enum obs_data_type type) +static void set_item_data(struct obs_data *data, struct obs_data_item *item, + const char *name, const void *ptr, size_t size, + enum obs_data_type type) { - if (!data) - return; - - struct obs_data_item *item = get_item(data, name); if (!item) { item = obs_data_item_create(name, ptr, size, type); item->next = data->first_item; @@ -317,6 +314,29 @@ static void set_item(struct obs_data *data, const char *name, const void *ptr, } } +static inline void set_item(struct obs_data *data, const char *name, + const void *ptr, size_t size, enum obs_data_type type) +{ + if (!data) + return; + + struct obs_data_item *item = get_item(data, name); + set_item_data(data, item, name, ptr, size, type); +} + +static inline void set_item_def(struct obs_data *data, const char *name, + const void *ptr, size_t size, enum obs_data_type type) +{ + if (!data) + return; + + struct obs_data_item *item = get_item(data, name); + if (item && item->type == type) + return; + + set_item_data(data, item, name, ptr, size, type); +} + void obs_data_erase(obs_data_t data, const char *name) { struct obs_data_item *item = get_item(data, name); @@ -360,29 +380,56 @@ void obs_data_setarray(obs_data_t data, const char *name, set_item(data, name, &array, sizeof(obs_data_t), OBS_DATA_ARRAY); } -const char *obs_data_getstring(obs_data_t data, const char *name, - const char *def) +void obs_data_set_default_string(obs_data_t data, const char *name, + const char *val) +{ + if (!val) val = ""; + set_item_def(data, name, val, strlen(val)+1, OBS_DATA_STRING); +} + +void obs_data_set_default_int(obs_data_t data, const char *name, long long val) +{ + double f_val = (double)val; + set_item_def(data, name, &f_val, sizeof(double), OBS_DATA_NUMBER); +} + +void obs_data_set_default_double(obs_data_t data, const char *name, double val) +{ + set_item_def(data, name, &val, sizeof(double), OBS_DATA_NUMBER); +} + +void obs_data_set_default_bool(obs_data_t data, const char *name, bool val) +{ + set_item_def(data, name, &val, sizeof(bool), OBS_DATA_BOOLEAN); +} + +void obs_data_set_default_obj(obs_data_t data, const char *name, obs_data_t obj) +{ + set_item_def(data, name, &obj, sizeof(obs_data_t), OBS_DATA_OBJECT); +} + +const char *obs_data_getstring(obs_data_t data, const char *name) { struct obs_data_item *item = get_item_of(data, name, OBS_DATA_STRING); - return item ? get_item_data(item) : def; + return item ? get_item_data(item) : ""; } -long long obs_data_getint(obs_data_t data, const char *name, long long def) +long long obs_data_getint(obs_data_t data, const char *name) { struct obs_data_item *item = get_item_of(data, name, OBS_DATA_NUMBER); - return item ? (long long)*(double*)get_item_data(item) : def; + return item ? (long long)*(double*)get_item_data(item) : 0; } -double obs_data_getdouble(obs_data_t data, const char *name, double def) +double obs_data_getdouble(obs_data_t data, const char *name) { struct obs_data_item *item = get_item_of(data, name, OBS_DATA_NUMBER); - return item ? *(double*)get_item_data(item) : def; + return item ? *(double*)get_item_data(item) : 0.0; } -bool obs_data_getbool(obs_data_t data, const char *name, bool def) +bool obs_data_getbool(obs_data_t data, const char *name) { struct obs_data_item *item = get_item_of(data, name, OBS_DATA_BOOLEAN); - return item ? *(bool*)get_item_data(item) : def; + return item ? *(bool*)get_item_data(item) : false; } obs_data_t obs_data_getobj(obs_data_t data, const char *name) @@ -565,27 +612,27 @@ static inline bool item_valid(struct obs_data_item *item, return item && item->type == type; } -const char *obs_data_item_getstring(obs_data_item_t item, const char *def) +const char *obs_data_item_getstring(obs_data_item_t item) { - return item_valid(item, OBS_DATA_STRING) ? get_item_data(item) : def; + return item_valid(item, OBS_DATA_STRING) ? get_item_data(item) : ""; } -long long obs_data_item_getint(obs_data_item_t item, long long def) +long long obs_data_item_getint(obs_data_item_t item) { return item_valid(item, OBS_DATA_NUMBER) ? - (long long)*(double*)get_item_data(item) : def; + (long long)*(double*)get_item_data(item) : 0; } -double obs_data_item_getdouble(obs_data_item_t item, double def) +double obs_data_item_getdouble(obs_data_item_t item) { return item_valid(item, OBS_DATA_NUMBER) ? - *(double*)get_item_data(item) : def; + *(double*)get_item_data(item) : 0.0; } -bool obs_data_item_getbool(obs_data_item_t item, bool def) +bool obs_data_item_getbool(obs_data_item_t item) { return item_valid(item, OBS_DATA_BOOLEAN) ? - *(bool*)get_item_data(item) : def; + *(bool*)get_item_data(item) : false; } obs_data_t obs_data_item_getobj(obs_data_item_t item) diff --git a/libobs/obs-data.h b/libobs/obs-data.h index b31f9285c..c82463836 100644 --- a/libobs/obs-data.h +++ b/libobs/obs-data.h @@ -69,16 +69,31 @@ EXPORT void obs_data_setobj(obs_data_t data, const char *name, obs_data_t obj); EXPORT void obs_data_setarray(obs_data_t data, const char *name, obs_data_array_t array); +/* + * Default value functions. + * + * These functions check to ensure the value exists, and is of a specific type. + * If not, it sets the default value instead. + */ +EXPORT void obs_data_set_default_string(obs_data_t data, const char *name, + const char *val); +EXPORT void obs_data_set_default_int(obs_data_t data, const char *name, + long long val); +EXPORT void obs_data_set_default_double(obs_data_t data, const char *name, + double val); +EXPORT void obs_data_set_default_bool(obs_data_t data, const char *name, + bool val); +EXPORT void obs_data_set_default_obj(obs_data_t data, const char *name, + obs_data_t obj); + /* * Get functions * NOTE: use a macro if you use 'defaults' in more than one place */ -EXPORT const char *obs_data_getstring(obs_data_t data, const char *name, - const char *def); -EXPORT long long obs_data_getint(obs_data_t data, const char *name, - long long def); -EXPORT double obs_data_getdouble(obs_data_t data, const char *name, double def); -EXPORT bool obs_data_getbool(obs_data_t data, const char *name, bool def); +EXPORT const char *obs_data_getstring(obs_data_t data, const char *name); +EXPORT long long obs_data_getint(obs_data_t data, const char *name); +EXPORT double obs_data_getdouble(obs_data_t data, const char *name); +EXPORT bool obs_data_getbool(obs_data_t data, const char *name); EXPORT obs_data_t obs_data_getobj(obs_data_t data, const char *name); EXPORT obs_data_array_t obs_data_getarray(obs_data_t data, const char *name); @@ -115,11 +130,10 @@ EXPORT void obs_data_item_setobj(obs_data_item_t *item, obs_data_t val); EXPORT void obs_data_item_setarray(obs_data_item_t *item, obs_data_array_t val); /* Item get functions */ -EXPORT const char *obs_data_item_getstring(obs_data_item_t item, - const char *def); -EXPORT long long obs_data_item_getint(obs_data_item_t item, long long def); -EXPORT double obs_data_item_getdouble(obs_data_item_t item, double def); -EXPORT bool obs_data_item_getbool(obs_data_item_t item, bool def); +EXPORT const char *obs_data_item_getstring(obs_data_item_t item); +EXPORT long long obs_data_item_getint(obs_data_item_t item); +EXPORT double obs_data_item_getdouble(obs_data_item_t item); +EXPORT bool obs_data_item_getbool(obs_data_item_t item); EXPORT obs_data_t obs_data_item_getobj(obs_data_item_t item); EXPORT obs_data_array_t obs_data_item_getarray(obs_data_item_t item); diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c index ee15b2441..521e6867f 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -75,15 +75,16 @@ obs_encoder_t obs_encoder_create(const char *id, const char *name, return NULL; } - encoder->data = ei->create(settings, encoder); + encoder->settings = obs_data_newref(settings); + encoder->data = ei->create(encoder->settings, encoder); + if (!encoder->data) { pthread_mutex_destroy(&encoder->data_callbacks_mutex); + obs_data_release(encoder->settings); bfree(encoder); return NULL; } - encoder->settings = obs_data_newref(settings); - pthread_mutex_lock(&obs->data.encoders_mutex); da_push_back(obs->data.encoders, &encoder); pthread_mutex_unlock(&obs->data.encoders_mutex); @@ -106,7 +107,7 @@ void obs_encoder_destroy(obs_encoder_t encoder) void obs_encoder_update(obs_encoder_t encoder, obs_data_t settings) { obs_data_replace(&encoder->settings, settings); - encoder->callbacks.update(encoder->data, settings); + encoder->callbacks.update(encoder->data, encoder->settings); } bool obs_encoder_reset(obs_encoder_t encoder) diff --git a/libobs/obs-output.c b/libobs/obs-output.c index 76fa729af..39a0b8d23 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -58,17 +58,17 @@ obs_output_t obs_output_create(const char *id, const char *name, output = bmalloc(sizeof(struct obs_output)); output->callbacks = *info; - output->data = info->create(settings, output); + output->settings = obs_data_newref(settings); + output->data = info->create(output->settings, output); + if (!output->data) { + obs_data_release(output->settings); bfree(output); return NULL; } output->name = bstrdup(name); - obs_data_addref(settings); - output->settings = settings; - pthread_mutex_lock(&obs->data.outputs_mutex); da_push_back(obs->data.outputs, &output); pthread_mutex_unlock(&obs->data.outputs_mutex); @@ -109,7 +109,7 @@ void obs_output_update(obs_output_t output, obs_data_t settings) obs_data_replace(&output->settings, settings); if (output->callbacks.update) - output->callbacks.update(output->data, settings); + output->callbacks.update(output->data, output->settings); } bool obs_output_canpause(obs_output_t output) diff --git a/libobs/obs-scene.c b/libobs/obs-scene.c index 2a0f0c6ea..74f455163 100644 --- a/libobs/obs-scene.c +++ b/libobs/obs-scene.c @@ -163,11 +163,13 @@ obs_scene_t obs_scene_create(const char *name) return NULL; } - scene = scene_create(NULL, source); + source->settings = obs_data_create(); + scene = scene_create(source->settings, source); source->data = scene; assert(scene); if (!scene) { + obs_data_release(source->settings); bfree(source); return NULL; } @@ -176,7 +178,7 @@ obs_scene_t obs_scene_create(const char *name) source->type = SOURCE_SCENE; scene->source = source; - obs_source_init(source, NULL, &scene_info); + obs_source_init(source, &scene_info); memcpy(&source->callbacks, &scene_info, sizeof(struct source_info)); return scene; } diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 8e9e6052c..b3c8d9081 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -101,8 +101,7 @@ const char *obs_source_getdisplayname(enum obs_source_type type, } /* internal initialization */ -bool obs_source_init(struct obs_source *source, obs_data_t settings, - const struct source_info *info) +bool obs_source_init(struct obs_source *source, const struct source_info *info) { uint32_t flags = info->get_output_flags(source->data); @@ -112,8 +111,6 @@ bool obs_source_init(struct obs_source *source, obs_data_t settings, pthread_mutex_init_value(&source->video_mutex); pthread_mutex_init_value(&source->audio_mutex); - source->settings = obs_data_newref(settings); - memcpy(&source->callbacks, info, sizeof(struct source_info)); if (pthread_mutex_init(&source->filter_mutex, NULL) != 0) @@ -164,13 +161,15 @@ obs_source_t obs_source_create(enum obs_source_type type, const char *id, if (!obs_source_init_handlers(source)) goto fail; - source->name = bstrdup(name); - source->type = type; - source->data = info->create(settings, source); + source->name = bstrdup(name); + source->type = type; + source->settings = obs_data_newref(settings); + source->data = info->create(source->settings, source); + if (!source->data) goto fail; - if (!obs_source_init(source, settings, info)) + if (!obs_source_init(source, info)) goto fail; obs_source_dosignal(source, "source-create"); @@ -278,7 +277,7 @@ void obs_source_update(obs_source_t source, obs_data_t settings) obs_data_replace(&source->settings, settings); if (source->callbacks.update) - source->callbacks.update(source->data, settings); + source->callbacks.update(source->data, source->settings); } void obs_source_activate(obs_source_t source) diff --git a/libobs/obs-source.h b/libobs/obs-source.h index 4f9e85d53..384d18fa2 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -248,7 +248,7 @@ extern bool load_source_info(void *module, const char *module_name, const char *source_name, struct source_info *info); bool obs_source_init_handlers(struct obs_source *source); -extern bool obs_source_init(struct obs_source *source, obs_data_t settings, +extern bool obs_source_init(struct obs_source *source, const struct source_info *info); extern void obs_source_activate(obs_source_t source); diff --git a/obs/obs-app.cpp b/obs/obs-app.cpp index a6e779eb2..4e45ca4de 100644 --- a/obs/obs-app.cpp +++ b/obs/obs-app.cpp @@ -87,7 +87,7 @@ bool OBSApp::InitGlobalConfigDefaults() 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_int(globalConfig, "Video", "FPSType", 0); config_set_default_string(globalConfig, "Video", "FPSCommon", "30"); config_set_default_uint(globalConfig, "Video", "FPSInt", 30); config_set_default_uint(globalConfig, "Video", "FPSNum", 30); diff --git a/obs/window-basic-settings.cpp b/obs/window-basic-settings.cpp index a7c230bb4..a90146f39 100644 --- a/obs/window-basic-settings.cpp +++ b/obs/window-basic-settings.cpp @@ -300,21 +300,21 @@ void OBSBasicSettings::SaveVideoSettings() QT_TO_UTF8(renderer)); if (ConvertResText(QT_TO_UTF8(baseResolution), cx, cy)) { - config_set_int(GetGlobalConfig(), "Video", "BaseCX", cx); - config_set_int(GetGlobalConfig(), "Video", "BaseCY", cy); + config_set_uint(GetGlobalConfig(), "Video", "BaseCX", cx); + config_set_uint(GetGlobalConfig(), "Video", "BaseCY", cy); } if (ConvertResText(QT_TO_UTF8(outputResolution), cx, cy)) { - config_set_int(GetGlobalConfig(), "Video", "OutputCX", cx); - config_set_int(GetGlobalConfig(), "Video", "OutputCY", cy); + config_set_uint(GetGlobalConfig(), "Video", "OutputCX", cx); + config_set_uint(GetGlobalConfig(), "Video", "OutputCY", cy); } - config_set_int(GetGlobalConfig(), "Video", "FPSType", fpsType); + config_set_uint(GetGlobalConfig(), "Video", "FPSType", fpsType); config_set_string(GetGlobalConfig(), "Video", "FPSCommon", QT_TO_UTF8(fpsCommon)); - config_set_int(GetGlobalConfig(), "Video", "FPSInt", fpsInteger); - config_set_int(GetGlobalConfig(), "Video", "FPSNum", fpsNumerator); - config_set_int(GetGlobalConfig(), "Video", "FPSDen", fpsDenominator); + config_set_uint(GetGlobalConfig(), "Video", "FPSInt", fpsInteger); + config_set_uint(GetGlobalConfig(), "Video", "FPSNum", fpsNumerator); + config_set_uint(GetGlobalConfig(), "Video", "FPSDen", fpsDenominator); } void OBSBasicSettings::SaveSettings()