From b6db19a5c67e4b58bc2555d7ff83f97bdba6811b Mon Sep 17 00:00:00 2001 From: Tim Mayberry Date: Wed, 1 Apr 2015 16:55:34 +1000 Subject: Add host api/driver selection to PortaudioBackend --- libs/backends/portaudio/portaudio_backend.cc | 29 ++++++++++- libs/backends/portaudio/portaudio_backend.h | 5 ++ libs/backends/portaudio/portaudio_io.cc | 78 +++++++++++++++++++++++----- libs/backends/portaudio/portaudio_io.h | 9 +++- 4 files changed, 107 insertions(+), 14 deletions(-) diff --git a/libs/backends/portaudio/portaudio_backend.cc b/libs/backends/portaudio/portaudio_backend.cc index 0277ca1270..3e24ff28f0 100644 --- a/libs/backends/portaudio/portaudio_backend.cc +++ b/libs/backends/portaudio/portaudio_backend.cc @@ -89,10 +89,37 @@ PortAudioBackend::is_realtime () const return true; } +bool +PortAudioBackend::requires_driver_selection() const +{ + // we could do this but implementation would need changing + /* + if (enumerate_drivers().size() == 1) { + return false; + } + */ + return true; +} + +std::vector +PortAudioBackend::enumerate_drivers () const +{ + std::vector currently_available; + _pcmio->host_api_list (currently_available); + return currently_available; +} + +int +PortAudioBackend::set_driver (const std::string& name) +{ + _target_driver = name; + return 0; +} + std::vector PortAudioBackend::enumerate_devices () const { - _pcmio->discover(); + _pcmio->discover(_target_driver); _audio_device_status.clear(); std::map devices; _pcmio->device_list(devices); diff --git a/libs/backends/portaudio/portaudio_backend.h b/libs/backends/portaudio/portaudio_backend.h index 36aebe0f14..432598263d 100644 --- a/libs/backends/portaudio/portaudio_backend.h +++ b/libs/backends/portaudio/portaudio_backend.h @@ -160,6 +160,10 @@ class PortAudioBackend : public AudioBackend { std::string name () const; bool is_realtime () const; + bool requires_driver_selection() const; + std::vector enumerate_drivers () const; + int set_driver (const std::string&); + std::vector enumerate_devices () const; std::vector available_sample_rates (const std::string& device) const; std::vector available_buffer_sizes (const std::string& device) const; @@ -313,6 +317,7 @@ class PortAudioBackend : public AudioBackend { static std::vector _audio_device_status; static std::vector _midi_device_status; + std::string _target_driver; mutable std::string _audio_device; std::string _midi_driver_option; diff --git a/libs/backends/portaudio/portaudio_io.cc b/libs/backends/portaudio/portaudio_io.cc index d8a7fc9cf1..0b2256496d 100644 --- a/libs/backends/portaudio/portaudio_io.cc +++ b/libs/backends/portaudio/portaudio_io.cc @@ -133,28 +133,80 @@ PortAudioIO::device_list (std::map &devices) const { } } -void -PortAudioIO::discover() +bool +PortAudioIO::initialize_pa () { - for (std::map::const_iterator i = _devices.begin (); i != _devices.end(); ++i) { - delete i->second; - } - _devices.clear(); - PaError err = paNoError; if (!_initialized) { err = Pa_Initialize(); + if (err != paNoError) { + return false; + } + _initialized = true; } - if (err != paNoError) { - return; + + return true; +} + +void +PortAudioIO::host_api_list (std::vector& api_list) +{ + if (!initialize_pa()) return; + + PaHostApiIndex count = Pa_GetHostApiCount(); + + if (count < 0) return; + + for (int i = 0; i < count; ++i) { + const PaHostApiInfo* info = Pa_GetHostApiInfo (i); + if (info->name != NULL) { // possible? + api_list.push_back (info->name); + } } +} - _initialized = true; +PaHostApiIndex +PortAudioIO::get_host_api_index_from_name (const std::string& name) +{ + if (!initialize_pa()) return -1; + + PaHostApiIndex count = Pa_GetHostApiCount(); + + if (count < 0) return -1; + + for (int i = 0; i < count; ++i) { + const PaHostApiInfo* info = Pa_GetHostApiInfo (i); + if (info->name != NULL) { // possible? + if (name == info->name) return i; + } + } + return -1; +} + +void +PortAudioIO::discover(const std::string& host_api) +{ + if (!initialize_pa()) return; + + for (std::map::const_iterator i = _devices.begin (); i != _devices.end(); ++i) { + delete i->second; + } + _devices.clear(); + + PaHostApiIndex host_api_index = get_host_api_index_from_name (host_api); + + if (host_api_index < 0) return; + + const PaHostApiInfo* info = Pa_GetHostApiInfo (host_api_index); + + if (info == NULL) return; + PaDeviceIndex default_input = info->defaultInputDevice; + PaDeviceIndex default_output = info->defaultOutputDevice; { - const PaDeviceInfo* nfo_i = Pa_GetDeviceInfo(Pa_GetDefaultInputDevice()); - const PaDeviceInfo* nfo_o = Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice()); + const PaDeviceInfo* nfo_i = Pa_GetDeviceInfo(default_input); + const PaDeviceInfo* nfo_o = Pa_GetDeviceInfo(default_output); if (nfo_i && nfo_o) { _devices.insert (std::pair (-1, new paDevice("Default", @@ -171,7 +223,9 @@ PortAudioIO::discover() for (int i = 0 ; i < n_devices; ++i) { const PaDeviceInfo* nfo = Pa_GetDeviceInfo(i); + if (!nfo) continue; + if (nfo->hostApi != host_api_index) continue; #ifndef NDEBUG printf(" (%d) '%s' in: %d (lat: %.1f .. %.1f) out: %d (lat: %.1f .. %.1f) sr:%.2f\n", i, nfo->name, diff --git a/libs/backends/portaudio/portaudio_io.h b/libs/backends/portaudio/portaudio_io.h index 532dc66df6..bbc3f9a4d0 100644 --- a/libs/backends/portaudio/portaudio_io.h +++ b/libs/backends/portaudio/portaudio_io.h @@ -37,7 +37,12 @@ public: int state (void) const { return _state; } - void discover(); + bool initialize_pa (); + + void host_api_list (std::vector&); + PaHostApiIndex get_host_api_index_from_name (const std::string& name); + + void discover(const std::string& host_api); void device_list (std::map &devices) const; int available_sample_rates (int device_id, std::vector& sampleRates); @@ -96,6 +101,8 @@ private: }; std::map _devices; + + std::string _host_api; }; } // namespace -- cgit v1.2.3