diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 4961960fd..b73be8a3f 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -186,6 +186,9 @@ struct obs_source { signal_handler_t signals; proc_handler_t procs; + /* prevents infinite recursion when enumerating sources */ + int enum_refs; + /* used to indicate that the source has been removed and all * references to it should be released (not exactly how I would prefer * to handle things but it's the best option) */ diff --git a/libobs/obs-scene.c b/libobs/obs-scene.c index b02041230..109383e7d 100644 --- a/libobs/obs-scene.c +++ b/libobs/obs-scene.c @@ -82,6 +82,29 @@ static void scene_destroy(void *data) bfree(scene); } +static void scene_enum_sources(void *data, + obs_source_enum_proc_t enum_callback, + void *param) +{ + struct obs_scene *scene = data; + struct obs_scene_item *item; + + pthread_mutex_lock(&scene->mutex); + + item = scene->first_item; + while (item) { + struct obs_scene_item *next = item->next; + + obs_sceneitem_addref(item); + enum_callback(scene->source, item->source, param); + obs_sceneitem_release(item); + + item = next; + } + + pthread_mutex_unlock(&scene->mutex); +} + static inline void detach_sceneitem(struct obs_scene_item *item) { if (item->prev) @@ -170,6 +193,7 @@ static const struct obs_source_info scene_info = .video_render = scene_video_render, .getwidth = scene_getwidth, .getheight = scene_getheight, + .enum_sources = scene_enum_sources }; obs_scene_t obs_scene_create(const char *name) diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 9d60de213..800b05c0f 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -1162,3 +1162,60 @@ int64_t obs_source_get_sync_offset(obs_source_t source) { return source ? source->sync_offset : 0; } + +struct source_enum_data { + obs_source_enum_proc_t enum_callback; + void *param; +}; + +static void enum_source_tree_callback(obs_source_t parent, obs_source_t child, + void *param) +{ + struct source_enum_data *data = param; + + if (child->info.enum_sources && !child->enum_refs) { + child->enum_refs++; + + child->info.enum_sources(child->data, + enum_source_tree_callback, data); + + child->enum_refs--; + } + + data->enum_callback(parent, child, data->param); +} + +void obs_source_enum_sources(obs_source_t source, + obs_source_enum_proc_t enum_callback, + void *param) +{ + if (!source || !source->info.enum_sources || source->enum_refs) + return; + + obs_source_addref(source); + + source->enum_refs++; + source->info.enum_sources(source->data, enum_callback, param); + source->enum_refs--; + + obs_source_release(source); +} + +void obs_source_enum_tree(obs_source_t source, + obs_source_enum_proc_t enum_callback, + void *param) +{ + struct source_enum_data data = {enum_callback, param}; + + if (!source || !source->info.enum_sources || source->enum_refs) + return; + + obs_source_addref(source); + + source->enum_refs++; + source->info.enum_sources(source->data, enum_source_tree_callback, + &data); + source->enum_refs--; + + obs_source_release(source); +} diff --git a/libobs/obs-source.h b/libobs/obs-source.h index e31e8022a..4b56feb00 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -87,6 +87,9 @@ enum obs_source_type { /** @} */ +typedef void (*obs_source_enum_proc_t)(obs_source_t parent, obs_source_t child, + void *param); + /** * Source definition structure */ @@ -226,6 +229,18 @@ struct obs_source_info { */ struct filtered_audio *(*filter_audio)(void *data, struct filtered_audio *audio); + + /** + * Called to enumerate all sources being used within this source. + * If the source has children it must implement this callback. + * + * @param data Source data + * @param enum_callback Enumeration callback + * @param param User data to pass to callback + */ + void (*enum_sources)(void *data, + obs_source_enum_proc_t enum_callback, + void *param); }; /** diff --git a/libobs/obs.h b/libobs/obs.h index a26685991..5cc527706 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -510,6 +510,16 @@ EXPORT void obs_source_set_sync_offset(obs_source_t source, int64_t offset); /** Gets the audio sync offset (in nanoseconds) for a source */ EXPORT int64_t obs_source_get_sync_offset(obs_source_t source); +/** Enumerates child sources used by this source */ +EXPORT void obs_source_enum_sources(obs_source_t source, + obs_source_enum_proc_t enum_callback, + void *param); + +/** Enumerates the entire child source tree used by this source */ +EXPORT void obs_source_enum_tree(obs_source_t source, + obs_source_enum_proc_t enum_callback, + void *param); + /* ------------------------------------------------------------------------- */ /* Functions used by sources */