From 5c8f395503d00329d0cf228405591cbf0887d8c1 Mon Sep 17 00:00:00 2001 From: casey langen Date: Thu, 29 Dec 2022 13:59:11 -0800 Subject: [PATCH] Add output device enumeration --- src/plugins/portaudioout/PortAudioOut.cpp | 69 ++++++++++++++++++----- src/plugins/portaudioout/PortAudioOut.h | 1 + 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/plugins/portaudioout/PortAudioOut.cpp b/src/plugins/portaudioout/PortAudioOut.cpp index c9d59ee17..acc2ccf2d 100644 --- a/src/plugins/portaudioout/PortAudioOut.cpp +++ b/src/plugins/portaudioout/PortAudioOut.cpp @@ -51,18 +51,13 @@ using namespace musik::core::sdk; #endif #define PREF_DEFAULT_SAMPLE_RATE "default_sample_rate" +#define PREF_DEFAULT_DEVICE "default_device" #define TAG "PortAudioOut" -static int defaultSampleRate = 48000; +static int kDefaultSampleRate = 48000; static IPreferences* prefs = nullptr; static IDebug* debug = nullptr; -static void reloadMultiplier() { - if (::prefs) { - ::defaultSampleRate = prefs->GetInt(PREF_DEFAULT_SAMPLE_RATE, defaultSampleRate); - } -} - extern "C" DLLEXPORT void SetDebug(IDebug* debug) { ::debug = debug; } @@ -73,7 +68,7 @@ extern "C" DLLEXPORT void SetPreferences(IPreferences* prefs) { extern "C" DLLEXPORT musik::core::sdk::ISchema* GetSchema() { auto schema = new TSchema<>(); - schema->AddInt(PREF_DEFAULT_SAMPLE_RATE, defaultSampleRate, 4096, 192000); + schema->AddInt(PREF_DEFAULT_SAMPLE_RATE, kDefaultSampleRate, 4096, 192000); return schema; } @@ -87,6 +82,26 @@ static void logPaError(const std::string& method, PaError error) { } } +class PortAudioDevice : public IDevice { + public: + PortAudioDevice(const std::string& name) { this->name = name; } + virtual void Release() override { delete this; } + virtual const char* Name() const override { return name.c_str(); } + virtual const char* Id() const override { return name.c_str(); } + private: + std::string name; +}; + +class PortAudioDeviceList : public musik::core::sdk::IDeviceList { + public: + virtual void Release() override { delete this; } + virtual size_t Count() const override { return devices.size(); } + virtual const IDevice* At(size_t index) const override { return &devices.at(index); } + void Add(const std::string& name) { devices.push_back(PortAudioDevice(name)); } + private: + std::vector devices; +}; + PortAudioOut::PortAudioOut() { this->volume = 1.0f; this->state = StateStopped; @@ -95,6 +110,10 @@ PortAudioOut::PortAudioOut() { PortAudioOut::~PortAudioOut() { logPaError("Pa_Terminate", Pa_Terminate()); + if (this->deviceList) { + this->deviceList->Release(); + this->deviceList = nullptr; + } } void PortAudioOut::Release() { @@ -106,7 +125,6 @@ void PortAudioOut::Pause() { } void PortAudioOut::Resume() { - reloadMultiplier(); this->state = StatePlaying; } @@ -127,15 +145,40 @@ void PortAudioOut::Drain() { } IDeviceList* PortAudioOut::GetDeviceList() { - return nullptr; + PortAudioDeviceList* result = new PortAudioDeviceList(); + PaDeviceIndex count = Pa_GetDeviceCount(); + for (PaDeviceIndex i = 0; i < count; i++) { + const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(i); + if (deviceInfo && deviceInfo->maxOutputChannels > 0) { + if (deviceInfo->name) { + const std::string name(deviceInfo->name); + if (name != "default") { + result->Add(deviceInfo->name); + } + } + } + } + return result; } bool PortAudioOut::SetDefaultDevice(const char* deviceId) { - return false; + ::prefs->SetString(PREF_DEFAULT_DEVICE, deviceId ? deviceId : ""); + return true; } IDevice* PortAudioOut::GetDefaultDevice() { - return nullptr; + if (!this->deviceList) { + this->deviceList = this->GetDeviceList(); + } + const std::string defaultDeviceName = + getPreferenceString(::prefs, PREF_DEFAULT_DEVICE, "default"); + for (int i = 0; i < this->deviceList->Count(); i++) { + auto device = this->deviceList->At(i); + if (device->Name() == defaultDeviceName) { + return new PortAudioDevice(defaultDeviceName); + } + } + return new PortAudioDevice("default"); } OutputState PortAudioOut::Play(IBuffer *buffer, IBufferProvider *provider) { @@ -155,5 +198,5 @@ double PortAudioOut::Latency() { } int PortAudioOut::GetDefaultSampleRate() { - return defaultSampleRate; + return kDefaultSampleRate; } diff --git a/src/plugins/portaudioout/PortAudioOut.h b/src/plugins/portaudioout/PortAudioOut.h index 147084a88..d23bce292 100644 --- a/src/plugins/portaudioout/PortAudioOut.h +++ b/src/plugins/portaudioout/PortAudioOut.h @@ -71,6 +71,7 @@ class PortAudioOut : public IOutput { StatePlaying }; + IDeviceList* deviceList { nullptr }; State state; double volume; };