mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #3909 from MerryMage/rm-SetDevice
sink_details: Tidy-up device listing code
This commit is contained in:
		
						commit
						47d283a1e4
					
				
					 13 changed files with 87 additions and 88 deletions
				
			
		|  | @ -7,7 +7,6 @@ | ||||||
| #include "audio_core/audio_types.h" | #include "audio_core/audio_types.h" | ||||||
| #include "audio_core/cubeb_sink.h" | #include "audio_core/cubeb_sink.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace AudioCore { | namespace AudioCore { | ||||||
| 
 | 
 | ||||||
|  | @ -25,13 +24,12 @@ struct CubebSink::Impl { | ||||||
|     static void StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state); |     static void StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| CubebSink::CubebSink() : impl(std::make_unique<Impl>()) { | CubebSink::CubebSink(std::string target_device_name) : impl(std::make_unique<Impl>()) { | ||||||
|     if (cubeb_init(&impl->ctx, "Citra", nullptr) != CUBEB_OK) { |     if (cubeb_init(&impl->ctx, "Citra", nullptr) != CUBEB_OK) { | ||||||
|         LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); |         LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const char* target_device_name = nullptr; |  | ||||||
|     cubeb_devid output_device = nullptr; |     cubeb_devid output_device = nullptr; | ||||||
| 
 | 
 | ||||||
|     cubeb_stream_params params; |     cubeb_stream_params params; | ||||||
|  | @ -46,27 +44,21 @@ CubebSink::CubebSink() : impl(std::make_unique<Impl>()) { | ||||||
|     if (cubeb_get_min_latency(impl->ctx, ¶ms, &minimum_latency) != CUBEB_OK) |     if (cubeb_get_min_latency(impl->ctx, ¶ms, &minimum_latency) != CUBEB_OK) | ||||||
|         LOG_CRITICAL(Audio_Sink, "Error getting minimum latency"); |         LOG_CRITICAL(Audio_Sink, "Error getting minimum latency"); | ||||||
| 
 | 
 | ||||||
|     cubeb_device_collection collection; |     if (target_device_name != auto_device_name && !target_device_name.empty()) { | ||||||
|     if (cubeb_enumerate_devices(impl->ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) { |         cubeb_device_collection collection; | ||||||
|         LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); |         if (cubeb_enumerate_devices(impl->ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) { | ||||||
|     } else { |             LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); | ||||||
|         if (collection.count >= 1 && Settings::values.audio_device_id != "auto" && |         } else { | ||||||
|             !Settings::values.audio_device_id.empty()) { |             const auto collection_end = collection.device + collection.count; | ||||||
|             target_device_name = Settings::values.audio_device_id.c_str(); |             const auto device = std::find_if(collection.device, collection_end, | ||||||
|         } |                                              [&](const cubeb_device_info& device) { | ||||||
| 
 |                                                  return target_device_name == device.friendly_name; | ||||||
|         for (size_t i = 0; i < collection.count; i++) { |                                              }); | ||||||
|             const cubeb_device_info& device = collection.device[i]; |             if (device != collection_end) { | ||||||
|             if (device.friendly_name) { |                 output_device = device->devid; | ||||||
|                 impl->device_list.emplace_back(device.friendly_name); |  | ||||||
| 
 |  | ||||||
|                 if (target_device_name && strcmp(target_device_name, device.friendly_name) == 0) { |  | ||||||
|                     output_device = device.devid; |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|  |             cubeb_device_collection_destroy(impl->ctx, &collection); | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         cubeb_device_collection_destroy(impl->ctx, &collection); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (cubeb_stream_init(impl->ctx, &impl->stream, "Citra Audio Output", nullptr, nullptr, |     if (cubeb_stream_init(impl->ctx, &impl->stream, "Citra Audio Output", nullptr, nullptr, | ||||||
|  | @ -101,10 +93,6 @@ unsigned int CubebSink::GetNativeSampleRate() const { | ||||||
|     return impl->sample_rate; |     return impl->sample_rate; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<std::string> CubebSink::GetDeviceList() const { |  | ||||||
|     return impl->device_list; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void CubebSink::EnqueueSamples(const s16* samples, size_t sample_count) { | void CubebSink::EnqueueSamples(const s16* samples, size_t sample_count) { | ||||||
|     if (!impl->ctx) |     if (!impl->ctx) | ||||||
|         return; |         return; | ||||||
|  | @ -120,8 +108,6 @@ size_t CubebSink::SamplesInQueue() const { | ||||||
|     return impl->queue.size() / 2; |     return impl->queue.size() / 2; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CubebSink::SetDevice(int device_id) {} |  | ||||||
| 
 |  | ||||||
| long CubebSink::Impl::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | long CubebSink::Impl::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | ||||||
|                                    void* output_buffer, long num_frames) { |                                    void* output_buffer, long num_frames) { | ||||||
|     Impl* impl = static_cast<Impl*>(user_data); |     Impl* impl = static_cast<Impl*>(user_data); | ||||||
|  | @ -146,4 +132,30 @@ long CubebSink::Impl::DataCallback(cubeb_stream* stream, void* user_data, const | ||||||
| 
 | 
 | ||||||
| void CubebSink::Impl::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} | void CubebSink::Impl::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} | ||||||
| 
 | 
 | ||||||
|  | std::vector<std::string> ListCubebSinkDevices() { | ||||||
|  |     std::vector<std::string> device_list; | ||||||
|  |     cubeb* ctx; | ||||||
|  | 
 | ||||||
|  |     if (cubeb_init(&ctx, "Citra Device Enumerator", nullptr) != CUBEB_OK) { | ||||||
|  |         LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     cubeb_device_collection collection; | ||||||
|  |     if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) { | ||||||
|  |         LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); | ||||||
|  |     } else { | ||||||
|  |         for (size_t i = 0; i < collection.count; i++) { | ||||||
|  |             const cubeb_device_info& device = collection.device[i]; | ||||||
|  |             if (device.friendly_name) { | ||||||
|  |                 device_list.emplace_back(device.friendly_name); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         cubeb_device_collection_destroy(ctx, &collection); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     cubeb_destroy(ctx); | ||||||
|  |     return device_list; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace AudioCore
 | } // namespace AudioCore
 | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ namespace AudioCore { | ||||||
| 
 | 
 | ||||||
| class CubebSink final : public Sink { | class CubebSink final : public Sink { | ||||||
| public: | public: | ||||||
|     CubebSink(); |     explicit CubebSink(std::string device_id); | ||||||
|     ~CubebSink() override; |     ~CubebSink() override; | ||||||
| 
 | 
 | ||||||
|     unsigned int GetNativeSampleRate() const override; |     unsigned int GetNativeSampleRate() const override; | ||||||
|  | @ -21,12 +21,11 @@ public: | ||||||
| 
 | 
 | ||||||
|     size_t SamplesInQueue() const override; |     size_t SamplesInQueue() const override; | ||||||
| 
 | 
 | ||||||
|     std::vector<std::string> GetDeviceList() const override; |  | ||||||
|     void SetDevice(int device_id) override; |  | ||||||
| 
 |  | ||||||
| private: | private: | ||||||
|     struct Impl; |     struct Impl; | ||||||
|     std::unique_ptr<Impl> impl; |     std::unique_ptr<Impl> impl; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | std::vector<std::string> ListCubebSinkDevices(); | ||||||
|  | 
 | ||||||
| } // namespace AudioCore
 | } // namespace AudioCore
 | ||||||
|  |  | ||||||
|  | @ -18,9 +18,9 @@ DspInterface::~DspInterface() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DspInterface::SetSink(const std::string& sink_id) { | void DspInterface::SetSink(const std::string& sink_id, const std::string& audio_device) { | ||||||
|     const SinkDetails& sink_details = GetSinkDetails(sink_id); |     const SinkDetails& sink_details = GetSinkDetails(sink_id); | ||||||
|     sink = sink_details.factory(); |     sink = sink_details.factory(audio_device); | ||||||
|     time_stretcher.SetOutputSampleRate(sink->GetNativeSampleRate()); |     time_stretcher.SetOutputSampleRate(sink->GetNativeSampleRate()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -61,7 +61,7 @@ public: | ||||||
|     virtual std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory() = 0; |     virtual std::array<u8, Memory::DSP_RAM_SIZE>& GetDspMemory() = 0; | ||||||
| 
 | 
 | ||||||
|     /// Select the sink to use based on sink id.
 |     /// Select the sink to use based on sink id.
 | ||||||
|     void SetSink(const std::string& sink_id); |     void SetSink(const std::string& sink_id, const std::string& audio_device); | ||||||
|     /// Get the current sink
 |     /// Get the current sink
 | ||||||
|     Sink& GetSink(); |     Sink& GetSink(); | ||||||
|     /// Enable/Disable audio stretching.
 |     /// Enable/Disable audio stretching.
 | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ namespace AudioCore { | ||||||
| 
 | 
 | ||||||
| class NullSink final : public Sink { | class NullSink final : public Sink { | ||||||
| public: | public: | ||||||
|  |     NullSink(std::string) {} | ||||||
|     ~NullSink() override = default; |     ~NullSink() override = default; | ||||||
| 
 | 
 | ||||||
|     unsigned int GetNativeSampleRate() const override { |     unsigned int GetNativeSampleRate() const override { | ||||||
|  | @ -23,12 +24,6 @@ public: | ||||||
|     size_t SamplesInQueue() const override { |     size_t SamplesInQueue() const override { | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     void SetDevice(int device_id) override {} |  | ||||||
| 
 |  | ||||||
|     std::vector<std::string> GetDeviceList() const override { |  | ||||||
|         return {}; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace AudioCore
 | } // namespace AudioCore
 | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ | ||||||
| #include "audio_core/sdl2_sink.h" | #include "audio_core/sdl2_sink.h" | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/settings.h" |  | ||||||
| 
 | 
 | ||||||
| namespace AudioCore { | namespace AudioCore { | ||||||
| 
 | 
 | ||||||
|  | @ -23,7 +22,7 @@ struct SDL2Sink::Impl { | ||||||
|     static void Callback(void* impl_, u8* buffer, int buffer_size_in_bytes); |     static void Callback(void* impl_, u8* buffer, int buffer_size_in_bytes); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| SDL2Sink::SDL2Sink() : impl(std::make_unique<Impl>()) { | SDL2Sink::SDL2Sink(std::string device_name) : impl(std::make_unique<Impl>()) { | ||||||
|     if (SDL_Init(SDL_INIT_AUDIO) < 0) { |     if (SDL_Init(SDL_INIT_AUDIO) < 0) { | ||||||
|         LOG_CRITICAL(Audio_Sink, "SDL_Init(SDL_INIT_AUDIO) failed with: {}", SDL_GetError()); |         LOG_CRITICAL(Audio_Sink, "SDL_Init(SDL_INIT_AUDIO) failed with: {}", SDL_GetError()); | ||||||
|         impl->audio_device_id = 0; |         impl->audio_device_id = 0; | ||||||
|  | @ -42,24 +41,16 @@ SDL2Sink::SDL2Sink() : impl(std::make_unique<Impl>()) { | ||||||
|     SDL_AudioSpec obtained_audiospec; |     SDL_AudioSpec obtained_audiospec; | ||||||
|     SDL_zero(obtained_audiospec); |     SDL_zero(obtained_audiospec); | ||||||
| 
 | 
 | ||||||
|     int device_count = SDL_GetNumAudioDevices(0); |  | ||||||
|     device_list.clear(); |  | ||||||
|     for (int i = 0; i < device_count; ++i) { |  | ||||||
|         device_list.push_back(SDL_GetAudioDeviceName(i, 0)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const char* device = nullptr; |     const char* device = nullptr; | ||||||
| 
 |     if (device_name != auto_device_name && !device_name.empty()) { | ||||||
|     if (device_count >= 1 && Settings::values.audio_device_id != "auto" && |         device = device_name.c_str(); | ||||||
|         !Settings::values.audio_device_id.empty()) { |  | ||||||
|         device = Settings::values.audio_device_id.c_str(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     impl->audio_device_id = SDL_OpenAudioDevice( |     impl->audio_device_id = SDL_OpenAudioDevice( | ||||||
|         device, false, &desired_audiospec, &obtained_audiospec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); |         device, false, &desired_audiospec, &obtained_audiospec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); | ||||||
|     if (impl->audio_device_id <= 0) { |     if (impl->audio_device_id <= 0) { | ||||||
|         LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed with code {} for device \"{}\"", |         LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed with code {} for device \"{}\"", | ||||||
|                      impl->audio_device_id, Settings::values.audio_device_id); |                      impl->audio_device_id, device_name); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -83,10 +74,6 @@ unsigned int SDL2Sink::GetNativeSampleRate() const { | ||||||
|     return impl->sample_rate; |     return impl->sample_rate; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<std::string> SDL2Sink::GetDeviceList() const { |  | ||||||
|     return device_list; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SDL2Sink::EnqueueSamples(const s16* samples, size_t sample_count) { | void SDL2Sink::EnqueueSamples(const s16* samples, size_t sample_count) { | ||||||
|     if (impl->audio_device_id <= 0) |     if (impl->audio_device_id <= 0) | ||||||
|         return; |         return; | ||||||
|  | @ -114,10 +101,6 @@ size_t SDL2Sink::SamplesInQueue() const { | ||||||
|     return total_size; |     return total_size; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SDL2Sink::SetDevice(int device_id) { |  | ||||||
|     this->device_id = device_id; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SDL2Sink::Impl::Callback(void* impl_, u8* buffer, int buffer_size_in_bytes) { | void SDL2Sink::Impl::Callback(void* impl_, u8* buffer, int buffer_size_in_bytes) { | ||||||
|     Impl* impl = reinterpret_cast<Impl*>(impl_); |     Impl* impl = reinterpret_cast<Impl*>(impl_); | ||||||
| 
 | 
 | ||||||
|  | @ -144,4 +127,21 @@ void SDL2Sink::Impl::Callback(void* impl_, u8* buffer, int buffer_size_in_bytes) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::vector<std::string> ListSDL2SinkDevices() { | ||||||
|  |     if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { | ||||||
|  |         LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem failed with: {}", SDL_GetError()); | ||||||
|  |         return {}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::vector<std::string> device_list; | ||||||
|  |     const int device_count = SDL_GetNumAudioDevices(0); | ||||||
|  |     for (int i = 0; i < device_count; ++i) { | ||||||
|  |         device_list.push_back(SDL_GetAudioDeviceName(i, 0)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     SDL_QuitSubSystem(SDL_INIT_AUDIO); | ||||||
|  | 
 | ||||||
|  |     return device_list; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace AudioCore
 | } // namespace AudioCore
 | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ namespace AudioCore { | ||||||
| 
 | 
 | ||||||
| class SDL2Sink final : public Sink { | class SDL2Sink final : public Sink { | ||||||
| public: | public: | ||||||
|     SDL2Sink(); |     explicit SDL2Sink(std::string device_id); | ||||||
|     ~SDL2Sink() override; |     ~SDL2Sink() override; | ||||||
| 
 | 
 | ||||||
|     unsigned int GetNativeSampleRate() const override; |     unsigned int GetNativeSampleRate() const override; | ||||||
|  | @ -21,14 +21,11 @@ public: | ||||||
| 
 | 
 | ||||||
|     size_t SamplesInQueue() const override; |     size_t SamplesInQueue() const override; | ||||||
| 
 | 
 | ||||||
|     std::vector<std::string> GetDeviceList() const override; |  | ||||||
|     void SetDevice(int device_id) override; |  | ||||||
| 
 |  | ||||||
| private: | private: | ||||||
|     struct Impl; |     struct Impl; | ||||||
|     std::unique_ptr<Impl> impl; |     std::unique_ptr<Impl> impl; | ||||||
|     int device_id; |  | ||||||
|     std::vector<std::string> device_list; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | std::vector<std::string> ListSDL2SinkDevices(); | ||||||
|  | 
 | ||||||
| } // namespace AudioCore
 | } // namespace AudioCore
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,8 @@ | ||||||
| 
 | 
 | ||||||
| namespace AudioCore { | namespace AudioCore { | ||||||
| 
 | 
 | ||||||
|  | constexpr char auto_device_name[] = "auto"; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * This class is an interface for an audio sink. An audio sink accepts samples in stereo signed |  * This class is an interface for an audio sink. An audio sink accepts samples in stereo signed | ||||||
|  * PCM16 format to be output. Sinks *do not* handle resampling and expect the correct sample rate. |  * PCM16 format to be output. Sinks *do not* handle resampling and expect the correct sample rate. | ||||||
|  | @ -31,15 +33,6 @@ public: | ||||||
| 
 | 
 | ||||||
|     /// Samples enqueued that have not been played yet.
 |     /// Samples enqueued that have not been played yet.
 | ||||||
|     virtual std::size_t SamplesInQueue() const = 0; |     virtual std::size_t SamplesInQueue() const = 0; | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Sets the desired output device. |  | ||||||
|      * @param device_id ID of the desired device. |  | ||||||
|      */ |  | ||||||
|     virtual void SetDevice(int device_id) = 0; |  | ||||||
| 
 |  | ||||||
|     /// Returns the list of available devices.
 |  | ||||||
|     virtual std::vector<std::string> GetDeviceList() const = 0; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace AudioCore
 | } // namespace AudioCore
 | ||||||
|  |  | ||||||
|  | @ -21,12 +21,13 @@ namespace AudioCore { | ||||||
| // g_sink_details is ordered in terms of desirability, with the best choice at the top.
 | // g_sink_details is ordered in terms of desirability, with the best choice at the top.
 | ||||||
| const std::vector<SinkDetails> g_sink_details = { | const std::vector<SinkDetails> g_sink_details = { | ||||||
| #ifdef HAVE_CUBEB | #ifdef HAVE_CUBEB | ||||||
|     {"cubeb", []() { return std::make_unique<CubebSink>(); }}, |     SinkDetails{"cubeb", &std::make_unique<CubebSink, std::string>, &ListCubebSinkDevices}, | ||||||
| #endif | #endif | ||||||
| #ifdef HAVE_SDL2 | #ifdef HAVE_SDL2 | ||||||
|     {"sdl2", []() { return std::make_unique<SDL2Sink>(); }}, |     SinkDetails{"sdl2", &std::make_unique<SDL2Sink, std::string>, &ListSDL2SinkDevices}, | ||||||
| #endif | #endif | ||||||
|     {"null", []() { return std::make_unique<NullSink>(); }}, |     SinkDetails{"null", &std::make_unique<NullSink, std::string>, | ||||||
|  |                 [] { return std::vector<std::string>{"null"}; }}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const SinkDetails& GetSinkDetails(std::string sink_id) { | const SinkDetails& GetSinkDetails(std::string sink_id) { | ||||||
|  |  | ||||||
|  | @ -13,13 +13,16 @@ namespace AudioCore { | ||||||
| class Sink; | class Sink; | ||||||
| 
 | 
 | ||||||
| struct SinkDetails { | struct SinkDetails { | ||||||
|     SinkDetails(const char* id_, std::function<std::unique_ptr<Sink>()> factory_) |     SinkDetails(const char* id_, std::function<std::unique_ptr<Sink>(std::string)> factory_, | ||||||
|         : id(id_), factory(factory_) {} |                 std::function<std::vector<std::string>()> list_devices_) | ||||||
|  |         : id(id_), factory(factory_), list_devices(list_devices_) {} | ||||||
| 
 | 
 | ||||||
|     /// Name for this sink.
 |     /// Name for this sink.
 | ||||||
|     const char* id; |     const char* id; | ||||||
|     /// A method to call to construct an instance of this type of sink.
 |     /// A method to call to construct an instance of this type of sink.
 | ||||||
|     std::function<std::unique_ptr<Sink>()> factory; |     std::function<std::unique_ptr<Sink>(std::string device_id)> factory; | ||||||
|  |     /// A method to call to list available devices.
 | ||||||
|  |     std::function<std::vector<std::string>()> list_devices; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern const std::vector<SinkDetails> g_sink_details; | extern const std::vector<SinkDetails> g_sink_details; | ||||||
|  |  | ||||||
|  | @ -65,11 +65,10 @@ void ConfigureAudio::applyConfiguration() { | ||||||
| 
 | 
 | ||||||
| void ConfigureAudio::updateAudioDevices(int sink_index) { | void ConfigureAudio::updateAudioDevices(int sink_index) { | ||||||
|     ui->audio_device_combo_box->clear(); |     ui->audio_device_combo_box->clear(); | ||||||
|     ui->audio_device_combo_box->addItem("auto"); |     ui->audio_device_combo_box->addItem(AudioCore::auto_device_name); | ||||||
| 
 | 
 | ||||||
|     std::string sink_id = ui->output_sink_combo_box->itemText(sink_index).toStdString(); |     std::string sink_id = ui->output_sink_combo_box->itemText(sink_index).toStdString(); | ||||||
|     std::vector<std::string> device_list = |     std::vector<std::string> device_list = AudioCore::GetSinkDetails(sink_id).list_devices(); | ||||||
|         AudioCore::GetSinkDetails(sink_id).factory()->GetDeviceList(); |  | ||||||
|     for (const auto& device : device_list) { |     for (const auto& device : device_list) { | ||||||
|         ui->audio_device_combo_box->addItem(device.c_str()); |         ui->audio_device_combo_box->addItem(device.c_str()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -166,7 +166,7 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     dsp_core = std::make_unique<AudioCore::DspHle>(); |     dsp_core = std::make_unique<AudioCore::DspHle>(); | ||||||
|     dsp_core->SetSink(Settings::values.sink_id); |     dsp_core->SetSink(Settings::values.sink_id, Settings::values.audio_device_id); | ||||||
|     dsp_core->EnableStretching(Settings::values.enable_audio_stretching); |     dsp_core->EnableStretching(Settings::values.enable_audio_stretching); | ||||||
| 
 | 
 | ||||||
|     telemetry_session = std::make_unique<Core::TelemetrySession>(); |     telemetry_session = std::make_unique<Core::TelemetrySession>(); | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ void Apply() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (Core::System::GetInstance().IsPoweredOn()) { |     if (Core::System::GetInstance().IsPoweredOn()) { | ||||||
|         Core::DSP().SetSink(values.sink_id); |         Core::DSP().SetSink(values.sink_id, values.audio_device_id); | ||||||
|         Core::DSP().EnableStretching(values.enable_audio_stretching); |         Core::DSP().EnableStretching(values.enable_audio_stretching); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue