add notion of unavailable devices to ARDOUR::AudioBackend
authorPaul Davis <paul@linuxaudiosystems.com>
Mon, 5 Aug 2013 17:19:23 +0000 (13:19 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 5 Aug 2013 17:19:23 +0000 (13:19 -0400)
gtk2_ardour/engine_dialog.cc
libs/ardour/ardour/audio_backend.h
libs/ardour/ardour/jack_audiobackend.h
libs/ardour/jack_audiobackend.cc

index 3a06fb5072b1d73abd0e3b2d5c3cdc471cd434c6..8c67d23d36ed9da3be956724275f46f88de02dd4 100644 (file)
@@ -280,14 +280,29 @@ EngineControl::list_devices ()
 
        /* now fill out devices, mark sample rates, buffer sizes insensitive */
            
-       vector<string> devices = backend->enumerate_devices ();
+       vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices ();
        
-       set_popdown_strings (interface_combo, devices);
-       interface_combo.set_active_text (devices.front());
-       set_popdown_strings (input_device_combo, devices);
-       input_device_combo.set_active_text (devices.front());
-       set_popdown_strings (output_device_combo, devices);
-       output_device_combo.set_active_text (devices.front());
+       /* NOTE: Ardour currently does not display the "available" field of the
+        * returned devices.
+        *
+        * Doing so would require a different GUI widget than the combo
+        * box/popdown that we currently use, since it has no way to list
+        * items that are not selectable. Something more like a popup menu,
+        * which could have unselectable items, would be appropriate.
+        */
+
+       vector<string> available_devices;
+
+       for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
+               available_devices.push_back (i->name);
+       }
+
+       set_popdown_strings (interface_combo, available_devices);
+       interface_combo.set_active_text (available_devices.front());
+       set_popdown_strings (input_device_combo, available_devices);
+       input_device_combo.set_active_text (available_devices.front());
+       set_popdown_strings (output_device_combo, available_devices);
+       output_device_combo.set_active_text (available_devices.front());
        
        interface_changed ();
 }
index 08dd7fb0b59b9826f096ec89dae22d71952cab3a..77b7eadb4803e7d4382085575f7839178e5e3aa3 100644 (file)
@@ -95,12 +95,25 @@ class AudioBackend {
      */
     virtual int set_driver (const std::string& /*drivername*/) { return 0; }
 
-    /** Returns a collection of strings identifying devices known
-     * to this backend. Any of these strings may be used to identify a
+    /** used to list device names along with whether or not they are currently
+     *  available. 
+    */
+    struct DeviceStatus {
+       std::string name;
+       bool        available;
+
+       DeviceStatus (const std::string& s, bool avail) : name (s), available (avail) {}
+    };
+
+    /** Returns a collection of DeviceStatuses identifying devices discovered
+     * by this backend since the start of the process.
+     *
+     * Any of the names in each DeviceStatus may be used to identify a
      * device in other calls to the backend, though any of them may become
      * invalid at any time.
      */
-    virtual std::vector<std::string> enumerate_devices () const = 0;
+    virtual std::vector<DeviceStatus> enumerate_devices () const = 0;
+
     /** Returns a collection of float identifying sample rates that are
      * potentially usable with the hardware identified by @param device.
      * Any of these values may be supplied in other calls to this backend
index 59b5b881053f6d9324f2d000f480f75ede6b699f..9fa3d0c1ccdf649531ca283c6a9bb5d61518776a 100644 (file)
@@ -23,6 +23,7 @@
 #include <string>
 #include <vector>
 #include <map>
+#include <set>
 
 #include <stdint.h>
 
@@ -53,7 +54,7 @@ class JACKAudioBackend : public AudioBackend {
     std::vector<std::string> enumerate_drivers () const;
     int set_driver (const std::string&);
 
-    std::vector<std::string> enumerate_devices () const;
+    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;
@@ -172,7 +173,11 @@ class JACKAudioBackend : public AudioBackend {
     uint32_t _current_usecs_per_cycle;
     uint32_t _current_systemic_input_latency;
     uint32_t _current_systemic_output_latency;
+
+    typedef std::set<std::string> DeviceList;
+    typedef std::map<std::string,DeviceList> DriverDeviceMap;
     
+    mutable DriverDeviceMap all_devices;
 };
 
 } // namespace
index 8ab8428555fe1717450b6e5c0590eb8ed5d2f299..19158aacc9bec401315f2d3c0fccfc095936517b 100644 (file)
@@ -97,9 +97,9 @@ JACKAudioBackend::requires_driver_selection() const
 vector<string>
 JACKAudioBackend::enumerate_drivers () const
 {
-       vector<string> s;
-       get_jack_audio_driver_names (s);
-       return s;
+       vector<string> currently_available;
+       get_jack_audio_driver_names (currently_available);
+       return currently_available;
 }
 
 int
@@ -109,10 +109,37 @@ JACKAudioBackend::set_driver (const std::string& name)
        return 0;
 }
 
-vector<string>
+vector<AudioBackend::DeviceStatus>
 JACKAudioBackend::enumerate_devices () const
 {
-       return get_jack_device_names_for_audio_driver (_target_driver);
+       vector<string> currently_available = get_jack_device_names_for_audio_driver (_target_driver);
+       vector<DeviceStatus> statuses;
+
+       if (all_devices.find (_target_driver) == all_devices.end()) {
+               all_devices.insert (make_pair (_target_driver, std::set<string>()));
+       }
+       
+       /* store every device we've found, by driver name. 
+        *
+        * This is so we do not confuse ALSA, FFADO, netjack etc. devices
+        * with each other.
+        */
+
+       DeviceList& all (all_devices[_target_driver]);
+
+       for (vector<string>::const_iterator d = currently_available.begin(); d != currently_available.end(); ++d) {
+               all.insert (*d);
+       }
+       
+       for (DeviceList::const_iterator d = all.begin(); d != all.end(); ++d) {
+               if (find (currently_available.begin(), currently_available.end(), *d) == currently_available.end()) {
+                       statuses.push_back (DeviceStatus (*d, false));
+               } else {
+                       statuses.push_back (DeviceStatus (*d, false));
+               }
+       }
+       
+       return statuses;
 }
 
 vector<float>