fix a problem creating and displaying connected status for ports not owned by ardour...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 6 Sep 2013 01:39:43 +0000 (21:39 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 6 Sep 2013 01:39:43 +0000 (21:39 -0400)
This was caused by using jack_port_get_connections() which will
not return the correct status for ports owned by another JACK
client. Because of the potential for deadlock by calling
jack_port_get_all_connections(), an extra argument was added
to several PortEngine:: API calls to specify whether the call
is in a process-callback context, which defaults to true.

The only place where false is passed is within the GlobalPortMatrix
when we need to determine whether two non-ardour ports are
connected.

gtk2_ardour/global_port_matrix.cc
libs/ardour/ardour/jack_portengine.h
libs/ardour/ardour/port_engine.h
libs/ardour/jack_portengine.cc
libs/ardour/port_manager.cc

index cdba7f5c27d6a74c4a8dab157d09c395096aec7a..80e2616bd81088023092333720548767f89e5ec0 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <gtkmm/image.h>
 #include <gtkmm/stock.h>
+
 #include "global_port_matrix.h"
 #include "utils.h"
 
@@ -118,15 +119,17 @@ GlobalPortMatrix::get_state (BundleChannel c[2]) const
 
                        if (!p && !q) {
                                /* two non-Ardour ports; things are slightly more involved */
-                               /* XXX: is this the easiest way to do this? */
-                               /* XXX: isn't this very inefficient? */
+
+                               /* get a port handle for one of them .. */
 
                                PortEngine::PortHandle ph = AudioEngine::instance()->port_engine().get_port_by_name (*i);
                                if (!ph) {
                                        return PortMatrixNode::NOT_ASSOCIATED;
                                }
 
-                               if (AudioEngine::instance()->port_engine().connected (ph)) {
+                               /* see if it is connected to the other one ... */
+
+                               if (AudioEngine::instance()->port_engine().connected_to (ph, *j, false)) {
                                        return PortMatrixNode::ASSOCIATED;
                                }
 
index f8db0c6ec42efe1b4a0a4d536b814669a27d7123..0e1eb48c5cc7473f91c19b9087391bc33b5a6b24 100644 (file)
@@ -63,11 +63,12 @@ class JACKPortEngine : public PortEngine
     PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
     void  unregister_port (PortHandle);
 
-    bool  connected (PortHandle);
-    bool  connected_to (PortHandle, const std::string&);
-    bool  physically_connected (PortHandle);
-    int   get_connections (PortHandle, std::vector<std::string>&);
+    bool  connected (PortHandle, bool process_callback_safe);
+    bool  connected_to (PortHandle, const std::string&, bool process_callback_safe);
+    bool  physically_connected (PortHandle, bool process_callback_safe);
+    int   get_connections (PortHandle, std::vector<std::string>&, bool process_callback_safe);
     int   connect (PortHandle, const std::string&);
+
     int   disconnect (PortHandle, const std::string&);
     int   disconnect_all (PortHandle);
     int   connect (const std::string& src, const std::string& dst);
index bb7ec5cb6698edd4aa1b5f313d26e9d79a466fba..71f93ea05e52dd1222fe5f520dc303e6b0659958 100644 (file)
@@ -185,21 +185,21 @@ class PortEngine {
     /** Return true if the port referred to by @param port has any connections
      * to other ports. Return false otherwise.
      */
-    virtual bool  connected (PortHandle port) = 0;
+    virtual bool  connected (PortHandle port, bool process_callback_safe = true) = 0;
     /** Return true if the port referred to by @param port is connected to
      * the port named by @param name. Return false otherwise.
      */
-    virtual bool  connected_to (PortHandle, const std::string& name) = 0;
+    virtual bool  connected_to (PortHandle, const std::string& name, bool process_callback_safe = true) = 0;
 
     /** Return true if the port referred to by @param port has any connections
      * to ports marked with the PortFlag IsPhysical. Return false otherwise.
      */
-    virtual bool  physically_connected (PortHandle port) = 0;
+    virtual bool  physically_connected (PortHandle port, bool process_callback_safe = true) = 0;
 
     /** Place the names of all ports connected to the port named by @param
      * ports into @param names, and return the number of connections.
      */
-    virtual int   get_connections (PortHandle port, std::vector<std::string>& names) = 0;
+    virtual int   get_connections (PortHandle port, std::vector<std::string>& names, bool process_callback_safe = true) = 0;
 
     /* MIDI */
 
index b0597f826984b720977b8d4569d9494b9c9ab34d..45958571759cd9d36f07dfab43fd496ad01c620c 100644 (file)
@@ -183,11 +183,18 @@ JACKPortEngine::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int
 }
 
 bool
-JACKPortEngine::connected (PortHandle port)
+JACKPortEngine::connected (PortHandle port, bool process_callback_safe)
 {
        bool ret = false;
 
-       const char** ports = jack_port_get_connections ((jack_port_t*) port);
+       const char** ports;
+
+       if (process_callback_safe) {
+               ports = jack_port_get_connections ((jack_port_t*)port);
+       } else {
+               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
+       }
 
        if (ports) {
                ret = true;
@@ -199,10 +206,17 @@ JACKPortEngine::connected (PortHandle port)
 }
 
 bool
-JACKPortEngine::connected_to (PortHandle port, const std::string& other)
+JACKPortEngine::connected_to (PortHandle port, const std::string& other, bool process_callback_safe)
 {
        bool ret = false;
-       const char** ports = jack_port_get_connections ((jack_port_t*) port);
+       const char** ports;
+
+       if (process_callback_safe) {
+               ports = jack_port_get_connections ((jack_port_t*)port);
+       } else {
+               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
+       }
 
        if (ports) {
                for (int i = 0; ports[i]; ++i) {
@@ -217,12 +231,19 @@ JACKPortEngine::connected_to (PortHandle port, const std::string& other)
 }
 
 bool
-JACKPortEngine::physically_connected (PortHandle p)
+JACKPortEngine::physically_connected (PortHandle p, bool process_callback_safe)
 {
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
        jack_port_t* port = (jack_port_t*) p;
 
-       const char** ports = jack_port_get_connections (port);
+       const char** ports;
+       
+       if (process_callback_safe) {
+               ports = jack_port_get_connections ((jack_port_t*)port);
+       } else {
+               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
+       }
 
        if (ports) {
                for (int i = 0; ports[i]; ++i) {
@@ -240,9 +261,16 @@ JACKPortEngine::physically_connected (PortHandle p)
 }
 
 int
-JACKPortEngine::get_connections (PortHandle port, vector<string>& s)
+JACKPortEngine::get_connections (PortHandle port, vector<string>& s, bool process_callback_safe)
 {
-       const char** ports = jack_port_get_connections ((jack_port_t*) port);
+       const char** ports;
+
+       if (process_callback_safe) {
+               ports = jack_port_get_connections ((jack_port_t*)port);
+       } else {
+               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
+       }
 
        if (ports) {
                for (int i = 0; ports[i]; ++i) {
@@ -443,7 +471,9 @@ int
 JACKPortEngine::connect (const std::string& src, const std::string& dst)
 {
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       return jack_connect (_priv_jack, src.c_str(), dst.c_str());
+       
+       int r = jack_connect (_priv_jack, src.c_str(), dst.c_str());
+       return r;
 }
 
 int
index 4e467e3008a1d092daf4fe1b26ca04baf5b4b57b..1758ea4a3fe3c562b6a4a39e3e8452c23104b7dc 100644 (file)
@@ -385,8 +385,13 @@ PortManager::connect (const string& source, const string& destination)
        } else if (dst) {
                ret = dst->connect (s);
        } else {
-               /* neither port is known to us, and this API isn't intended for use as a general patch bay */
-               ret = -1;
+               /* neither port is known to us ...hand-off to the PortEngine
+                */
+               if (_impl) {
+                       ret = _impl->connect (s, d);
+               } else {
+                       ret = -1;
+               }
        }
 
        if (ret > 0) {
@@ -412,12 +417,17 @@ PortManager::disconnect (const string& source, const string& destination)
        boost::shared_ptr<Port> dst = get_port_by_name (d);
 
        if (src) {
-                       ret = src->disconnect (d);
+               ret = src->disconnect (d);
        } else if (dst) {
-                       ret = dst->disconnect (s);
+               ret = dst->disconnect (s);
        } else {
-               /* neither port is known to us, and this API isn't intended for use as a general patch bay */
-               ret = -1;
+               /* neither port is known to us ...hand-off to the PortEngine
+                */
+               if (_impl) {
+                       ret = _impl->disconnect (s, d);
+               } else {
+                       ret = -1;
+               }
        }
        return ret;
 }