start code reorganization needed to deal with backend choices. compiles, links and...
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 1 Aug 2013 22:49:40 +0000 (18:49 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 1 Aug 2013 22:49:40 +0000 (18:49 -0400)
13 files changed:
gtk2_ardour/ardour_ui.cc
libs/ardour/ardour/audio_backend.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/jack_audiobackend.h
libs/ardour/ardour/jack_portengine.h
libs/ardour/ardour/port_engine.h
libs/ardour/ardour/port_manager.h
libs/ardour/audioengine.cc
libs/ardour/globals.cc
libs/ardour/io.cc
libs/ardour/jack_audiobackend.cc
libs/ardour/jack_portengine.cc
libs/ardour/port_manager.cc

index dc9018fc62fe3db41e2ee50018242bb82686471c..12f3feafa18f40de6089664c3d9e0de0ab6025b7 100644 (file)
@@ -395,30 +395,25 @@ ARDOUR_UI::create_engine ()
 
        loading_message (_("Starting audio engine"));
 
-       try {
-               engine = ARDOUR::AudioEngine::create (ARDOUR_COMMAND_LINE::backend_client_name, ARDOUR_COMMAND_LINE::backend_session_uuid);
-
-       } catch (...) {
-
-               return -1;
-       }
+       AudioEngine* engine = AudioEngine::instance();
 
        engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
        engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
        engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
 
        engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
+       engine->BackendAvailable.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::post_engine, this));
 
        ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
 
-       post_engine ();
-
        return 0;
 }
 
 void
 ARDOUR_UI::post_engine ()
 {
+       cerr << "Backend available!\n";
+
        /* Things to be done once we create the AudioEngine
         */
 
@@ -689,6 +684,7 @@ ARDOUR_UI::startup ()
 {
        Application* app = Application::instance ();
        char *nsm_url;
+
        app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
        app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load));
 
index 3b68432b6ff6e2b1cc31db91ebd71380e7f80c1c..6aee33a50770b8748e66696a16aceb065f5c771f 100644 (file)
@@ -284,7 +284,7 @@ class AudioBackend {
     virtual int set_time_master (bool /*yn*/) { return 0; }
 
     virtual int        usecs_per_cycle () const { return 1000000 * (buffer_size() / sample_rate()); }
-    virtual size_t     raw_buffer_size (DataType t);
+    virtual size_t     raw_buffer_size (DataType t) = 0;
     
     /* Process time */
     
index 0bbbe90ef43dedfd47212e14d954d47f36bb66b1..cf22925565e2d10ce1a6df2e0b20091a1c5c82cb 100644 (file)
@@ -67,19 +67,17 @@ class AudioEngine : public SessionHandlePtr, public PortManager
 {
 public:
 
-    static AudioEngine* create (const std::string&  client_name, const std::string& session_uuid);
+    static AudioEngine* create ();
 
     virtual ~AudioEngine ();
     
     int discover_backends();
     std::vector<std::string> available_backends() const;
     std::string current_backend_name () const;
-    int set_backend (const std::string&);
+    int set_backend (const std::string&, const std::string& arg1, const std::string& arg2);
 
     ProcessThread* main_thread() const { return _main_thread; }
     
-    std::string client_name() const { return backend_client_name; }
-
     /* START BACKEND PROXY API 
      *
      * See audio_backend.h for full documentation and semantics. These wrappers
@@ -144,7 +142,6 @@ public:
     int  reset_timebase ();
     
     void update_latencies ();
-
     
     /* this signal is sent for every process() cycle while freewheeling.
        (the regular process() call to session->process() is not made)
@@ -154,10 +151,7 @@ public:
     
     PBD::Signal0<void> Xrun;
     
-    /* this signal is if the backend notifies us of a graph order event */
-    
-    PBD::Signal0<void> GraphReordered;
-    
+
 #ifdef HAVE_JACK_SESSION
     PBD::Signal1<void,jack_session_event_t *> JackSessionEvent;
 #endif
@@ -176,6 +170,13 @@ public:
     
     PBD::Signal0<void> Running;
     PBD::Signal0<void> Stopped;
+
+    /* these two are emitted as we create backends that
+       can actually be used to do stuff (e.g. register ports)
+    */
+    
+    PBD::Signal0<void> BackendAvailable;
+    PBD::Signal0<void> BackendRemoved;
     
     static AudioEngine* instance() { return _instance; }
     static void destroy();
@@ -197,7 +198,7 @@ public:
     static void thread_init_callback (void *);
 
   private:
-    AudioEngine (const std::string&  client_name, const std::string& session_uuid);
+    AudioEngine ();
 
     static AudioEngine*       _instance;
 
@@ -227,9 +228,6 @@ public:
     Glib::Threads::Thread*     m_meter_thread;
     ProcessThread*            _main_thread;
     
-    std::string               backend_client_name;
-    std::string               backend_session_uuid;
-    
     void meter_thread ();
     void start_metering_thread ();
     void stop_metering_thread ();
index 7104b814c2e0e715938c87d4b81c15652e028147..05638f6c73882cd85964700483c0deeda7868eea 100644 (file)
@@ -144,7 +144,6 @@ class JACKAudioBackend : public AudioBackend {
     static void* _start_process_thread (void*);
 
     ChanCount n_physical (unsigned long) const;
-    void get_physical (DataType, unsigned long, std::vector<std::string> &);
 
     /* pffooo */
 
index bee87532d3e9cd0f5397bc1f57709f5dbb65ae89..638d3382ad799a11d931038330b6f5ae0b0f3b91 100644 (file)
@@ -44,6 +44,8 @@ class JACKPortEngine : public PortEngine
 
     const std::string& my_name() const;
 
+    uint32_t port_name_size() const;
+
     int         set_port_name (PortHandle, const std::string&);
     std::string get_port_name (PortHandle) const;
     PortHandle* get_port_by_name (const std::string&) const;
index e63c52630d5e33b51ad6262e72f20b4538378c6d..f03a8e263f2e6b57867e8b3c297b517f11929210 100644 (file)
@@ -93,6 +93,8 @@ class PortEngine {
 
     virtual const std::string& my_name() const = 0;
 
+    virtual uint32_t port_name_size() const = 0;
+
     virtual int         set_port_name (PortHandle, const std::string&) = 0;
     virtual std::string get_port_name (PortHandle) const = 0;
     virtual PortHandle* get_port_by_name (const std::string&) const = 0;
index d88143d1102e23510789f40b6d4019f4a01c73a9..06e4939101efa60a7bb587ff7548703f58126714 100644 (file)
@@ -47,7 +47,10 @@ class PortManager
 
     void set_port_engine (PortEngine& pe);
     PortEngine& port_engine() { return *_impl; }
-    
+
+    uint32_t port_name_size() const;
+    std::string my_name() const;
+
     /* Port registration */
     
     boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname);
@@ -114,6 +117,9 @@ class PortManager
 
     bool port_remove_in_progress() const { return _port_remove_in_progress; }
 
+    /** Emitted if the backend notifies us of a graph order event */
+    PBD::Signal0<void> GraphReordered;
+
     /** Emitted if a Port is registered or unregistered */
     PBD::Signal0<void> PortRegisteredOrUnregistered;
     
index 05f59707a8227e2897e845afcd96d92a210eb131..eee21cad1f691cce1c4ae82a38962372b065a5f3 100644 (file)
@@ -63,7 +63,7 @@ using namespace PBD;
 gint AudioEngine::m_meter_exit;
 AudioEngine* AudioEngine::_instance = 0;
 
-AudioEngine::AudioEngine (const std::string& bcn, const std::string& bsu)
+AudioEngine::AudioEngine ()
        : session_remove_pending (false)
        , session_removal_countdown (-1)
        , monitor_check_interval (INT32_MAX)
@@ -75,10 +75,9 @@ AudioEngine::AudioEngine (const std::string& bcn, const std::string& bsu)
        , port_remove_in_progress (false)
        , m_meter_thread (0)
        , _main_thread (0)
-       , backend_client_name (bcn)
-       , backend_session_uuid (bsu)
 {
        g_atomic_int_set (&m_meter_exit, 0);
+       discover_backends ();
 }
 
 AudioEngine::~AudioEngine ()
@@ -95,12 +94,15 @@ AudioEngine::~AudioEngine ()
 }
 
 AudioEngine*
-AudioEngine::create (const std::string& bcn, const std::string& bsu)
+AudioEngine::create ()
 {
        if (_instance) {
                return _instance;
        }
-       return new AudioEngine (bcn, bsu);
+
+       _instance = new AudioEngine ();
+       
+       return _instance;
 }
 
 void
@@ -120,8 +122,6 @@ _thread_init_callback (void * /*arg*/)
        MIDI::JackMIDIPort::set_process_thread (pthread_self());
 }
 
-
-
 void
 AudioEngine::split_cycle (pframes_t offset)
 {
@@ -488,8 +488,8 @@ AudioEngine::discover_backends ()
 
        _backends.clear ();
 
-       Glib::PatternSpec so_extension_pattern("*.so");
-       Glib::PatternSpec dylib_extension_pattern("*.dylib");
+       Glib::PatternSpec so_extension_pattern("*backend.so");
+       Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
 
        find_matching_files_in_search_path (backend_search_path (),
                                            so_extension_pattern, backend_modules);
@@ -497,7 +497,7 @@ AudioEngine::discover_backends ()
        find_matching_files_in_search_path (backend_search_path (),
                                            dylib_extension_pattern, backend_modules);
 
-       DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1"), backend_search_path().to_string()));
+       DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1\n"), backend_search_path().to_string()));
 
        for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
 
@@ -514,26 +514,26 @@ AudioEngine::discover_backends ()
 AudioBackendInfo*
 AudioEngine::backend_discover (const string& path)
 {
-       Glib::Module* module = new Glib::Module(path);
+       Glib::Module module (path);
        AudioBackendInfo* info;
        void* sym = 0;
 
        if (!module) {
                error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
-                               Glib::Module::get_last_error()) << endmsg;
-               delete module;
+                                       Glib::Module::get_last_error()) << endmsg;
                return 0;
        }
-
-       if (!module->get_symbol("descriptor", sym)) {
+       
+       if (!module.get_symbol ("descriptor", sym)) {
                error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor."), path) << endmsg;
                error << Glib::Module::get_last_error() << endmsg;
-               delete module;
                return 0;
        }
 
+       module.make_resident ();
+       
        info = (AudioBackendInfo*) sym;
-
+       
        return info;
 }
 
@@ -564,11 +564,13 @@ AudioEngine::drop_backend ()
        if (_backend) {
                _backend->stop ();
                _backend.reset ();
+
+               BackendRemoved(); /* EMIT SIGNAL */
        }
 }
 
 int
-AudioEngine::set_backend (const std::string& name)
+AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
 {
        BackendMap::iterator b = _backends.find (name);
 
@@ -580,14 +582,21 @@ AudioEngine::set_backend (const std::string& name)
 
        try {
 
+               if (b->second->instantiate (arg1, arg2)) {
+                       throw failed_constructor ();
+               }
+
                _backend = b->second->backend_factory (*this);
                _impl = b->second->portengine_factory (*this);
 
+
        } catch (...) {
                error << string_compose (_("Could not create backend for %1"), name) << endmsg;
                return -1;
        }
 
+       BackendAvailable (); /* EMIT SIGNAL */
+
        return 0;
 }
 
@@ -993,3 +1002,4 @@ AudioEngine::halted_callback (const char* why)
        MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */
        Halted (why); /* EMIT SIGNAL */
 }
+
index b2833db4fa521a397bcc7f49e587e9e9a65fc7d1..132a5fb35d4332f5cca037d58e74117007f3d843 100644 (file)
@@ -331,6 +331,17 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
        EventTypeMap::instance().new_parameter(EnvelopeAutomation);
        EventTypeMap::instance().new_parameter(MidiCCAutomation);
 
+       ARDOUR::AudioEngine::create ();
+
+       uint32_t backend_cnt;
+
+       if ((backend_cnt = AudioEngine::instance()->available_backends().size()) == 0) {
+               error << _("No audio/MIDI backends are available") << endmsg;
+               return -1;
+       }
+
+       cerr << "We have " << backend_cnt << endl;
+
        return 0;
 }
 
index 21fdca6e96271520b633c6b42be9acb2f862474c..c517defe1a0f8441cba69e260b279b8de4ef0126 100644 (file)
@@ -1337,7 +1337,7 @@ IO::bundle_changed (Bundle::Change /*c*/)
 string
 IO::build_legal_port_name (DataType type)
 {
-       const int name_size = jack_port_name_size();
+       const int name_size = AudioEngine::instance()->port_name_size();
        int limit;
        string suffix;
 
@@ -1371,7 +1371,7 @@ IO::build_legal_port_name (DataType type)
 
        // allow up to 4 digits for the output port number, plus the slash, suffix and extra space
 
-       limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
+       limit = name_size - AudioEngine::instance()->my_name().length() - (suffix.length() + 5);
 
        char buf1[name_size+1];
        char buf2[name_size+1];
index 04ee94a80ce74642ccaa6c8db9fd13a26999b2fb..420f10407725e058e4a446fff4733a5afc0a6ba9 100644 (file)
@@ -58,6 +58,10 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnec
 {
 }
 
+JACKAudioBackend::~JACKAudioBackend()
+{
+}
+
 string
 JACKAudioBackend::name() const 
 {
@@ -825,3 +829,26 @@ JACKAudioBackend::update_latencies ()
        GET_PRIVATE_JACK_POINTER (_priv_jack);
        jack_recompute_total_latencies (_priv_jack);
 }
+
+ChanCount
+JACKAudioBackend::n_physical (unsigned long flags) const
+{
+       ChanCount c;
+
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, c);
+
+       const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
+
+       if (ports) {
+               for (uint32_t i = 0; ports[i]; ++i) {
+                       if (!strstr (ports[i], "Midi-Through")) {
+                               DataType t (jack_port_type (jack_port_by_name (_priv_jack, ports[i])));
+                               c.set (t, c.get (t) + 1);
+                       }
+               }
+               
+               jack_free (ports);
+       }
+
+       return c;
+}
index 7280c9ff2479ab7eb4554d21c00423e8e2295f49..1dc323576a680f483079c9813d528941cb06b3cc 100644 (file)
@@ -222,6 +222,21 @@ JACKPortEngine::physically_connected (PortHandle p)
        return false;
 }
 
+int
+JACKPortEngine::get_connections (PortHandle port, vector<string>& s)
+{
+       const char** ports = jack_port_get_connections ((jack_port_t*) port);
+
+       if (ports) {
+               for (int i = 0; ports[i]; ++i) {
+                       s.push_back (ports[i]);
+               }
+               jack_free (ports);
+       }
+
+       return s.size();
+}
+
 DataType
 JACKPortEngine::port_data_type (PortHandle p) const
 {
@@ -357,6 +372,23 @@ JACKPortEngine::can_monitor_input () const
        return true;
 }
 
+int
+JACKPortEngine::request_input_monitoring (PortHandle port, bool yn)
+{
+       return jack_port_request_monitor ((jack_port_t*) port, yn);
+}
+int
+JACKPortEngine::ensure_input_monitoring (PortHandle port, bool yn)
+{
+       return jack_port_ensure_monitor ((jack_port_t*) port, yn);
+}
+bool
+JACKPortEngine::monitoring_input (PortHandle port)
+{
+       return jack_port_monitoring_input ((jack_port_t*) port);
+}
+
+
 pframes_t
 JACKPortEngine::sample_time_at_cycle_start ()
 {
@@ -480,3 +512,9 @@ JACKPortEngine::get_buffer (PortHandle port, pframes_t nframes)
 {
        return jack_port_get_buffer ((jack_port_t*) port, nframes);
 }
+
+uint32_t
+JACKPortEngine::port_name_size() const
+{
+       return jack_port_name_size ();
+}
index b5f280292e4fc785718ac13d8616be5b3418ff2e..5c807a6979363d5bee49bbfc7dba66767909d0aa 100644 (file)
@@ -67,6 +67,10 @@ PortManager::remove_all_ports ()
 string
 PortManager::make_port_name_relative (const string& portname) const
 {
+       if (!_impl) {
+               return portname;
+       }
+
        string::size_type len;
        string::size_type n;
        string self = _impl->my_name();
@@ -105,6 +109,10 @@ PortManager::make_port_name_non_relative (const string& portname) const
 bool
 PortManager::port_is_mine (const string& portname) const
 {
+       if (!_impl) {
+               return true;
+       }
+
        string self = _impl->my_name();
 
        if (portname.find_first_of (':') != string::npos) {
@@ -119,6 +127,10 @@ PortManager::port_is_mine (const string& portname) const
 bool
 PortManager::port_is_physical (const std::string& portname) const
 {
+       if (!_impl) {
+               return false;
+       }
+
        PortEngine::PortHandle ph = _impl->get_port_by_name (portname);
        if (!ph) {
                return false;
@@ -130,24 +142,38 @@ PortManager::port_is_physical (const std::string& portname) const
 void
 PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s)
 {
+       if (!_impl) {
+               return;
+       }
        _impl->get_physical_outputs (type, s);
 }
  
 void
 PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s)
 {
+       if (!_impl) {
+               return;
+       }
+
        _impl->get_physical_inputs (type, s);
 }
  
 ChanCount
 PortManager::n_physical_outputs () const
 {
+       if (!_impl) {
+               return ChanCount::ZERO;
+       }
+
        return _impl->n_physical_outputs ();
 }
  
 ChanCount
 PortManager::n_physical_inputs () const
 {
+       if (!_impl) {
+               return ChanCount::ZERO;
+       }
        return _impl->n_physical_inputs ();
 }
 
@@ -158,6 +184,10 @@ PortManager::n_physical_inputs () const
 boost::shared_ptr<Port>
 PortManager::get_port_by_name (const string& portname)
 {
+       if (!_impl) {
+               return boost::shared_ptr<Port>();
+       }
+
         if (!port_is_mine (portname)) {
                 /* not an ardour port */
                 return boost::shared_ptr<Port> ();
@@ -200,12 +230,20 @@ PortManager::port_renamed (const std::string& old_relative_name, const std::stri
 int
 PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
 {
+       if (!_impl) {
+               return 0;
+       }
+
        return _impl->get_ports (port_name_pattern, type, flags, s);
 }
 
 void
 PortManager::port_registration_failure (const std::string& portname)
 {
+       if (!_impl) {
+               return;
+       }
+
        string full_portname = _impl->my_name();
        full_portname += ':';
        full_portname += portname;
@@ -293,6 +331,10 @@ PortManager::unregister_port (boost::shared_ptr<Port> port)
 bool
 PortManager::connected (const string& port_name)
 {
+       if (!_impl) {
+               return false;
+       }
+
        PortEngine::PortHandle handle = _impl->get_port_by_name (port_name);
 
        if (!handle) {
@@ -437,12 +479,20 @@ PortManager::registration_callback ()
 bool
 PortManager::can_request_input_monitoring () const
 {
+       if (!_impl) {
+               return false;
+       }
+
        return _impl->can_monitor_input ();
 }
  
 void
 PortManager::request_input_monitoring (const string& name, bool yn) const
 {
+       if (!_impl) {
+               return;
+       }
+
        PortEngine::PortHandle ph = _impl->get_port_by_name (name);
 
        if (ph) {
@@ -453,6 +503,10 @@ PortManager::request_input_monitoring (const string& name, bool yn) const
 void
 PortManager::ensure_input_monitoring (const string& name, bool yn) const
 {
+       if (!_impl) {
+               return;
+       }
+
        PortEngine::PortHandle ph = _impl->get_port_by_name (name);
 
        if (ph) {
@@ -460,3 +514,32 @@ PortManager::ensure_input_monitoring (const string& name, bool yn) const
        }
 }
 
+uint32_t
+PortManager::port_name_size() const
+{
+       if (!_impl) {
+               return 0;
+       }
+       
+       return _impl->port_name_size ();
+}
+
+string
+PortManager::my_name() const
+{
+       if (!_impl) {
+               return string();
+       }
+       
+       return _impl->my_name();
+}
+
+int
+PortManager::graph_order_callback ()
+{
+       if (!_port_remove_in_progress) {
+               GraphReordered(); /* EMIT SIGNAL */
+       }
+
+       return 0;
+}