diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp index 0c8f5b18e0..cbba17632f 100644 --- a/src/audio_core/audio_out.cpp +++ b/src/audio_core/audio_out.cpp @@ -30,8 +30,7 @@ static Stream::Format ChannelsToStreamFormat(u32 num_channels) { StreamPtr AudioOut::OpenStream(u32 sample_rate, u32 num_channels, std::string&& name, Stream::ReleaseCallback&& release_callback) { if (!sink) { - const SinkDetails& sink_details = GetSinkDetails(Settings::values.sink_id); - sink = sink_details.factory(Settings::values.audio_device_id); + sink = CreateSinkFromID(Settings::values.sink_id, Settings::values.audio_device_id); } return std::make_shared( diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp index d31a1c8442..097328901d 100644 --- a/src/audio_core/cubeb_sink.cpp +++ b/src/audio_core/cubeb_sink.cpp @@ -107,7 +107,7 @@ private: static void StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state); }; -CubebSink::CubebSink(std::string target_device_name) { +CubebSink::CubebSink(std::string_view target_device_name) { if (cubeb_init(&ctx, "yuzu", nullptr) != CUBEB_OK) { LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); return; diff --git a/src/audio_core/cubeb_sink.h b/src/audio_core/cubeb_sink.h index 59cbf05e9c..efb9d16342 100644 --- a/src/audio_core/cubeb_sink.h +++ b/src/audio_core/cubeb_sink.h @@ -15,7 +15,7 @@ namespace AudioCore { class CubebSink final : public Sink { public: - explicit CubebSink(std::string device_id); + explicit CubebSink(std::string_view device_id); ~CubebSink() override; SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels, diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h index a78d788934..61a28d5429 100644 --- a/src/audio_core/null_sink.h +++ b/src/audio_core/null_sink.h @@ -10,7 +10,7 @@ namespace AudioCore { class NullSink final : public Sink { public: - explicit NullSink(std::string){}; + explicit NullSink(std::string_view) {} ~NullSink() override = default; SinkStream& AcquireSinkStream(u32 /*sample_rate*/, u32 /*num_channels*/, diff --git a/src/audio_core/sink_details.cpp b/src/audio_core/sink_details.cpp index 67cf1f3b27..a848eb1c9f 100644 --- a/src/audio_core/sink_details.cpp +++ b/src/audio_core/sink_details.cpp @@ -14,31 +14,68 @@ #include "common/logging/log.h" namespace AudioCore { +namespace { +struct SinkDetails { + using FactoryFn = std::unique_ptr (*)(std::string_view); + using ListDevicesFn = std::vector (*)(); -// g_sink_details is ordered in terms of desirability, with the best choice at the top. -const std::vector g_sink_details = { + /// Name for this sink. + const char* id; + /// A method to call to construct an instance of this type of sink. + FactoryFn factory; + /// A method to call to list available devices. + ListDevicesFn list_devices; +}; + +// sink_details is ordered in terms of desirability, with the best choice at the top. +constexpr SinkDetails sink_details[] = { #ifdef HAVE_CUBEB - SinkDetails{"cubeb", &std::make_unique, &ListCubebSinkDevices}, + SinkDetails{"cubeb", + [](std::string_view device_id) -> std::unique_ptr { + return std::make_unique(device_id); + }, + &ListCubebSinkDevices}, #endif - SinkDetails{"null", &std::make_unique, + SinkDetails{"null", + [](std::string_view device_id) -> std::unique_ptr { + return std::make_unique(device_id); + }, [] { return std::vector{"null"}; }}, }; const SinkDetails& GetSinkDetails(std::string_view sink_id) { auto iter = - std::find_if(g_sink_details.begin(), g_sink_details.end(), + std::find_if(std::begin(sink_details), std::end(sink_details), [sink_id](const auto& sink_detail) { return sink_detail.id == sink_id; }); - if (sink_id == "auto" || iter == g_sink_details.end()) { + if (sink_id == "auto" || iter == std::end(sink_details)) { if (sink_id != "auto") { LOG_ERROR(Audio, "AudioCore::SelectSink given invalid sink_id {}", sink_id); } // Auto-select. - // g_sink_details is ordered in terms of desirability, with the best choice at the front. - iter = g_sink_details.begin(); + // sink_details is ordered in terms of desirability, with the best choice at the front. + iter = std::begin(sink_details); } return *iter; } +} // Anonymous namespace + +std::vector GetSinkIDs() { + std::vector sink_ids(std::size(sink_details)); + + std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids), + [](const auto& sink) { return sink.id; }); + + return sink_ids; +} + +std::vector GetDeviceListForSink(std::string_view sink_id) { + return GetSinkDetails(sink_id).list_devices(); +} + +std::unique_ptr CreateSinkFromID(std::string_view sink_id, std::string_view device_id) { + return GetSinkDetails(sink_id).factory(device_id); +} } // namespace AudioCore diff --git a/src/audio_core/sink_details.h b/src/audio_core/sink_details.h index 03534b1875..bc8786270d 100644 --- a/src/audio_core/sink_details.h +++ b/src/audio_core/sink_details.h @@ -4,34 +4,21 @@ #pragma once -#include -#include #include #include -#include #include namespace AudioCore { class Sink; -struct SinkDetails { - using FactoryFn = std::function(std::string)>; - using ListDevicesFn = std::function()>; +/// Retrieves the IDs for all available audio sinks. +std::vector GetSinkIDs(); - SinkDetails(const char* id_, FactoryFn factory_, ListDevicesFn list_devices_) - : id(id_), factory(std::move(factory_)), list_devices(std::move(list_devices_)) {} +/// Gets the list of devices for a particular sink identified by the given ID. +std::vector GetDeviceListForSink(std::string_view sink_id); - /// Name for this sink. - const char* id; - /// A method to call to construct an instance of this type of sink. - FactoryFn factory; - /// A method to call to list available devices. - ListDevicesFn list_devices; -}; - -extern const std::vector g_sink_details; - -const SinkDetails& GetSinkDetails(std::string_view sink_id); +/// Creates an audio sink identified by the given device ID. +std::unique_ptr CreateSinkFromID(std::string_view sink_id, std::string_view device_id); } // namespace AudioCore diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index eb1da0f9eb..5d9ccc6e80 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -17,8 +17,8 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) ui->output_sink_combo_box->clear(); ui->output_sink_combo_box->addItem("auto"); - for (const auto& sink_detail : AudioCore::g_sink_details) { - ui->output_sink_combo_box->addItem(sink_detail.id); + for (const char* id : AudioCore::GetSinkIDs()) { + ui->output_sink_combo_box->addItem(id); } connect(ui->volume_slider, &QSlider::valueChanged, this, @@ -97,8 +97,7 @@ void ConfigureAudio::updateAudioDevices(int sink_index) { ui->audio_device_combo_box->addItem(AudioCore::auto_device_name); const std::string sink_id = ui->output_sink_combo_box->itemText(sink_index).toStdString(); - const std::vector device_list = AudioCore::GetSinkDetails(sink_id).list_devices(); - for (const auto& device : device_list) { + for (const auto& device : AudioCore::GetDeviceListForSink(sink_id)) { ui->audio_device_combo_box->addItem(QString::fromStdString(device)); } }