From 7920668e562571625a3ff95c78c5403fb4c98ba5 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 15 Sep 2015 22:39:11 -0700 Subject: [PATCH] libobs: Add private data to definition structures This is useful for allowing the ability to have private data associated with the object type definition structures. This private data can be useful for things like plugin wrappers for other languages, or providing dynamically generated object types. --- libobs/obs-encoder.h | 3 +++ libobs/obs-module.c | 53 +++++++++++++++++++++++++++++++++++++------- libobs/obs-output.h | 3 +++ libobs/obs-service.h | 3 +++ libobs/obs-source.h | 10 +++++++++ libobs/obs-ui.h | 6 +++++ libobs/obs.c | 28 ++++++++++++++++------- 7 files changed, 90 insertions(+), 16 deletions(-) diff --git a/libobs/obs-encoder.h b/libobs/obs-encoder.h index 4d894170f..d60e44e40 100644 --- a/libobs/obs-encoder.h +++ b/libobs/obs-encoder.h @@ -223,6 +223,9 @@ struct obs_encoder_info { * @param[in/out] info Video format information */ void (*get_video_info)(void *data, struct video_scale_info *info); + + void *type_data; + void (*free_type_data)(void *type_data); }; EXPORT void obs_register_encoder_s(const struct obs_encoder_info *info, diff --git a/libobs/obs-module.c b/libobs/obs-module.c index 0d1ce245d..16bba313b 100644 --- a/libobs/obs-module.c +++ b/libobs/obs-module.c @@ -478,7 +478,7 @@ cleanup: "(%llu)", \ (long long unsigned)size_var, \ (long long unsigned)sizeof(data));\ - return; \ + goto error; \ } \ \ memcpy(&data, info, size_var); \ @@ -492,10 +492,23 @@ cleanup: blog(LOG_ERROR, "Required value '" #val "' for " \ "'%s' not found. " #func \ " failed.", info->id); \ - return; \ + goto error; \ } \ } while (false) +#define HANDLE_ERROR(size_var, structure, info) \ + do { \ + struct structure data = {0}; \ + if (!size_var) \ + return; \ + \ + memcpy(&data, info, sizeof(data) < size_var ? \ + sizeof(data) : size_var); \ + \ + if (info->type_data && info->free_type_data) \ + info->free_type_data(info->type_data); \ + } while (false) + void obs_register_source_s(const struct obs_source_info *info, size_t size) { struct obs_source_info data = {0}; @@ -510,13 +523,13 @@ void obs_register_source_s(const struct obs_source_info *info, size_t size) } else { blog(LOG_ERROR, "Tried to register unknown source type: %u", info->type); - return; + goto error; } if (find_source(array, info->id)) { blog(LOG_WARNING, "Source d '%s' already exists! " "Duplicate library?", info->id); - return; + goto error; } #define CHECK_REQUIRED_VAL_(info, val, func) \ @@ -538,7 +551,7 @@ void obs_register_source_s(const struct obs_source_info *info, size_t size) "%llu which is more than libobs currently " "supports (%llu)", (long long unsigned)size, (long long unsigned)sizeof(data)); - return; + goto error; } memcpy(&data, info, size); @@ -550,6 +563,10 @@ void obs_register_source_s(const struct obs_source_info *info, size_t size) } darray_push_back(sizeof(struct obs_source_info), array, &data); + return; + +error: + HANDLE_ERROR(size, obs_source_info, info); } void obs_register_output_s(const struct obs_output_info *info, size_t size) @@ -557,7 +574,7 @@ void obs_register_output_s(const struct obs_output_info *info, size_t size) if (find_output(info->id)) { blog(LOG_WARNING, "Output id '%s' already exists! " "Duplicate library?", info->id); - return; + goto error; } #define CHECK_REQUIRED_VAL_(info, val, func) \ @@ -582,6 +599,10 @@ void obs_register_output_s(const struct obs_output_info *info, size_t size) #undef CHECK_REQUIRED_VAL_ REGISTER_OBS_DEF(size, obs_output_info, obs->output_types, info); + return; + +error: + HANDLE_ERROR(size, obs_output_info, info); } void obs_register_encoder_s(const struct obs_encoder_info *info, size_t size) @@ -589,7 +610,7 @@ void obs_register_encoder_s(const struct obs_encoder_info *info, size_t size) if (find_encoder(info->id)) { blog(LOG_WARNING, "Encoder id '%s' already exists! " "Duplicate library?", info->id); - return; + goto error; } #define CHECK_REQUIRED_VAL_(info, val, func) \ @@ -604,6 +625,10 @@ void obs_register_encoder_s(const struct obs_encoder_info *info, size_t size) #undef CHECK_REQUIRED_VAL_ REGISTER_OBS_DEF(size, obs_encoder_info, obs->encoder_types, info); + return; + +error: + HANDLE_ERROR(size, obs_encoder_info, info); } void obs_register_service_s(const struct obs_service_info *info, size_t size) @@ -611,7 +636,7 @@ void obs_register_service_s(const struct obs_service_info *info, size_t size) if (find_service(info->id)) { blog(LOG_WARNING, "Service id '%s' already exists! " "Duplicate library?", info->id); - return; + goto error; } #define CHECK_REQUIRED_VAL_(info, val, func) \ @@ -622,6 +647,10 @@ void obs_register_service_s(const struct obs_service_info *info, size_t size) #undef CHECK_REQUIRED_VAL_ REGISTER_OBS_DEF(size, obs_service_info, obs->service_types, info); + return; + +error: + HANDLE_ERROR(size, obs_service_info, info); } void obs_regsiter_modal_ui_s(const struct obs_modal_ui *info, size_t size) @@ -634,6 +663,10 @@ void obs_regsiter_modal_ui_s(const struct obs_modal_ui *info, size_t size) #undef CHECK_REQUIRED_VAL_ REGISTER_OBS_DEF(size, obs_modal_ui, obs->modal_ui_callbacks, info); + return; + +error: + HANDLE_ERROR(size, obs_modal_ui, info); } void obs_regsiter_modeless_ui_s(const struct obs_modeless_ui *info, size_t size) @@ -647,4 +680,8 @@ void obs_regsiter_modeless_ui_s(const struct obs_modeless_ui *info, size_t size) REGISTER_OBS_DEF(size, obs_modeless_ui, obs->modeless_ui_callbacks, info); + return; + +error: + HANDLE_ERROR(size, obs_modeless_ui, info); } diff --git a/libobs/obs-output.h b/libobs/obs-output.h index 093aef45e..63735fed8 100644 --- a/libobs/obs-output.h +++ b/libobs/obs-output.h @@ -61,6 +61,9 @@ struct obs_output_info { uint64_t (*get_total_bytes)(void *data); int (*get_dropped_frames)(void *data); + + void *type_data; + void (*free_type_data)(void *type_data); }; EXPORT void obs_register_output_s(const struct obs_output_info *info, diff --git a/libobs/obs-service.h b/libobs/obs-service.h index c5b464ae3..a5d5c158d 100644 --- a/libobs/obs-service.h +++ b/libobs/obs-service.h @@ -69,6 +69,9 @@ struct obs_service_info { obs_data_t *video_encoder_settings, obs_data_t *audio_encoder_settings); + void *type_data; + void (*free_type_data)(void *type_data); + /* TODO: more stuff later */ }; diff --git a/libobs/obs-source.h b/libobs/obs-source.h index 649ace284..f20f9d33f 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -372,6 +372,16 @@ struct obs_source_info { * @param source Source that the filter being removed from */ void (*filter_remove)(void *data, obs_source_t *source); + + /** + * Private data associated with this entry + */ + void *type_data; + + /** + * If defined, called to free private data on shutdown + */ + void (*free_type_data)(void *type_data); }; EXPORT void obs_register_source_s(const struct obs_source_info *info, diff --git a/libobs/obs-ui.h b/libobs/obs-ui.h index 111f088ab..f5947b46e 100644 --- a/libobs/obs-ui.h +++ b/libobs/obs-ui.h @@ -65,6 +65,9 @@ struct obs_modal_ui { * @b false if user cancelled the task. */ bool (*exec)(void *object, void *ui_data); + + void *type_data; + void (*free_type_data)(void *type_data); }; /** @@ -101,6 +104,9 @@ struct obs_modeless_ui { * the specific target. */ void *(*create)(void *object, void *ui_data); + + void *type_data; + void (*free_type_data)(void *type_data); }; /** diff --git a/libobs/obs.c b/libobs/obs.c index bc2e8ea44..33612105e 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -752,14 +752,26 @@ void obs_shutdown(void) if (!obs) return; - da_free(obs->input_types); - da_free(obs->filter_types); - da_free(obs->encoder_types); - da_free(obs->transition_types); - da_free(obs->output_types); - da_free(obs->service_types); - da_free(obs->modal_ui_callbacks); - da_free(obs->modeless_ui_callbacks); +#define FREE_REGISTERED_TYPES(structure, list) \ + do { \ + for (size_t i = 0; i < list.num; i++) { \ + struct structure *item = &list.array[i]; \ + if (item->type_data && item->free_type_data) \ + item->free_type_data(item->type_data); \ + } \ + da_free(list); \ + } while (false) + + FREE_REGISTERED_TYPES(obs_source_info, obs->input_types); + FREE_REGISTERED_TYPES(obs_source_info, obs->filter_types); + FREE_REGISTERED_TYPES(obs_source_info, obs->transition_types); + FREE_REGISTERED_TYPES(obs_output_info, obs->output_types); + FREE_REGISTERED_TYPES(obs_encoder_info, obs->encoder_types); + FREE_REGISTERED_TYPES(obs_service_info, obs->service_types); + FREE_REGISTERED_TYPES(obs_modal_ui, obs->modal_ui_callbacks); + FREE_REGISTERED_TYPES(obs_modeless_ui, obs->modeless_ui_callbacks); + +#undef FREE_REGISTERED_TYPES stop_video(); stop_hotkeys();