Audio Core: Implemented feedback from comments

Worked with the Sink abstraction and tuned the "Device Selection"
configuration so that the Device List is automatically populated when
the Sink is changed.
This hopefully addresses the concerns and recommendations mentioned in
the comments of the PR.
This commit is contained in:
Andy Tran 2016-07-15 10:42:13 +10:00
parent 9bc8a230b7
commit 96cba3e719
13 changed files with 45 additions and 40 deletions

View File

@ -71,13 +71,6 @@ void SelectSink(std::string sink_id) {
DSP::HLE::SetSink(iter->factory()); DSP::HLE::SetSink(iter->factory());
} }
void SelectDevice(std::string device_id){
if (device_id == "") {
LOG_ERROR(Audio, "AudioCore::SelectDevice given invalid device_id");
return;
}
}
void Shutdown() { void Shutdown() {
CoreTiming::UnscheduleEvent(tick_event, 0); CoreTiming::UnscheduleEvent(tick_event, 0);
DSP::HLE::Shutdown(); DSP::HLE::Shutdown();

View File

@ -23,9 +23,6 @@ void AddAddressSpace(Kernel::VMManager& vm_manager);
/// Select the sink to use based on sink id. /// Select the sink to use based on sink id.
void SelectSink(std::string sink_id); void SelectSink(std::string sink_id);
/// Select the device to use based on device id.
void SelectDevice(std::string device_id);
/// Shutdown Audio Core /// Shutdown Audio Core
void Shutdown(); void Shutdown();

View File

@ -28,7 +28,7 @@ public:
void SetDevice(int device_id) override {} void SetDevice(int device_id) override {}
std::map<int, std::string>* GetDeviceMap() override { std::vector<std::string>* GetDeviceMap() override {
return nullptr; return nullptr;
} }
}; };

View File

@ -50,12 +50,12 @@ SDL2Sink::SDL2Sink() : impl(std::make_unique<Impl>()) {
int device_count = SDL_GetNumAudioDevices(0); int device_count = SDL_GetNumAudioDevices(0);
device_map.clear(); device_map.clear();
for (int i = 0; i < device_count; ++i) { for (int i = 0; i < device_count; ++i) {
device_map[i] = SDL_GetAudioDeviceName(i, 0); device_map.push_back(SDL_GetAudioDeviceName(i, 0));
} }
if (device_count < 1 || if (device_count < 1 ||
Settings::values.audio_device_id == "auto" || Settings::values.audio_device_id == "auto" ||
Settings::values.audio_device_id == "") { Settings::values.audio_device_id.empty()) {
impl->audio_device_id = SDL_OpenAudioDevice(nullptr, false, &desired_audiospec, &obtained_audiospec, SDL_AUDIO_ALLOW_ANY_CHANGE); impl->audio_device_id = SDL_OpenAudioDevice(nullptr, false, &desired_audiospec, &obtained_audiospec, SDL_AUDIO_ALLOW_ANY_CHANGE);
if (impl->audio_device_id <= 0) { if (impl->audio_device_id <= 0) {
LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed with code %d for device \"auto\"", impl->audio_device_id); LOG_CRITICAL(Audio_Sink, "SDL_OpenAudioDevice failed with code %d for device \"auto\"", impl->audio_device_id);
@ -91,6 +91,10 @@ unsigned int SDL2Sink::GetNativeSampleRate() const {
return impl->sample_rate; return impl->sample_rate;
} }
std::vector<std::string>* SDL2Sink::GetDeviceMap() {
return &device_map;
}
void SDL2Sink::EnqueueSamples(const std::vector<s16>& samples) { void SDL2Sink::EnqueueSamples(const std::vector<s16>& samples) {
if (impl->audio_device_id <= 0) if (impl->audio_device_id <= 0)
return; return;
@ -123,10 +127,6 @@ void SDL2Sink::SetDevice(int _device_id) {
this->device_id = _device_id; this->device_id = _device_id;
} }
std::map<int, std::string>* SDL2Sink::GetDeviceMap() {
return &device_map;
}
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_);

View File

@ -23,16 +23,14 @@ public:
size_t SamplesInQueue() const override; size_t SamplesInQueue() const override;
std::map<int, std::string>* GetDeviceMap(); std::vector<std::string>* GetDeviceMap() override;
void SetDevice(int _device_id); void SetDevice(int _device_id);
private: private:
struct Impl; struct Impl;
std::unique_ptr<Impl> impl; std::unique_ptr<Impl> impl;
int device_id; int device_id;
std::map<int, std::string> device_map; std::vector<std::string> device_map;
}; };
} // namespace AudioCore } // namespace AudioCore

View File

@ -5,7 +5,6 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <map>
#include "common/common_types.h" #include "common/common_types.h"
@ -32,7 +31,7 @@ public:
virtual std::size_t SamplesInQueue() const = 0; virtual std::size_t SamplesInQueue() const = 0;
virtual void SetDevice(int device_id) = 0; virtual void SetDevice(int device_id) = 0;
virtual std::map<int, std::string>* GetDeviceMap() = 0; virtual std::vector<std::string>* GetDeviceMap() = 0;
}; };
} // namespace } // namespace

View File

@ -22,11 +22,4 @@ const std::vector<SinkDetails> g_sink_details = {
{ "null", []() { return std::make_unique<NullSink>(); } }, { "null", []() { return std::make_unique<NullSink>(); } },
}; };
#ifdef HAVE_SDL2
SDL2Sink sink;
const std::map<int, std::string> g_device_map = *sink.GetDeviceMap();
#else
const std::map<int, std::string> g_device_map = { {0, "null"} };
#endif
} // namespace AudioCore } // namespace AudioCore

View File

@ -7,7 +7,6 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <map>
namespace AudioCore { namespace AudioCore {
@ -24,6 +23,5 @@ struct SinkDetails {
}; };
extern const std::vector<SinkDetails> g_sink_details; extern const std::vector<SinkDetails> g_sink_details;
extern const std::map<int, std::string> g_device_map;
} // namespace AudioCore } // namespace AudioCore

View File

@ -78,6 +78,7 @@ void Config::ReadValues() {
// Audio // Audio
Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto"); Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto");
Settings::values.audio_device_id = sdl2_config->Get("Audio", "output_device", "auto");
// Data Storage // Data Storage
Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true);

View File

@ -2,12 +2,15 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "audio_core/audio_core.h"
#include "audio_core/sink.h"
#include "audio_core/sink_details.h" #include "audio_core/sink_details.h"
#include "citra_qt/configure_audio.h" #include "citra_qt/configure_audio.h"
#include "ui_configure_audio.h" #include "ui_configure_audio.h"
#include "core/settings.h" #include "core/settings.h"
#include <memory>
ConfigureAudio::ConfigureAudio(QWidget* parent) : ConfigureAudio::ConfigureAudio(QWidget* parent) :
QWidget(parent), QWidget(parent),
@ -21,18 +24,15 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) :
ui->output_sink_combo_box->addItem(sink_detail.id); ui->output_sink_combo_box->addItem(sink_detail.id);
} }
ui->audio_device_combo_box->clear();
ui->audio_device_combo_box->addItem("auto");
for (const auto& device : AudioCore::g_device_map) {
ui->audio_device_combo_box->addItem(device.second.c_str());
}
this->setConfiguration(); this->setConfiguration();
connect(ui->output_sink_combo_box, SIGNAL(currentIndexChanged(int)),
this, SLOT(updateAudioDevices(int)));
} }
ConfigureAudio::~ConfigureAudio() { ConfigureAudio::~ConfigureAudio() {
} }
void ConfigureAudio::setConfiguration() { void ConfigureAudio::setConfiguration() {
int new_sink_index = 0; int new_sink_index = 0;
for (int index = 0; index < ui->output_sink_combo_box->count(); index++) { for (int index = 0; index < ui->output_sink_combo_box->count(); index++) {
@ -43,6 +43,8 @@ void ConfigureAudio::setConfiguration() {
} }
ui->output_sink_combo_box->setCurrentIndex(new_sink_index); ui->output_sink_combo_box->setCurrentIndex(new_sink_index);
// The device list cannot be pre-populated (nor listed) until the output sink is known.
updateAudioDevices(new_sink_index);
int new_device_index = -1; int new_device_index = -1;
for (int index = 0; index < ui->audio_device_combo_box->count(); index++) { for (int index = 0; index < ui->audio_device_combo_box->count(); index++) {
@ -59,3 +61,26 @@ void ConfigureAudio::applyConfiguration() {
Settings::values.audio_device_id = ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()).toStdString(); Settings::values.audio_device_id = ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()).toStdString();
Settings::Apply(); Settings::Apply();
} }
void ConfigureAudio::updateAudioDevices(int sink_index) {
ui->audio_device_combo_box->clear();
ui->audio_device_combo_box->addItem("auto");
// If the current sink is set to "auto", the "front" sink is selected.
auto quick_sink_populate_device = AudioCore::g_sink_details[0];
if (sink_index > 0) {
// Case where the sink is pointed to a directly known sink device (NullSink, SDL2Sink).
// The first index (0) should be "auto", which is not in the vector list (-1).
quick_sink_populate_device = AudioCore::g_sink_details[sink_index - 1];
}
auto iter = quick_sink_populate_device.factory();
// Prevent accessing a null device list.
if (std::move(iter)->GetDeviceMap()) {
for (const auto& device : *(std::move(iter)->GetDeviceMap())) {
ui->audio_device_combo_box->addItem(device.c_str());
}
}
}

View File

@ -20,6 +20,9 @@ public:
void applyConfiguration(); void applyConfiguration();
public slots:
void updateAudioDevices(int sinkIndex);
private: private:
void setConfiguration(); void setConfiguration();

View File

@ -24,7 +24,6 @@ void Apply() {
VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution; VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution;
AudioCore::SelectSink(values.sink_id); AudioCore::SelectSink(values.sink_id);
AudioCore::SelectDevice(values.audio_device_id);
} }
} // namespace } // namespace

View File

@ -6,7 +6,6 @@
#include <string> #include <string>
#include <array> #include <array>
#include <map>
#include "common/common_types.h" #include "common/common_types.h"