add Port::PostDisconnect signal to allow objects other than the one being directly...
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 26 Jan 2012 19:00:27 +0000 (19:00 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 26 Jan 2012 19:00:27 +0000 (19:00 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@11355 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/io.h
libs/ardour/ardour/port.h
libs/ardour/io.cc
libs/ardour/port.cc
libs/ardour/route.cc

index c7c91a6cf3d66ab36e5ab73e57a001bd37548fd9..88706ecea11c30c49873a954b803fdfd6b09fbce 100644 (file)
@@ -247,6 +247,7 @@ class IO : public SessionObject, public Latent
        std::string bundle_channel_name (uint32_t, uint32_t, DataType) const;
 
        BufferSet _buffers;
+       void disconnect_check (boost::shared_ptr<ARDOUR::Port>, boost::shared_ptr<ARDOUR::Port>);
 };
 
 } // namespace ARDOUR
index bbf61b00fc00875e766b8669e52a6168ee0c8e18..7aa4e8a0d538be1595449b92e53cd08480391b7a 100644 (file)
@@ -125,7 +125,7 @@ public:
        static void set_engine (AudioEngine *);
 
        PBD::Signal1<void,bool> MonitorInputChanged;
-
+       static PBD::Signal2<void,boost::shared_ptr<Port>,boost::shared_ptr<Port> > PostDisconnect;
 
        static void set_cycle_framecnt (pframes_t n) {
                _cycle_nframes = n;
index 2397c7ee067132da932818453b15495d5cdd689f..3805d7ac837eac14f16c13e876471e9643b6e49a 100644 (file)
@@ -69,6 +69,7 @@ IO::IO (Session& s, const string& name, Direction dir, DataType default_type)
        , _default_type (default_type)
 {
        _active = true;
+       Port::PostDisconnect.connect_same_thread (*this, boost::bind (&IO::disconnect_check, this, _1, _2));
        pending_state_node = 0;
        setup_bundle ();
 }
@@ -80,6 +81,7 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
 {
        _active = true;
        pending_state_node = 0;
+       Port::PostDisconnect.connect_same_thread (*this, boost::bind (&IO::disconnect_check, this, _1, _2));
 
        set_state (node, Stateful::loading_state_version);
        setup_bundle ();
@@ -96,6 +98,31 @@ IO::~IO ()
        }
 }
 
+void
+IO::disconnect_check (boost::shared_ptr<Port> a, boost::shared_ptr<Port> b)
+{
+       /* this could be called from within our own ::disconnect() method(s)
+          or from somewhere that operates directly on a port. so, we don't
+          know for sure if we can take this lock or not. if we fail,
+          we assume that its safely locked by our own ::disconnect().
+       */
+
+       Glib::Mutex::Lock tm (io_lock, Glib::TRY_LOCK);
+
+       if (tm.locked()) {
+               /* we took the lock, so we cannot be here from inside
+                * ::disconnect()
+                */
+               if (_ports.contains (a) || _ports.contains (b)) {
+                       changed (IOChange (IOChange::ConnectionsChanged), this); /* EMIT SIGNAL */              
+               }
+       } else {
+               /* we didn't get the lock, so assume that we're inside
+                * ::disconnect(), and it will call changed() appropriately.
+                */
+       }
+}
+
 void
 IO::increment_port_buffer_offset (pframes_t offset)
 {
index d6c959df30e0c78cc6713c73fe0b1addf2bded30..45874bba8db1ac769982968436f786d9ed4ff272 100644 (file)
@@ -39,6 +39,8 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
+PBD::Signal2<void,boost::shared_ptr<Port>, boost::shared_ptr<Port> > Port::PostDisconnect;
+
 AudioEngine* Port::_engine = 0;
 bool         Port::_connecting_blocked = false;
 pframes_t    Port::_global_port_buffer_offset = 0;
@@ -94,6 +96,11 @@ Port::disconnect_all ()
        jack_port_disconnect (_engine->jack(), _jack_port);
        _connections.clear ();
 
+       /* a cheaper, less hacky way to do boost::shared_from_this() ... 
+        */
+       boost::shared_ptr<Port> pself = _engine->get_port_by_name (name());
+       PostDisconnect (pself, boost::shared_ptr<Port>()); // emit signal
+
        return 0;
 }
 
@@ -168,21 +175,34 @@ Port::connect (std::string const & other)
 int
 Port::disconnect (std::string const & other)
 {
-       std::string const other_shrt = _engine->make_port_name_non_relative (other);
-       std::string const this_shrt = _engine->make_port_name_non_relative (_name);
+       std::string const other_fullname = _engine->make_port_name_non_relative (other);
+       std::string const this_fullname = _engine->make_port_name_non_relative (_name);
 
        int r = 0;
 
        if (sends_output ()) {
-               r = jack_disconnect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
+               r = jack_disconnect (_engine->jack (), this_fullname.c_str (), other_fullname.c_str ());
        } else {
-               r = jack_disconnect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str ());
+               r = jack_disconnect (_engine->jack (), other_fullname.c_str (), this_fullname.c_str ());
        }
 
        if (r == 0) {
                _connections.erase (other);
        }
 
+       /* a cheaper, less hacky way to do boost::shared_from_this() ... 
+        */
+       boost::shared_ptr<Port> pself = _engine->get_port_by_name (name());
+       boost::shared_ptr<Port> pother = _engine->get_port_by_name (other);
+
+       if (pself && pother) {
+               /* Disconnecting from another Ardour port: need to allow
+                  a check on whether this may affect anything that we
+                  need to know about.
+               */
+               PostDisconnect (pself, pother); // emit signal 
+       }
+
        return r;
 }
 
index 645addd7ab0178384fbbd7f843f58ec57d36440c..acc353f7dbb4e2526af14e872921c73e2c2b56de 100644 (file)
@@ -2837,8 +2837,6 @@ Route::input_change_handler (IOChange change, void * /*src*/)
                io_changed (); /* EMIT SIGNAL */
        }
 
-       cerr << _name << ": input change, connected ? " << _input->connected() << endl;
-
        if (!_input->connected() && _soloed_by_others_upstream) {
                if (need_to_queue_solo_change) {
                        _session.cancel_solo_after_disconnect (shared_from_this(), true);
@@ -2860,8 +2858,6 @@ Route::output_change_handler (IOChange change, void * /*src*/)
                need_to_queue_solo_change = false;
        }
 
-       cerr << _name << ": output change, connected ? " << _output->connected() << endl;
-
        if (!_output->connected() && _soloed_by_others_downstream) {
                if (need_to_queue_solo_change) {
                        _session.cancel_solo_after_disconnect (shared_from_this(), false);
@@ -2874,7 +2870,6 @@ Route::output_change_handler (IOChange change, void * /*src*/)
 void
 Route::cancel_solo_after_disconnect (bool upstream)
 {
-       cerr << _name << " CSAD upstream ? " << upstream << endl;
        if (upstream) {
                _soloed_by_others_upstream = 0;
        } else {