X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fio.cc;h=da79301a311e1c42a46be611f782f50f9f202cb0;hb=9a0b1cce075f32768197d001f269a191869cc4e6;hp=23c7594d401e39c1bc1718d47dbbdc61a841f1a8;hpb=0c9c47086c49d27a38cef5f5cc819e1aec56857c;p=ardour.git diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 23c7594d40..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; } @@ -292,6 +314,15 @@ IO::add_port (string destination, void* src, DataType type) type = _default_type; } + ChanCount before = _ports.count (); + ChanCount after = before; + after.set (type, after.get (type) + 1); + + bool const r = PortCountChanging (after); /* EMIT SIGNAL */ + if (r) { + return -1; + } + IOChange change; { @@ -920,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) @@ -1243,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); @@ -1539,12 +1609,19 @@ IO::connected_to (const string& str) const return false; } -/** Caller must hold process lock */ +/** Call a processor's ::run() method, giving it our buffers + * Caller must hold process lock. + */ void IO::process_input (boost::shared_ptr proc, framepos_t start_frame, framepos_t end_frame, pframes_t nframes) { /* don't read the data into new buffers - just use the port buffers directly */ + if (n_ports().n_total() == 0) { + /* We have no ports, so nothing to process */ + return; + } + _buffers.get_jack_port_addresses (_ports, nframes); proc->run (_buffers, start_frame, end_frame, nframes, true); }