From f2ee9507468b9ceee9d9467d10e9444b491d6527 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Fri, 7 Mar 2014 17:03:34 -0700 Subject: [PATCH] Activate user-selected audio devices - Fix a bug where the initial audio data insertion would cause all audio data to unintentionally clear (mixed up < and > operators, damn human error) - Fixed a potential interdependant lock scenario with channel mutex locks and graphics mutex locks. The main video thread could lock the graphics mutex and then while in the graphics mutex could lock the channels mutex. Meanwhile in another thread, the channel mutex could get locked, and then the graphics mutex would get locked, causing a deadlock. The best way to deal with this is to not let mutexes lock within other mutexes, but sometimes it's difficult to avoid such as in the main video thread. - Audio devices should now be functional, and the devices in the audio settings can now be changed as desired. --- libobs/media-io/audio-io.c | 16 ++++++----- libobs/obs-view.c | 10 +++---- libobs/obs.c | 10 +++---- obs/obs-app.cpp | 21 +++++++++++++++ obs/obs-app.hpp | 3 +++ obs/window-basic-main.cpp | 45 +++++++++++++++++++++++++++++-- obs/window-basic-main.hpp | 4 ++- obs/window-basic-settings.cpp | 4 ++- plugins/win-wasapi/win-wasapi.cpp | 4 +++ 9 files changed, 96 insertions(+), 21 deletions(-) diff --git a/libobs/media-io/audio-io.c b/libobs/media-io/audio-io.c index 2776b2680..e1b5b73d0 100644 --- a/libobs/media-io/audio-io.c +++ b/libobs/media-io/audio-io.c @@ -144,21 +144,23 @@ static inline uint64_t conv_frames_to_time(audio_t audio, uint32_t frames) /* ------------------------------------------------------------------------- */ +/* this only really happens with the very initial data insertion. can be + * ignored safely. */ static inline void clear_excess_audio_data(struct audio_line *line, uint64_t prev_time) { size_t size = ts_diff_bytes(line->audio, prev_time, line->base_timestamp); - blog(LOG_WARNING, "Excess audio data for audio line '%s', somehow " - "audio data went back in time by %"PRIu32" bytes. " - "prev_time: %"PRIu64", line->base_timestamp: %"PRIu64, - line->name, (uint32_t)size, - prev_time, line->base_timestamp); + /*blog(LOG_DEBUG, "Excess audio data for audio line '%s', somehow " + "audio data went back in time by %"PRIu32" bytes. " + "prev_time: %"PRIu64", line->base_timestamp: %"PRIu64, + line->name, (uint32_t)size, + prev_time, line->base_timestamp);*/ for (size_t i = 0; i < line->audio->planes; i++) { - size_t clear_size = (size > line->buffers[i].size) ? - (size_t)size : line->buffers[i].size; + size_t clear_size = (size < line->buffers[i].size) ? + size : line->buffers[i].size; circlebuf_pop_front(&line->buffers[i], NULL, clear_size); } diff --git a/libobs/obs-view.c b/libobs/obs-view.c index 0dd584960..5d3111f6d 100644 --- a/libobs/obs-view.c +++ b/libobs/obs-view.c @@ -94,20 +94,20 @@ void obs_view_setsource(obs_view_t view, uint32_t channel, pthread_mutex_lock(&view->channels_mutex); + obs_source_addref(source); + prev_source = view->channels[channel]; view->channels[channel] = source; - if (source) { - obs_source_addref(source); + pthread_mutex_unlock(&view->channels_mutex); + + if (source) obs_source_activate(source, AUX_VIEW); - } if (prev_source) { obs_source_deactivate(prev_source, AUX_VIEW); obs_source_release(prev_source); } - - pthread_mutex_unlock(&view->channels_mutex); } void obs_view_render(obs_view_t view) diff --git a/libobs/obs.c b/libobs/obs.c index a96bf0aac..7b1333663 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -727,6 +727,8 @@ void obs_set_output_source(uint32_t channel, obs_source_t source) pthread_mutex_lock(&view->channels_mutex); + obs_source_addref(source); + prev_source = view->channels[channel]; calldata_setint(¶ms, "channel", channel); @@ -738,17 +740,15 @@ void obs_set_output_source(uint32_t channel, obs_source_t source) view->channels[channel] = source; - if (source) { - obs_source_addref(source); + pthread_mutex_unlock(&view->channels_mutex); + + if (source) obs_source_activate(source, MAIN_VIEW); - } if (prev_source) { obs_source_deactivate(prev_source, MAIN_VIEW); obs_source_release(prev_source); } - - pthread_mutex_unlock(&view->channels_mutex); } void obs_enum_outputs(bool (*enum_proc)(void*, obs_output_t), void *param) diff --git a/obs/obs-app.cpp b/obs/obs-app.cpp index a22658dc1..82b2cf7fc 100644 --- a/obs/obs-app.cpp +++ b/obs/obs-app.cpp @@ -181,6 +181,27 @@ void OBSApp::OBSInit() mainWindow->OBSInit(); } +#ifdef __APPLE__ +#define INPUT_AUDIO_SOURCE "coreaudio_input_capture +#define OUTPUT_AUDIO_SOURCE "coreaudio_output_capture +#elif _WIN32 +#define INPUT_AUDIO_SOURCE "wasapi_input_capture" +#define OUTPUT_AUDIO_SOURCE "wasapi_output_capture" +#else +#define INPUT_AUDIO_SOURCE "" +#define OUTPUT_AUDIO_SOURCE "" +#endif + +const char *OBSApp::InputAudioSource() const +{ + return INPUT_AUDIO_SOURCE; +} + +const char *OBSApp::OutputAudioSource() const +{ + return OUTPUT_AUDIO_SOURCE; +} + struct NoFocusFrameStyle : QProxyStyle { void drawControl(ControlElement element, const QStyleOption *option, diff --git a/obs/obs-app.hpp b/obs/obs-app.hpp index c591216fa..c82961b4b 100644 --- a/obs/obs-app.hpp +++ b/obs/obs-app.hpp @@ -56,6 +56,9 @@ public: return textLookup.GetString(lookupVal); } + const char *InputAudioSource() const; + const char *OutputAudioSource() const; + const char *GetRenderModule() const; }; diff --git a/obs/window-basic-main.cpp b/obs/window-basic-main.cpp index 463a28e42..ee3e6015c 100644 --- a/obs/window-basic-main.cpp +++ b/obs/window-basic-main.cpp @@ -144,6 +144,8 @@ void OBSBasic::OBSInit() obs_load_module("win-wasapi"); obs_load_module("win-capture"); #endif + + ResetAudioDevices(); } OBSBasic::~OBSBasic() @@ -419,9 +421,48 @@ bool OBSBasic::ResetAudio() return obs_reset_audio(&ai); } -bool OBSBasic::ResetAudioDevices() +void OBSBasic::ResetAudioDevice(const char *sourceId, const char *deviceName, + int channel) { - return false; + const char *deviceId = config_get_string(basicConfig, "Audio", + deviceName); + obs_source_t source; + obs_data_t settings; + bool same = false; + + source = obs_get_output_source(channel); + if (source) { + settings = obs_source_getsettings(source); + const char *curId = obs_data_getstring(settings, "device_id"); + + same = (strcmp(curId, deviceId) == 0); + + obs_data_release(settings); + obs_source_release(source); + } + + if (!same) + obs_set_output_source(channel, nullptr); + + if (!same && strcmp(deviceId, "disabled") != 0) { + obs_data_t settings = obs_data_create(); + obs_data_setstring(settings, "device_id", deviceId); + source = obs_source_create(OBS_SOURCE_TYPE_INPUT, + sourceId, deviceName, settings); + obs_data_release(settings); + + obs_set_output_source(channel, source); + obs_source_release(source); + } +} + +void OBSBasic::ResetAudioDevices() +{ + ResetAudioDevice(App()->OutputAudioSource(), "DesktopDevice1", 1); + ResetAudioDevice(App()->OutputAudioSource(), "DesktopDevice2", 2); + ResetAudioDevice(App()->InputAudioSource(), "AuxDevice1", 3); + ResetAudioDevice(App()->InputAudioSource(), "AuxDevice2", 4); + ResetAudioDevice(App()->InputAudioSource(), "AuxDevice3", 5); } void OBSBasic::ResizePreview(uint32_t cx, uint32_t cy) diff --git a/obs/window-basic-main.hpp b/obs/window-basic-main.hpp index 5feac7adf..bf81ff139 100644 --- a/obs/window-basic-main.hpp +++ b/obs/window-basic-main.hpp @@ -82,7 +82,9 @@ public: bool ResetVideo(); bool ResetAudio(); - bool ResetAudioDevices(); + void ResetAudioDevice(const char *sourceId, const char *deviceName, + int channel); + void ResetAudioDevices(); void NewProject(); void SaveProject(); diff --git a/obs/window-basic-settings.cpp b/obs/window-basic-settings.cpp index 5fddec79b..d863b6c5f 100644 --- a/obs/window-basic-settings.cpp +++ b/obs/window-basic-settings.cpp @@ -481,7 +481,7 @@ void OBSBasicSettings::SaveAudioSettings() QString desktopDevice2 = GetComboData(ui->desktopAudioDevice2); QString auxDevice1 = GetComboData(ui->auxAudioDevice1); QString auxDevice2 = GetComboData(ui->auxAudioDevice2); - QString auxDevice3 = GetComboData(ui->auxAudioDevice2); + QString auxDevice3 = GetComboData(ui->auxAudioDevice3); const char *channelSetup; if (channelSetupIdx == 0) @@ -509,6 +509,8 @@ void OBSBasicSettings::SaveAudioSettings() QT_TO_UTF8(auxDevice2)); config_set_string(main->Config(), "Audio", "AuxDevice3", QT_TO_UTF8(auxDevice3)); + + main->ResetAudioDevices(); } void OBSBasicSettings::SaveSettings() diff --git a/plugins/win-wasapi/win-wasapi.cpp b/plugins/win-wasapi/win-wasapi.cpp index c41d1b54c..fb7979b70 100644 --- a/plugins/win-wasapi/win-wasapi.cpp +++ b/plugins/win-wasapi/win-wasapi.cpp @@ -92,6 +92,10 @@ WASAPISource::WASAPISource(obs_data_t settings, obs_source_t source_, inline WASAPISource::~WASAPISource() { + if (active) + blog(LOG_INFO, "WASAPI: Device '%s' Terminated", + device_name.c_str()); + SetEvent(stopSignal); if (active)