diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index bdb3600d8..aaf3df066 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -185,6 +185,9 @@ struct obs_source { signal_handler_t signals; proc_handler_t procs; + /* ensures show/hide are only called once */ + int show_refs; + /* ensures activate/deactivate are only called once */ int activate_refs; @@ -241,8 +244,13 @@ bool obs_source_init_handlers(struct obs_source *source); extern bool obs_source_init(struct obs_source *source, const struct obs_source_info *info); -extern void obs_source_activate(obs_source_t source); -extern void obs_source_deactivate(obs_source_t source); +enum view_type { + MAIN_VIEW, + AUX_VIEW +}; + +extern void obs_source_activate(obs_source_t source, enum view_type type); +extern void obs_source_deactivate(obs_source_t source, enum view_type type); extern void obs_source_video_tick(obs_source_t source, float seconds); diff --git a/libobs/obs-source.c b/libobs/obs-source.c index c4d4d33b6..251de22a3 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -123,13 +123,16 @@ bool obs_source_init(struct obs_source *source, } static inline void obs_source_dosignal(struct obs_source *source, - const char *signal) + const char *signal_obs, const char *signal_source) { struct calldata data; calldata_init(&data); calldata_setptr(&data, "source", source); - signal_handler_signal(obs->signals, signal, &data); + if (signal_obs) + signal_handler_signal(obs->signals, signal_obs, &data); + if (signal_source) + signal_handler_signal(source->signals, signal_source, &data); calldata_free(&data); } @@ -159,7 +162,7 @@ obs_source_t obs_source_create(enum obs_source_type type, const char *id, if (!obs_source_init(source, info)) goto fail; - obs_source_dosignal(source, "source-create"); + obs_source_dosignal(source, "source-create", NULL); return source; fail: @@ -187,7 +190,7 @@ static void obs_source_destroy(struct obs_source *source) { size_t i; - obs_source_dosignal(source, "source-destroy"); + obs_source_dosignal(source, "source-destroy", "destroy"); if (source->filter_parent) obs_source_filter_remove(source->filter_parent, source); @@ -243,7 +246,6 @@ void obs_source_release(obs_source_t source) void obs_source_remove(obs_source_t source) { struct obs_core_data *data = &obs->data; - struct calldata cd = {0}; size_t id; pthread_mutex_lock(&data->sources_mutex); @@ -263,11 +265,7 @@ void obs_source_remove(obs_source_t source) pthread_mutex_unlock(&data->sources_mutex); - calldata_setptr(&cd, "source", source); - signal_handler_signal(obs->signals, "source-remove", &cd); - signal_handler_signal(source->signals, "remove", &cd); - calldata_free(&cd); - + obs_source_dosignal(source, "source-remove", "remove"); obs_source_release(source); } @@ -300,28 +298,30 @@ void obs_source_update(obs_source_t source, obs_data_t settings) static void activate_source(obs_source_t source) { - struct calldata data = {0}; - if (source->info.activate) source->info.activate(source->data); - - calldata_setptr(&data, "source", source); - signal_handler_signal(obs->signals, "source-activate", &data); - signal_handler_signal(source->signals, "activate", &data); - calldata_free(&data); + obs_source_dosignal(source, "source-activate", "activate"); } static void deactivate_source(obs_source_t source) { - struct calldata data = {0}; - if (source->info.deactivate) source->info.deactivate(source->data); + obs_source_dosignal(source, "source-deactivate", "deactivate"); +} - calldata_setptr(&data, "source", source); - signal_handler_signal(obs->signals, "source-deactivate", &data); - signal_handler_signal(source->signals, "deactivate", &data); - calldata_free(&data); +static void show_source(obs_source_t source) +{ + if (source->info.show) + source->info.show(source->data); + obs_source_dosignal(source, "source-show", "show"); +} + +static void hide_source(obs_source_t source) +{ + if (source->info.hide) + source->info.hide(source->data); + obs_source_dosignal(source, "source-hide", "hide"); } static void activate_tree(obs_source_t parent, obs_source_t child, void *param) @@ -343,25 +343,57 @@ static void deactivate_tree(obs_source_t parent, obs_source_t child, UNUSED_PARAMETER(param); } -void obs_source_activate(obs_source_t source) +static void show_tree(obs_source_t parent, obs_source_t child, void *param) +{ + if (++child->show_refs == 1) + show_source(child); + + UNUSED_PARAMETER(parent); + UNUSED_PARAMETER(param); +} + +static void hide_tree(obs_source_t parent, obs_source_t child, void *param) +{ + if (--child->show_refs == 0) + hide_source(child); + + UNUSED_PARAMETER(parent); + UNUSED_PARAMETER(param); +} + +void obs_source_activate(obs_source_t source, enum view_type type) { if (!source) return; - if (++source->activate_refs == 1) { - activate_source(source); - obs_source_enum_tree(source, activate_tree, NULL); - obs_source_set_present_volume(source, 1.0f); + if (++source->show_refs == 1) { + show_source(source); + obs_source_enum_tree(source, show_tree, NULL); + } + + if (type == MAIN_VIEW) { + if (++source->activate_refs == 1) { + activate_source(source); + obs_source_enum_tree(source, activate_tree, NULL); + obs_source_set_present_volume(source, 1.0f); + } } } -void obs_source_deactivate(obs_source_t source) +void obs_source_deactivate(obs_source_t source, enum view_type type) { if (!source) return; - if (--source->activate_refs == 0) { - deactivate_source(source); - obs_source_enum_tree(source, deactivate_tree, NULL); - obs_source_set_present_volume(source, 0.0f); + if (--source->show_refs == 0) { + hide_source(source); + obs_source_enum_tree(source, hide_tree, NULL); + } + + if (type == MAIN_VIEW) { + if (--source->activate_refs == 0) { + deactivate_source(source); + obs_source_enum_tree(source, deactivate_tree, NULL); + obs_source_set_present_volume(source, 0.0f); + } } } @@ -1311,16 +1343,22 @@ void obs_source_add_child(obs_source_t parent, obs_source_t child) { if (!parent || !child) return; - if (parent->activate_refs > 0) - obs_source_activate(child); + for (int i = 0; i < parent->show_refs; i++) { + enum view_type type; + type = (i < parent->activate_refs) ? MAIN_VIEW : AUX_VIEW; + obs_source_activate(child, type); + } } void obs_source_remove_child(obs_source_t parent, obs_source_t child) { if (!parent || !child) return; - if (parent->activate_refs > 0) - obs_source_deactivate(child); + for (int i = 0; i < parent->show_refs; i++) { + enum view_type type; + type = (i < parent->activate_refs) ? MAIN_VIEW : AUX_VIEW; + obs_source_deactivate(child, type); + } } static void reset_transition_vol(obs_source_t parent, obs_source_t child, diff --git a/libobs/obs-source.h b/libobs/obs-source.h index 4b56feb00..da85bc073 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -151,15 +151,21 @@ struct obs_source_info { */ void (*update)(void *data, obs_data_t settings); - /** Called when the source has been activated */ + /** Called when the source has been activated in the main view */ void (*activate)(void *data); /** - * Called when the source has been deactivated (no longer being - * played/displayed) + * Called when the source has been deactivated from the main view + * (no longer being played/displayed) */ void (*deactivate)(void *data); + /** Called when the source is visible */ + void (*show)(void *data); + + /** Called when the source is no longer visible */ + void (*hide)(void *data); + /** * Called each video frame with the time elapsed * diff --git a/libobs/obs-view.c b/libobs/obs-view.c index b22211dd9..2887d0146 100644 --- a/libobs/obs-view.c +++ b/libobs/obs-view.c @@ -95,11 +95,11 @@ void obs_view_setsource(obs_view_t view, uint32_t channel, if (source) { obs_source_addref(source); - obs_source_activate(source); + obs_source_activate(source, AUX_VIEW); } if (prev_source) { - obs_source_deactivate(prev_source); + obs_source_deactivate(prev_source, AUX_VIEW); obs_source_release(prev_source); } diff --git a/libobs/obs.c b/libobs/obs.c index 72b397e0c..6f991faf9 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -707,11 +707,11 @@ void obs_set_output_source(uint32_t channel, obs_source_t source) if (source) { obs_source_addref(source); - obs_source_activate(source); + obs_source_activate(source, MAIN_VIEW); } if (prev_source) { - obs_source_deactivate(prev_source); + obs_source_deactivate(prev_source, MAIN_VIEW); obs_source_release(prev_source); } diff --git a/obs/forms/OBSBasicSettings.ui b/obs/forms/OBSBasicSettings.ui index 26dbd26ed..805b55dc9 100644 --- a/obs/forms/OBSBasicSettings.ui +++ b/obs/forms/OBSBasicSettings.ui @@ -77,7 +77,7 @@ - 2 + 0