summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-01-26 19:00:27 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-01-26 19:00:27 +0000
commite3b21111094556494993a711edf6fbc6f826a057 (patch)
tree116ea553f73149e28e0fec2a30acf968e0cbffbd
parent9b3aefec1b0da4b838ecc90df7080be539b2edba (diff)
add Port::PostDisconnect signal to allow objects other than the one being directly disconnected to act when disconnection happens. This turns out to be much easier than using the JACK port connect/disconnect callback
git-svn-id: svn://localhost/ardour2/branches/3.0@11355 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/ardour/ardour/io.h1
-rw-r--r--libs/ardour/ardour/port.h2
-rw-r--r--libs/ardour/io.cc27
-rw-r--r--libs/ardour/port.cc28
-rw-r--r--libs/ardour/route.cc5
5 files changed, 53 insertions, 10 deletions
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index c7c91a6cf3..88706ecea1 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -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
diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h
index bbf61b00fc..7aa4e8a0d5 100644
--- a/libs/ardour/ardour/port.h
+++ b/libs/ardour/ardour/port.h
@@ -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;
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 2397c7ee06..3805d7ac83 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -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 ();
@@ -97,6 +99,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)
{
/* io_lock, not taken: function must be called from Session::process() calltree */
diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc
index d6c959df30..45874bba8d 100644
--- a/libs/ardour/port.cc
+++ b/libs/ardour/port.cc
@@ -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;
}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 645addd7ab..acc353f7db 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -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 {