From 669da7ba36c686e18b9d1120bbb64f27a67cfb78 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Thu, 7 Jan 2016 19:48:36 -0800 Subject: [PATCH] libobs: Do not use signals with audio capture/controls (Note: This commit also modifies UI) Instead of using signals, use designated callback lists for audio capture and audio control helpers. Signals aren't suitable here due to the fact that signals aren't meant for things that happen every frame or things that happen every time audio/video is received. Also prevents audio from being allocated every time these functions are called due to the calldata structure. --- libobs/obs-audio-controls.c | 168 +++++++++++++++++++++--------------- libobs/obs-audio-controls.h | 20 +++-- libobs/obs-internal.h | 7 ++ libobs/obs-source.c | 47 +++++++--- libobs/obs.h | 8 ++ obs/volume-control.cpp | 27 ++---- obs/volume-control.hpp | 5 +- 7 files changed, 176 insertions(+), 106 deletions(-) diff --git a/libobs/obs-audio-controls.c b/libobs/obs-audio-controls.c index 19bdd585e..6e3ee33e0 100644 --- a/libobs/obs-audio-controls.c +++ b/libobs/obs-audio-controls.c @@ -34,9 +34,13 @@ along with this program. If not, see . typedef float (*obs_fader_conversion_t)(const float val); +struct fader_cb { + obs_fader_changed_t callback; + void *param; +}; + struct obs_fader { pthread_mutex_t mutex; - signal_handler_t *signals; obs_fader_conversion_t def_to_db; obs_fader_conversion_t db_to_def; obs_source_t *source; @@ -45,17 +49,27 @@ struct obs_fader { float min_db; float cur_db; bool ignore_next_signal; + + pthread_mutex_t callback_mutex; + DARRAY(struct fader_cb)callbacks; +}; + +struct meter_cb { + obs_volmeter_updated_t callback; + void *param; }; struct obs_volmeter { pthread_mutex_t mutex; - signal_handler_t *signals; obs_fader_conversion_t pos_to_db; obs_fader_conversion_t db_to_pos; obs_source_t *source; enum obs_fader_type type; float cur_db; + pthread_mutex_t callback_mutex; + DARRAY(struct meter_cb)callbacks; + unsigned int channels; unsigned int update_ms; unsigned int update_frames; @@ -72,17 +86,6 @@ struct obs_volmeter { float vol_max; }; -static const char *fader_signals[] = { - "void volume_changed(ptr fader, float db)", - NULL -}; - -static const char *volmeter_signals[] = { - "void levels_updated(ptr volmeter, float level, " - "float magnitude, float peak, bool muted)", - NULL -}; - static float cubic_def_to_db(const float def) { if (def == 1.0f) @@ -191,39 +194,26 @@ static float log_db_to_def(const float db) / (LOG_OFFSET_VAL - LOG_RANGE_VAL); } -static void signal_volume_changed(signal_handler_t *sh, - struct obs_fader *fader, const float db) +static void signal_volume_changed(struct obs_fader *fader, const float db) { - struct calldata data; - - calldata_init(&data); - - calldata_set_ptr (&data, "fader", fader); - calldata_set_float(&data, "db", db); - - signal_handler_signal(sh, "volume_changed", &data); - - calldata_free(&data); + pthread_mutex_lock(&fader->callback_mutex); + for (size_t i = fader->callbacks.num; i > 0; i--) { + struct fader_cb cb = fader->callbacks.array[i - 1]; + cb.callback(cb.param, db); + } + pthread_mutex_unlock(&fader->callback_mutex); } -static void signal_levels_updated(signal_handler_t *sh, - struct obs_volmeter *volmeter, +static void signal_levels_updated(struct obs_volmeter *volmeter, const float level, const float magnitude, const float peak, bool muted) { - struct calldata data; - - calldata_init(&data); - - calldata_set_ptr (&data, "volmeter", volmeter); - calldata_set_float(&data, "level", level); - calldata_set_float(&data, "magnitude", magnitude); - calldata_set_float(&data, "peak", peak); - calldata_set_bool (&data, "muted", muted); - - signal_handler_signal(sh, "levels_updated", &data); - - calldata_free(&data); + pthread_mutex_lock(&volmeter->callback_mutex); + for (size_t i = volmeter->callbacks.num; i > 0; i--) { + struct meter_cb cb = volmeter->callbacks.array[i - 1]; + cb.callback(cb.param, level, magnitude, peak, muted); + } + pthread_mutex_unlock(&volmeter->callback_mutex); } static void fader_source_volume_changed(void *vptr, calldata_t *calldata) @@ -238,14 +228,13 @@ static void fader_source_volume_changed(void *vptr, calldata_t *calldata) return; } - signal_handler_t *sh = fader->signals; const float mul = (float)calldata_float(calldata, "volume"); const float db = mul_to_db(mul); fader->cur_db = db; pthread_mutex_unlock(&fader->mutex); - signal_volume_changed(sh, fader, db); + signal_volume_changed(fader, db); } static void volmeter_source_volume_changed(void *vptr, calldata_t *calldata) @@ -335,7 +324,7 @@ static void volmeter_calc_ival_levels(obs_volmeter_t *volmeter) } static bool volmeter_process_audio_data(obs_volmeter_t *volmeter, - struct audio_data *data) + const struct audio_data *data) { bool updated = false; size_t frames = 0; @@ -374,16 +363,15 @@ static bool volmeter_process_audio_data(obs_volmeter_t *volmeter, return updated; } -static void volmeter_source_data_received(void *vptr, calldata_t *calldata) +static void volmeter_source_data_received(void *vptr, obs_source_t *source, + const struct audio_data *data, bool muted) { struct obs_volmeter *volmeter = (struct obs_volmeter *) vptr; bool updated = false; float mul, level, mag, peak; - signal_handler_t *sh; pthread_mutex_lock(&volmeter->mutex); - struct audio_data *data = calldata_ptr(calldata, "data"); updated = volmeter_process_audio_data(volmeter, data); if (updated) { @@ -393,14 +381,14 @@ static void volmeter_source_data_received(void *vptr, calldata_t *calldata) mag = volmeter->db_to_pos(mul_to_db(volmeter->vol_mag * mul)); peak = volmeter->db_to_pos( mul_to_db(volmeter->vol_peak * mul)); - sh = volmeter->signals; } pthread_mutex_unlock(&volmeter->mutex); if (updated) - signal_levels_updated(sh, volmeter, level, mag, peak, - calldata_bool(calldata, "muted")); + signal_levels_updated(volmeter, level, mag, peak, muted); + + UNUSED_PARAMETER(source); } static void volmeter_update_audio_settings(obs_volmeter_t *volmeter) @@ -420,12 +408,10 @@ obs_fader_t *obs_fader_create(enum obs_fader_type type) return NULL; pthread_mutex_init_value(&fader->mutex); + pthread_mutex_init_value(&fader->callback_mutex); if (pthread_mutex_init(&fader->mutex, NULL) != 0) goto fail; - fader->signals = signal_handler_create(); - if (!fader->signals) - goto fail; - if (!signal_handler_add_array(fader->signals, fader_signals)) + if (pthread_mutex_init(&fader->callback_mutex, NULL) != 0) goto fail; switch(type) { @@ -465,7 +451,8 @@ void obs_fader_destroy(obs_fader_t *fader) return; obs_fader_detach_source(fader); - signal_handler_destroy(fader->signals); + da_free(fader->callbacks); + pthread_mutex_destroy(&fader->callback_mutex); pthread_mutex_destroy(&fader->mutex); bfree(fader); @@ -603,9 +590,30 @@ exit: pthread_mutex_unlock(&fader->mutex); } -signal_handler_t *obs_fader_get_signal_handler(obs_fader_t *fader) +void obs_fader_add_callback(obs_fader_t *fader, obs_fader_changed_t callback, + void *param) { - return (fader) ? fader->signals : NULL; + struct fader_cb cb = {callback, param}; + + if (!obs_ptr_valid(fader, "obs_fader_add_callback")) + return; + + pthread_mutex_lock(&fader->callback_mutex); + da_push_back(fader->callbacks, &cb); + pthread_mutex_unlock(&fader->callback_mutex); +} + +void obs_fader_remove_callback(obs_fader_t *fader, obs_fader_changed_t callback, + void *param) +{ + struct fader_cb cb = {callback, param}; + + if (!obs_ptr_valid(fader, "obs_fader_remove_callback")) + return; + + pthread_mutex_lock(&fader->callback_mutex); + da_erase_item(fader->callbacks, &cb); + pthread_mutex_unlock(&fader->callback_mutex); } obs_volmeter_t *obs_volmeter_create(enum obs_fader_type type) @@ -615,12 +623,10 @@ obs_volmeter_t *obs_volmeter_create(enum obs_fader_type type) return NULL; pthread_mutex_init_value(&volmeter->mutex); + pthread_mutex_init_value(&volmeter->callback_mutex); if (pthread_mutex_init(&volmeter->mutex, NULL) != 0) goto fail; - volmeter->signals = signal_handler_create(); - if (!volmeter->signals) - goto fail; - if (!signal_handler_add_array(volmeter->signals, volmeter_signals)) + if (pthread_mutex_init(&volmeter->callback_mutex, NULL) != 0) goto fail; /* set conversion functions */ @@ -658,7 +664,8 @@ void obs_volmeter_destroy(obs_volmeter_t *volmeter) return; obs_volmeter_detach_source(volmeter); - signal_handler_destroy(volmeter->signals); + da_free(volmeter->callbacks); + pthread_mutex_destroy(&volmeter->callback_mutex); pthread_mutex_destroy(&volmeter->mutex); bfree(volmeter); @@ -678,10 +685,10 @@ bool obs_volmeter_attach_source(obs_volmeter_t *volmeter, obs_source_t *source) sh = obs_source_get_signal_handler(source); signal_handler_connect(sh, "volume", volmeter_source_volume_changed, volmeter); - signal_handler_connect(sh, "audio_data", - volmeter_source_data_received, volmeter); signal_handler_connect(sh, "destroy", volmeter_source_destroyed, volmeter); + obs_source_add_audio_capture_callback(source, + volmeter_source_data_received, volmeter); volmeter->source = source; volmeter->cur_db = mul_to_db(obs_source_get_volume(source)); @@ -706,10 +713,10 @@ void obs_volmeter_detach_source(obs_volmeter_t *volmeter) sh = obs_source_get_signal_handler(volmeter->source); signal_handler_disconnect(sh, "volume", volmeter_source_volume_changed, volmeter); - signal_handler_disconnect(sh, "audio_data", - volmeter_source_data_received, volmeter); signal_handler_disconnect(sh, "destroy", volmeter_source_destroyed, volmeter); + obs_source_remove_audio_capture_callback(volmeter->source, + volmeter_source_data_received, volmeter); volmeter->source = NULL; @@ -717,11 +724,6 @@ exit: pthread_mutex_unlock(&volmeter->mutex); } -signal_handler_t *obs_volmeter_get_signal_handler(obs_volmeter_t *volmeter) -{ - return (volmeter) ? volmeter->signals : NULL; -} - void obs_volmeter_set_update_interval(obs_volmeter_t *volmeter, const unsigned int ms) { @@ -768,3 +770,29 @@ unsigned int obs_volmeter_get_peak_hold(obs_volmeter_t *volmeter) return peakhold; } + +void obs_volmeter_add_callback(obs_volmeter_t *volmeter, + obs_volmeter_updated_t callback, void *param) +{ + struct meter_cb cb = {callback, param}; + + if (!obs_ptr_valid(volmeter, "obs_volmeter_add_callback")) + return; + + pthread_mutex_lock(&volmeter->callback_mutex); + da_push_back(volmeter->callbacks, &cb); + pthread_mutex_unlock(&volmeter->callback_mutex); +} + +void obs_volmeter_remove_callback(obs_volmeter_t *volmeter, + obs_volmeter_updated_t callback, void *param) +{ + struct meter_cb cb = {callback, param}; + + if (!obs_ptr_valid(volmeter, "obs_volmeter_remove_callback")) + return; + + pthread_mutex_lock(&volmeter->callback_mutex); + da_erase_item(volmeter->callbacks, &cb); + pthread_mutex_unlock(&volmeter->callback_mutex); +} diff --git a/libobs/obs-audio-controls.h b/libobs/obs-audio-controls.h index 857c6816a..89020afee 100644 --- a/libobs/obs-audio-controls.h +++ b/libobs/obs-audio-controls.h @@ -154,12 +154,12 @@ EXPORT bool obs_fader_attach_source(obs_fader_t *fader, obs_source_t *source); */ EXPORT void obs_fader_detach_source(obs_fader_t *fader); -/** - * @brief Get signal handler for the fader - * @param fader pointer to the fader object - * @return signal handler - */ -EXPORT signal_handler_t *obs_fader_get_signal_handler(obs_fader_t *fader); +typedef void (*obs_fader_changed_t)(void *param, float db); + +EXPORT void obs_fader_add_callback(obs_fader_t *fader, + obs_fader_changed_t callback, void *param); +EXPORT void obs_fader_remove_callback(obs_fader_t *fader, + obs_fader_changed_t callback, void *param); /** * @brief Create a volume meter @@ -251,6 +251,14 @@ EXPORT void obs_volmeter_set_peak_hold(obs_volmeter_t *volmeter, */ EXPORT unsigned int obs_volmeter_get_peak_hold(obs_volmeter_t *volmeter); +typedef void (*obs_volmeter_updated_t)(void *param, float level, + float magnitude, float peak, float muted); + +EXPORT void obs_volmeter_add_callback(obs_volmeter_t *volmeter, + obs_volmeter_updated_t callback, void *param); +EXPORT void obs_volmeter_remove_callback(obs_volmeter_t *volmeter, + obs_volmeter_updated_t callback, void *param); + #ifdef __cplusplus } #endif diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 960a3f891..12511d5a2 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -485,6 +485,11 @@ struct obs_weak_source { struct obs_source *source; }; +struct audio_cb_info { + obs_source_audio_capture_t callback; + void *param; +}; + struct obs_source { struct obs_context_data context; struct obs_source_info info; @@ -542,6 +547,8 @@ struct obs_source { pthread_mutex_t audio_actions_mutex; pthread_mutex_t audio_buf_mutex; pthread_mutex_t audio_mutex; + pthread_mutex_t audio_cb_mutex; + DARRAY(struct audio_cb_info) audio_cb_list; struct obs_audio_data audio_data; size_t audio_storage_size; uint32_t audio_mixers; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index fb017229b..474517136 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -65,7 +65,6 @@ static const char *source_signals[] = { "void update_properties(ptr source)", "void update_flags(ptr source, int flags)", "void audio_sync(ptr source, int out int offset)", - "void audio_data(ptr source, ptr data, bool muted)", "void audio_mixers(ptr source, in out int mixers)", "void filter_add(ptr source, ptr filter)", "void filter_remove(ptr source, ptr filter)", @@ -131,6 +130,7 @@ bool obs_source_init(struct obs_source *source) pthread_mutex_init_value(&source->async_mutex); pthread_mutex_init_value(&source->audio_mutex); pthread_mutex_init_value(&source->audio_buf_mutex); + pthread_mutex_init_value(&source->audio_cb_mutex); if (pthread_mutexattr_init(&attr) != 0) return false; @@ -142,6 +142,8 @@ bool obs_source_init(struct obs_source *source) return false; if (pthread_mutex_init(&source->audio_actions_mutex, NULL) != 0) return false; + if (pthread_mutex_init(&source->audio_cb_mutex, NULL) != 0) + return false; if (pthread_mutex_init(&source->audio_mutex, NULL) != 0) return false; if (pthread_mutex_init(&source->async_mutex, NULL) != 0) @@ -415,12 +417,14 @@ void obs_source_destroy(struct obs_source *source) obs_transition_free(source); da_free(source->audio_actions); + da_free(source->audio_cb_list); da_free(source->async_cache); da_free(source->async_frames); da_free(source->filters); pthread_mutex_destroy(&source->filter_mutex); pthread_mutex_destroy(&source->audio_actions_mutex); pthread_mutex_destroy(&source->audio_buf_mutex); + pthread_mutex_destroy(&source->audio_cb_mutex); pthread_mutex_destroy(&source->audio_mutex); pthread_mutex_destroy(&source->async_mutex); obs_context_data_free(&source->context); @@ -912,17 +916,14 @@ static void handle_ts_jump(obs_source_t *source, uint64_t expected, static void source_signal_audio_data(obs_source_t *source, struct audio_data *in, bool muted) { - struct calldata data; + pthread_mutex_lock(&source->audio_cb_mutex); - calldata_init(&data); + for (size_t i = source->audio_cb_list.num; i > 0; i--) { + struct audio_cb_info info = source->audio_cb_list.array[i - 1]; + info.callback(info.param, source, in, muted); + } - calldata_set_ptr(&data, "source", source); - calldata_set_ptr(&data, "data", in); - calldata_set_bool(&data, "muted", muted); - - signal_handler_signal(source->context.signals, "audio_data", &data); - - calldata_free(&data); + pthread_mutex_unlock(&source->audio_cb_mutex); } static inline uint64_t uint64_diff(uint64_t ts1, uint64_t ts2) @@ -3531,3 +3532,29 @@ void obs_source_get_audio_mix(const obs_source_t *source, } } } + +void obs_source_add_audio_capture_callback(obs_source_t *source, + obs_source_audio_capture_t callback, void *param) +{ + struct audio_cb_info info = {callback, param}; + + if (!obs_source_valid(source, "obs_source_add_audio_capture_callback")) + return; + + pthread_mutex_lock(&source->audio_cb_mutex); + da_push_back(source->audio_cb_list, &info); + pthread_mutex_unlock(&source->audio_cb_mutex); +} + +void obs_source_remove_audio_capture_callback(obs_source_t *source, + obs_source_audio_capture_t callback, void *param) +{ + struct audio_cb_info info = {callback, param}; + + if (!obs_source_valid(source, "obs_source_remove_audio_capture_callback")) + return; + + pthread_mutex_lock(&source->audio_cb_mutex); + da_erase_item(source->audio_cb_list, &info); + pthread_mutex_unlock(&source->audio_cb_mutex); +} diff --git a/libobs/obs.h b/libobs/obs.h index 9a6ebdf7b..6714cc379 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -844,6 +844,14 @@ EXPORT uint64_t obs_source_get_push_to_talk_delay(obs_source_t *source); EXPORT void obs_source_set_push_to_talk_delay(obs_source_t *source, uint64_t delay); +typedef void (*obs_source_audio_capture_t)(void *param, obs_source_t *source, + const struct audio_data *audio_data, bool muted); + +EXPORT void obs_source_add_audio_capture_callback(obs_source_t *source, + obs_source_audio_capture_t callback, void *param); +EXPORT void obs_source_remove_audio_capture_callback(obs_source_t *source, + obs_source_audio_capture_t callback, void *param); + /* ------------------------------------------------------------------------- */ /* Functions used by sources */ diff --git a/obs/volume-control.cpp b/obs/volume-control.cpp index 568bdbbc5..02456a48e 100644 --- a/obs/volume-control.cpp +++ b/obs/volume-control.cpp @@ -16,26 +16,23 @@ using namespace std; -void VolControl::OBSVolumeChanged(void *data, calldata_t *calldata) +void VolControl::OBSVolumeChanged(void *data, float db) { - Q_UNUSED(calldata); + Q_UNUSED(db); VolControl *volControl = static_cast(data); QMetaObject::invokeMethod(volControl, "VolumeChanged"); } -void VolControl::OBSVolumeLevel(void *data, calldata_t *calldata) +void VolControl::OBSVolumeLevel(void *data, float level, float mag, + float peak, float muted) { VolControl *volControl = static_cast(data); - float peak = calldata_float(calldata, "level"); - float mag = calldata_float(calldata, "magnitude"); - float peakHold = calldata_float(calldata, "peak"); - bool muted = calldata_bool (calldata, "muted"); QMetaObject::invokeMethod(volControl, "VolumeLevel", Q_ARG(float, mag), + Q_ARG(float, level), Q_ARG(float, peak), - Q_ARG(float, peakHold), Q_ARG(bool, muted)); } @@ -174,11 +171,8 @@ VolControl::VolControl(OBSSource source_, bool showConfig) setLayout(mainLayout); - signal_handler_connect(obs_fader_get_signal_handler(obs_fader), - "volume_changed", OBSVolumeChanged, this); - - signal_handler_connect(obs_volmeter_get_signal_handler(obs_volmeter), - "levels_updated", OBSVolumeLevel, this); + obs_fader_add_callback(obs_fader, OBSVolumeChanged, this); + obs_volmeter_add_callback(obs_volmeter, OBSVolumeLevel, this); signal_handler_connect(obs_source_get_signal_handler(source), "mute", OBSVolumeMuted, this); @@ -199,11 +193,8 @@ VolControl::VolControl(OBSSource source_, bool showConfig) VolControl::~VolControl() { - signal_handler_disconnect(obs_fader_get_signal_handler(obs_fader), - "volume_changed", OBSVolumeChanged, this); - - signal_handler_disconnect(obs_volmeter_get_signal_handler(obs_volmeter), - "levels_updated", OBSVolumeLevel, this); + obs_fader_remove_callback(obs_fader, OBSVolumeChanged, this); + obs_volmeter_remove_callback(obs_volmeter, OBSVolumeLevel, this); signal_handler_disconnect(obs_source_get_signal_handler(source), "mute", OBSVolumeMuted, this); diff --git a/obs/volume-control.hpp b/obs/volume-control.hpp index a1fb10f6f..27b52b207 100644 --- a/obs/volume-control.hpp +++ b/obs/volume-control.hpp @@ -56,8 +56,9 @@ private: obs_fader_t *obs_fader; obs_volmeter_t *obs_volmeter; - static void OBSVolumeChanged(void *param, calldata_t *calldata); - static void OBSVolumeLevel(void *data, calldata_t *calldata); + static void OBSVolumeChanged(void *param, float db); + static void OBSVolumeLevel(void *data, float level, float mag, + float peak, float muted); static void OBSVolumeMuted(void *data, calldata_t *calldata); void EmitConfigClicked();