From f5df13eb24a70f1a37089eed8d4ce8a3e5b848de Mon Sep 17 00:00:00 2001 From: James Rowe Date: Wed, 6 Mar 2019 20:59:58 -0700 Subject: [PATCH] Remove global state and add mic hot swapping --- src/audio_core/cubeb_input.cpp | 2 +- .../configuration/configure_audio.cpp | 10 +-- src/core/frontend/mic.h | 10 +-- src/core/hle/service/mic_u.cpp | 74 ++++++++++++++----- src/core/hle/service/mic_u.h | 4 + src/core/settings.cpp | 23 ++---- 6 files changed, 71 insertions(+), 52 deletions(-) diff --git a/src/audio_core/cubeb_input.cpp b/src/audio_core/cubeb_input.cpp index f191fd8cd3..9e83125e73 100644 --- a/src/audio_core/cubeb_input.cpp +++ b/src/audio_core/cubeb_input.cpp @@ -113,7 +113,7 @@ long CubebInput::Impl::DataCallback(cubeb_stream* stream, void* user_data, const return 0; } - u8 const* data = reinterpret_cast(input_buffer); + const u8* data = reinterpret_cast(input_buffer); std::vector samples{data, data + num_frames * impl->sample_size_in_bytes}; impl->sample_queue->Push(samples); diff --git a/src/citra_qt/configuration/configure_audio.cpp b/src/citra_qt/configuration/configure_audio.cpp index e9d700c9b9..6c2fd09fda 100644 --- a/src/citra_qt/configuration/configure_audio.cpp +++ b/src/citra_qt/configuration/configure_audio.cpp @@ -42,9 +42,6 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) connect(ui->input_type_combo_box, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureAudio::updateAudioInputDevices); - ui->input_type_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn()); - ui->input_device_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn()); - this->setConfiguration(); connect(ui->output_sink_combo_box, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureAudio::updateAudioOutputDevices); @@ -142,12 +139,7 @@ void ConfigureAudio::updateAudioOutputDevices(int sink_index) { } } -void ConfigureAudio::updateAudioInputDevices(int index) { - // TODO: Don't hardcode this to the index for "Real Device" without making it a constant - // somewhere - ui->input_device_combo_box->setEnabled(index == 1 && - !Core::System::GetInstance().IsPoweredOn()); -} +void ConfigureAudio::updateAudioInputDevices(int index) {} void ConfigureAudio::retranslateUi() { ui->retranslateUi(this); diff --git a/src/core/frontend/mic.h b/src/core/frontend/mic.h index 296e434f6e..1605e77c0e 100644 --- a/src/core/frontend/mic.h +++ b/src/core/frontend/mic.h @@ -46,8 +46,10 @@ public: */ virtual Samples Read() = 0; - /// Adjusts the Parameters. Implementations should update the parameters field in addition to - /// changing the mic to sample according to the new parameters. Called by Core + /** + * Adjusts the Parameters. Implementations should update the parameters field in addition to + * changing the mic to sample according to the new parameters. Called by Core + */ virtual void AdjustSampleRate(u32 sample_rate) = 0; /// Value from 0 - 100 to adjust the mic gain setting. Called by Core @@ -111,8 +113,4 @@ private: std::vector CACHE_16_BIT; }; -void RegisterMic(std::shared_ptr mic); - -std::shared_ptr GetCurrentMic(); - } // namespace Frontend::Mic diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp index 7098446766..ca2f065548 100644 --- a/src/core/hle/service/mic_u.cpp +++ b/src/core/hle/service/mic_u.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#ifdef HAVE_CUBEB +#include "audio_core/cubeb_input.h" +#endif #include "common/logging/log.h" #include "core/core.h" #include "core/frontend/mic.h" @@ -12,6 +15,7 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/service/mic_u.h" +#include "core/settings.h" namespace Service::MIC { @@ -129,6 +133,9 @@ struct MIC_U::Impl { } void UpdateSharedMemBuffer(u64 userdata, s64 cycles_late) { + if (change_mic_impl_requested.exchange(false)) { + CreateMic(); + } // If the event was scheduled before the application requested the mic to stop sampling if (!mic->IsSampling()) { return; @@ -311,13 +318,49 @@ struct MIC_U::Impl { rb.Push(RESULT_SUCCESS); } + void CreateMic() { + std::unique_ptr new_mic; + switch (Settings::values.mic_input_type) { + case Settings::MicInputType::None: + new_mic = std::make_unique(); + break; + case Settings::MicInputType::Real: +#if HAVE_CUBEB + new_mic = std::make_unique(); +#else + new_mic = std::make_unique(); +#endif + break; + case Settings::MicInputType::Static: + new_mic = std::make_unique(); + break; + default: + LOG_CRITICAL(Audio, "Mic type not found. Defaulting to null mic"); + new_mic = std::make_unique(); + } + // If theres already a mic, copy over any data to the new mic impl + if (mic) { + new_mic->SetGain(mic->GetGain()); + new_mic->SetPower(mic->GetPower()); + auto params = mic->GetParameters(); + if (mic->IsSampling()) { + mic->StopSampling(); + new_mic->StartSampling(params); + } + } + + mic = std::move(new_mic); + change_mic_impl_requested.store(false); + } + + std::atomic change_mic_impl_requested = false; Kernel::SharedPtr buffer_full_event; Core::TimingEventType* buffer_write_event = nullptr; Kernel::SharedPtr shared_memory; u32 client_version = 0; bool allow_shell_closed = false; bool clamp = false; - std::shared_ptr mic; + std::unique_ptr mic; Core::Timing& timing; State state{}; }; @@ -407,7 +450,7 @@ MIC_U::MIC_U(Core::System& system) {0x00100040, &MIC_U::SetClientVersion, "SetClientVersion"}, }; - impl->mic = Frontend::Mic::GetCurrentMic(); + impl->CreateMic(); RegisterHandlers(functions); } @@ -415,25 +458,20 @@ MIC_U::~MIC_U() { impl->mic->StopSampling(); } +void MIC_U::ReloadMic() { + impl->change_mic_impl_requested.store(true); +} + +void ReloadMic(Core::System& system) { + auto micu = system.ServiceManager().GetService("mic:u"); + if (!micu) + return; + micu->ReloadMic(); +} + void InstallInterfaces(Core::System& system) { auto& service_manager = system.ServiceManager(); std::make_shared(system)->InstallAsService(service_manager); } } // namespace Service::MIC - -namespace Frontend::Mic { -static std::shared_ptr current_mic; - -void RegisterMic(std::shared_ptr mic) { - current_mic = mic; -} - -std::shared_ptr GetCurrentMic() { - if (!current_mic) { - current_mic = std::make_shared(); - } - return current_mic; -} - -} // namespace Frontend::Mic diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h index bc49332293..2e40ed4047 100644 --- a/src/core/hle/service/mic_u.h +++ b/src/core/hle/service/mic_u.h @@ -19,6 +19,8 @@ public: explicit MIC_U(Core::System& system); ~MIC_U(); + void ReloadMic(); + private: /** * MIC::MapSharedMem service function @@ -190,6 +192,8 @@ private: std::unique_ptr impl; }; +void ReloadMic(Core::System& system); + void InstallInterfaces(Core::System& system); } // namespace Service::MIC diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 9574e7bde9..c7311e268d 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -3,17 +3,14 @@ // Refer to the license.txt file included. #include -#if HAVE_CUBEB -#include "audio_core/cubeb_input.h" -#endif #include "audio_core/dsp_interface.h" #include "core/core.h" #include "core/frontend/emu_window.h" -#include "core/frontend/mic.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/service/hid/hid.h" #include "core/hle/service/ir/ir_rst.h" #include "core/hle/service/ir/ir_user.h" +#include "core/hle/service/mic_u.h" #include "core/settings.h" #include "video_core/renderer_base.h" #include "video_core/video_core.h" @@ -61,20 +58,8 @@ void Apply() { if (cam) { cam->ReloadCameraDevices(); } - } - // TODO support mic hotswapping by creating the new impl, and copying any parameters to it. - switch (Settings::values.mic_input_type) { - case Settings::MicInputType::None: - Frontend::Mic::RegisterMic(std::make_shared()); - break; - case Settings::MicInputType::Real: -#if HAVE_CUBEB - Frontend::Mic::RegisterMic(std::make_shared()); -#endif - break; - case Settings::MicInputType::Static: - Frontend::Mic::RegisterMic(std::make_shared()); - break; + + Service::MIC::ReloadMic(system); } } @@ -105,6 +90,8 @@ void LogSettings() { LogSetting("Audio_OutputEngine", Settings::values.sink_id); LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching); LogSetting("Audio_OutputDevice", Settings::values.audio_device_id); + LogSetting("Audio_InputDeviceType", static_cast(Settings::values.mic_input_type)); + LogSetting("Audio_InputDevice", Settings::values.mic_input_device); using namespace Service::CAM; LogSetting("Camera_OuterRightName", Settings::values.camera_name[OuterRightCamera]); LogSetting("Camera_OuterRightConfig", Settings::values.camera_config[OuterRightCamera]);