X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fio.cc;h=da79301a311e1c42a46be611f782f50f9f202cb0;hb=9a0b1cce075f32768197d001f269a191869cc4e6;hp=aac2adf7849dbd25813cba9e67b3fb5aa472b33c;hpb=0dbc0429a81bb10b558f83d66c5be098d287f293;p=ardour.git diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index aac2adf784..da79301a31 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -34,17 +34,12 @@ #include "ardour/audioengine.h" #include "ardour/buffer.h" +#include "ardour/buffer_set.h" #include "ardour/debug.h" #include "ardour/io.h" -#include "ardour/route.h" #include "ardour/port.h" -#include "ardour/audio_port.h" -#include "ardour/midi_port.h" +#include "ardour/route.h" #include "ardour/session.h" -#include "ardour/cycle_timer.h" -#include "ardour/buffer_set.h" -#include "ardour/meter.h" -#include "ardour/amp.h" #include "ardour/user_bundle.h" #include "i18n.h" @@ -69,6 +64,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 +76,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 +93,31 @@ IO::~IO () } } +void +IO::disconnect_check (boost::shared_ptr a, boost::shared_ptr 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) { @@ -229,8 +251,8 @@ IO::remove_port (boost::shared_ptr port, void* src) ChanCount after = before; after.set (port->type(), after.get (port->type()) - 1); - bool const r = PortCountChanging (after); /* EMIT SIGNAL */ - if (r) { + boost::optional const r = PortCountChanging (after); /* EMIT SIGNAL */ + if (r.get_value_or (false)) { return -1; } @@ -929,6 +951,44 @@ IO::make_connections (const XMLNode& node, int version, bool in) return 0; } +void +IO::prepare_for_reset (XMLNode& node, const std::string& name) +{ + /* reset name */ + node.add_property ("name", name); + + /* now find connections and reset the name of the port + in one so that when we re-use it it will match + the name of the thing we're applying it to. + */ + + XMLProperty* prop; + XMLNodeList children = node.children(); + + for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) { + + if ((*i)->name() == "Port") { + + prop = (*i)->property (X_("name")); + + if (prop) { + string new_name; + string old = prop->value(); + string::size_type slash = old.find ('/'); + + if (slash != string::npos) { + /* port name is of form: / */ + + new_name = name; + new_name += old.substr (old.find ('/')); + + prop->set_value (new_name); + } + } + } + } +} + int IO::make_connections_2X (const XMLNode& node, int /*version*/, bool in) @@ -1252,6 +1312,7 @@ IO::disable_connecting () int IO::enable_connecting () { + Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock()); connecting_legal = true; boost::optional r = ConnectingLegal (); return r.get_value_or (0);