Add host api/driver selection to PortaudioBackend
authorTim Mayberry <mojofunk@gmail.com>
Wed, 1 Apr 2015 06:55:34 +0000 (16:55 +1000)
committerTim Mayberry <mojofunk@gmail.com>
Thu, 30 Jul 2015 23:59:54 +0000 (09:59 +1000)
libs/backends/portaudio/portaudio_backend.cc
libs/backends/portaudio/portaudio_backend.h
libs/backends/portaudio/portaudio_io.cc
libs/backends/portaudio/portaudio_io.h

index 0277ca12706a91231075f0f5e00fb0f31a284197..3e24ff28f0b0f5d72b7c1e338b7d0a16461a2b13 100644 (file)
@@ -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<std::string>
+PortAudioBackend::enumerate_drivers () const
+{
+       std::vector<std::string> 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<AudioBackend::DeviceStatus>
 PortAudioBackend::enumerate_devices () const
 {
-       _pcmio->discover();
+       _pcmio->discover(_target_driver);
        _audio_device_status.clear();
        std::map<int, std::string> devices;
        _pcmio->device_list(devices);
index 36aebe0f14a2b29ad914810798cb2e726d3fd462..432598263dfecc45c6ef2f80d23ed5335e0eaa23 100644 (file)
@@ -160,6 +160,10 @@ class PortAudioBackend : public AudioBackend {
                std::string name () const;
                bool is_realtime () const;
 
+               bool requires_driver_selection() const;
+               std::vector<std::string> enumerate_drivers () const;
+               int set_driver (const std::string&);
+
                std::vector<DeviceStatus> enumerate_devices () const;
                std::vector<float> available_sample_rates (const std::string& device) const;
                std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
@@ -313,6 +317,7 @@ class PortAudioBackend : public AudioBackend {
                static std::vector<AudioBackend::DeviceStatus> _audio_device_status;
                static std::vector<AudioBackend::DeviceStatus> _midi_device_status;
 
+               std::string  _target_driver;
                mutable std::string _audio_device;
                std::string _midi_driver_option;
 
index d8a7fc9cf140c280ec06f051707b9da4fdc557ce..0b2256496db9b0910d00833062f38e1b43a6bace 100644 (file)
@@ -133,28 +133,80 @@ PortAudioIO::device_list (std::map<int, std::string> &devices) const {
        }
 }
 
-void
-PortAudioIO::discover()
+bool
+PortAudioIO::initialize_pa ()
 {
-       for (std::map<int, paDevice*>::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<std::string>& 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<int, paDevice*>::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<int, paDevice*> (-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,
index 532dc66df6db1f69375288e7a06cf8c2815a27fd..bbc3f9a4d00ac5a0303b9ccaaf579d07945bdcdd 100644 (file)
@@ -37,7 +37,12 @@ public:
 
        int      state (void) const { return _state; }
 
-       void     discover();
+       bool     initialize_pa ();
+
+       void     host_api_list (std::vector<std::string>&);
+       PaHostApiIndex get_host_api_index_from_name (const std::string& name);
+
+       void     discover(const std::string& host_api);
        void     device_list (std::map<int, std::string> &devices) const;
 
        int      available_sample_rates (int device_id, std::vector<float>& sampleRates);
@@ -96,6 +101,8 @@ private:
        };
 
        std::map<int, paDevice *> _devices;
+
+       std::string _host_api;
 };
 
 } // namespace