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