From 0cb42dffeccad2d99ac036c7c1c1516092f9756f Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 23 Jun 2024 18:18:17 +0200 Subject: [PATCH] Use RCU to for IO::_ports #9730 This removes the _io_lock, and prevents invalid iterators BUT it currently does not work.. PortSet needs an appropriate copy c'tor that does not re-register ports --- gtk2_ardour/export_channel_selector.cc | 4 +- gtk2_ardour/io_button.cc | 28 +- gtk2_ardour/io_selector.cc | 2 +- gtk2_ardour/plugin_pin_dialog.cc | 12 +- gtk2_ardour/processor_box.cc | 4 +- libs/ardour/ardour/buffer_set.h | 4 +- libs/ardour/ardour/io.h | 8 +- libs/ardour/ardour/port_set.h | 2 +- libs/ardour/buffer_set.cc | 2 +- libs/ardour/delivery.cc | 21 +- libs/ardour/io.cc | 502 ++++++++++++------------- libs/ardour/io_plug.cc | 10 +- libs/ardour/midi_track.cc | 16 +- libs/ardour/port_insert.cc | 4 +- libs/ardour/route.cc | 4 +- libs/ardour/session.cc | 26 +- libs/ardour/track.cc | 15 +- libs/surfaces/osc/osc.cc | 10 +- 18 files changed, 318 insertions(+), 356 deletions(-) diff --git a/gtk2_ardour/export_channel_selector.cc b/gtk2_ardour/export_channel_selector.cc index c7f25b9e30..087a981ce4 100644 --- a/gtk2_ardour/export_channel_selector.cc +++ b/gtk2_ardour/export_channel_selector.cc @@ -733,8 +733,8 @@ TrackExportChannelSelector::sync_with_manager_state () PortExportChannel::PortSet route_ports; PortExportChannel::PortSet intersection; - PortSet& ps (route->output()->ports ()); - for (PortSet::audio_iterator p = ps.audio_begin (); p != ps.audio_end (); ++p) { + std::shared_ptr ps (route->output()->ports ()); + for (PortSet::audio_iterator p = ps->audio_begin (); p != ps->audio_end (); ++p) { route_ports.insert (*p); } diff --git a/gtk2_ardour/io_button.cc b/gtk2_ardour/io_button.cc index 3f153d1683..6625c9f8c7 100644 --- a/gtk2_ardour/io_button.cc +++ b/gtk2_ardour/io_button.cc @@ -60,11 +60,11 @@ exclusively_connected (std::shared_ptr dest_io, std::shared_ptr io, Data uint32_t n = 0; uint32_t cnt = 0; std::set pn; - PortSet const& psa (dest_io->ports ()); - PortSet const& psb (io->ports ()); + std::shared_ptr psa (dest_io->ports ()); + std::shared_ptr psb (io->ports ()); - for (auto a = psa.begin (dt); a != psa.end (dt); ++a, ++n) { - for (auto b = psb.begin (dt); b != psb.end (dt); ++b) { + for (auto a = psa->begin (dt); a != psa->end (dt); ++a, ++n) { + for (auto b = psb->begin (dt); b != psb->end (dt); ++b) { if (a->connected_to (b->name ())) { ++cnt; pn.insert (n); @@ -117,7 +117,7 @@ IOButtonBase::guess_main_type (std::shared_ptr io) /* Find most likely type among connected ports */ DataType type = DataType::NIL; /* NIL is always last so least likely */ - for (PortSet::iterator p = io->ports ().begin (); p != io->ports ().end (); ++p) { + for (auto const& p : *io->ports ()) { if (p->connected () && p->type () < type) type = p->type (); } @@ -213,7 +213,7 @@ IOButtonBase::set_label (IOButtonBase& self, ARDOUR::Session& session, std::shar vector port_connections; - for (auto const& port : io->ports ()) { + for (auto const& port : *io->ports ()) { port_connections.clear (); port->get_connections (port_connections); @@ -306,8 +306,9 @@ IOButtonBase::set_label (IOButtonBase& self, ARDOUR::Session& session, std::shar session.engine ().get_physical_outputs (dt, phys); playorcapture = "playback_"; } - for (PortSet::iterator port = io->ports ().begin (dt); - port != io->ports ().end (dt); + std::shared_ptr ps (io->ports ()); + for (PortSet::iterator port = ps->begin (dt); + port != ps->end (dt); ++port) { string pn = ""; for (auto const& s : phys) { @@ -328,7 +329,7 @@ IOButtonBase::set_label (IOButtonBase& self, ARDOUR::Session& session, std::shar temp_label.str (""); /* erase the failed attempt */ break; } - if (port != io->ports ().begin (dt)) { + if (port != ps->begin (dt)) { temp_label << "/"; } temp_label << pn; @@ -368,10 +369,11 @@ IOButtonBase::set_label (IOButtonBase& self, ARDOUR::Session& session, std::shar /* Is each main-typed channel connected to a single and different port with * the same client name (e.g. another JACK client) ? */ if (!have_label && each_typed_port_has_one_connection) { - string maybe_client = ""; - vector connections; - for (PortSet::iterator port = io->ports ().begin (dt); - port != io->ports ().end (dt); + string maybe_client = ""; + vector connections; + std::shared_ptr ps (io->ports ()); + for (PortSet::iterator port = ps->begin (dt); + port != ps->end (dt); ++port) { port_connections.clear (); port->get_connections (port_connections); diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc index 4f671074e4..5b64ceb5ff 100644 --- a/gtk2_ardour/io_selector.cc +++ b/gtk2_ardour/io_selector.cc @@ -79,7 +79,7 @@ IOSelector::setup_type () int N = 0; DataType type_with_ports = DataType::NIL; for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) { - if (_io->ports().num_ports (*i)) { + if (_io->ports()->num_ports (*i)) { type_with_ports = *i; ++N; } diff --git a/gtk2_ardour/plugin_pin_dialog.cc b/gtk2_ardour/plugin_pin_dialog.cc index acce858f9f..e847f5a5e2 100644 --- a/gtk2_ardour/plugin_pin_dialog.cc +++ b/gtk2_ardour/plugin_pin_dialog.cc @@ -482,12 +482,12 @@ PluginPinWidget::refill_sidechain_table () } uint32_t r = 0; - PortSet& p (io->ports ()); - bool can_remove = p.num_ports () > 1; - for (PortSet::iterator i = p.begin (DataType::MIDI); i != p.end (DataType::MIDI); ++i) { + std::shared_ptr p (io->ports ()); + bool can_remove = p->num_ports () > 1; + for (PortSet::iterator i = p->begin (DataType::MIDI); i != p->end (DataType::MIDI); ++i) { r += add_port_to_table (*i, r, can_remove); } - for (PortSet::iterator i = p.begin (DataType::AUDIO); i != p.end (DataType::AUDIO); ++i) { + for (PortSet::iterator i = p->begin (DataType::AUDIO); i != p->end (DataType::AUDIO); ++i) { r += add_port_to_table (*i, r, can_remove); } _sidechain_tbl->show_all (); @@ -1857,8 +1857,8 @@ PluginPinWidget::add_send_from (std::weak_ptr wp, std::weak_ptrdisconnect_all (); DataType dt = p->type (); - PortSet& ps (send->output ()->ports ()); - for (PortSet::iterator i = ps.begin (dt); i != ps.end (dt); ++i) { + std::shared_ptr ps (send->output ()->ports ()); + for (PortSet::iterator i = ps->begin (dt); i != ps->end (dt); ++i) { p->connect (&(**i)); } diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index 531c368673..8dfc7fb2ec 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -636,8 +636,8 @@ ProcessorEntry::name (Width w) const if (send->remove_on_disconnect ()) { // assume it's a sidechain, find pretty name of connected port(s) - PortSet& ps (send->output ()->ports ()); - for (PortSet::iterator i = ps.begin (); i != ps.end () && pretty_ok; ++i) { + shared_ptr ps (send->output ()->ports ()); + for (auto i = ps->begin (); i != ps->end () && pretty_ok; ++i) { vector connections; if (i->get_connections (connections)) { vector::const_iterator ci; diff --git a/libs/ardour/ardour/buffer_set.h b/libs/ardour/ardour/buffer_set.h index 38891f4a47..a791ad2406 100644 --- a/libs/ardour/ardour/buffer_set.h +++ b/libs/ardour/ardour/buffer_set.h @@ -71,8 +71,8 @@ public: void clear(); - void attach_buffers (PortSet& ports); - void get_backend_port_addresses (PortSet &, samplecnt_t); + void attach_buffers (PortSet const& ports); + void get_backend_port_addresses (PortSet&, samplecnt_t); /* the capacity here is a size_t and has a different interpretation depending on the DataType of the buffers. for audio, its a sample count. for MIDI diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index b807c5fcf2..05484c063f 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -31,6 +31,7 @@ #include "pbd/fastlog.h" #include "pbd/undo.h" +#include "pbd/rcu.h" #include "pbd/statefuldestructible.h" #include "pbd/controllable.h" #include "pbd/enum_convert.h" @@ -131,8 +132,8 @@ public: void set_public_port_latencies (samplecnt_t value, bool playback) const; void set_public_port_latency_from_connections () const; - PortSet& ports() { return _ports; } - const PortSet& ports() const { return _ports; } + std::shared_ptr ports (); + std::shared_ptr ports () const; bool has_port (std::shared_ptr) const; @@ -205,8 +206,7 @@ protected: bool _sendish; private: - mutable Glib::Threads::RWLock _io_lock; - PortSet _ports; + SerializedRCUManager _ports; void reestablish_port_subscriptions (); PBD::ScopedConnectionList _port_connections; diff --git a/libs/ardour/ardour/port_set.h b/libs/ardour/ardour/port_set.h index 6ec32cce44..a9aba4ca1a 100644 --- a/libs/ardour/ardour/port_set.h +++ b/libs/ardour/ardour/port_set.h @@ -41,7 +41,7 @@ class MidiPort; * and once in a vector of all port (_all_ports). This is to speed up the * fairly common case of iterating over all ports. */ -class LIBARDOUR_API PortSet : public boost::noncopyable { +class LIBARDOUR_API PortSet { public: PortSet(); diff --git a/libs/ardour/buffer_set.cc b/libs/ardour/buffer_set.cc index bf847b6333..3aa3a7333c 100644 --- a/libs/ardour/buffer_set.cc +++ b/libs/ardour/buffer_set.cc @@ -102,7 +102,7 @@ BufferSet::clear() * XXX: this *is* called in a process context; I'm not sure quite what `should not' means above. */ void -BufferSet::attach_buffers (PortSet& ports) +BufferSet::attach_buffers (PortSet const& ports) { const ChanCount& count (ports.count()); diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc index a2134ef774..b350c9a4fe 100644 --- a/libs/ardour/delivery.cc +++ b/libs/ardour/delivery.cc @@ -262,10 +262,10 @@ Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample return; } - PortSet& ports (_output->ports()); + std::shared_ptr ports (_output->ports()); gain_t tgain; - if (ports.num_ports () == 0) { + if (ports->num_ports () == 0) { return; } @@ -274,7 +274,7 @@ Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample */ // TODO delayline -- latency-compensation - output_buffers().get_backend_port_addresses (ports, nframes); + output_buffers().get_backend_port_addresses (*ports, nframes); // this Delivery processor is not a derived type, and thus we assume // we really can modify the buffers passed in (it is almost certainly @@ -555,10 +555,8 @@ Delivery::non_realtime_transport_stop (samplepos_t now, bool flush) } if (_output) { - PortSet& ports (_output->ports()); - - for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) { - i->transport_stopped (); + for (auto const& p : *_output->ports()) { + p->transport_stopped (); } } } @@ -567,10 +565,8 @@ void Delivery::realtime_locate (bool for_loop_end) { if (_output) { - PortSet& ports (_output->ports()); - - for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) { - i->realtime_locate (for_loop_end); + for (auto const& p : *_output->ports()) { + p->realtime_locate (for_loop_end); } } } @@ -601,6 +597,7 @@ Delivery::target_gain () case Listen: mp = MuteMaster::Listen; break; + case DirectOuts: case Send: case Insert: case Aux: @@ -673,7 +670,7 @@ Delivery::output_changed (IOChange change, void* /*src*/) { if (change.type & IOChange::ConfigurationChanged) { reset_panner (); - _output_buffers->attach_buffers (_output->ports ()); + _output_buffers->attach_buffers (*_output->ports ()); } } diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 8faaac741a..32d412d1c3 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -80,6 +80,7 @@ IO::IO (Session& s, const string& name, Direction dir, DataType default_type, bo , _direction (dir) , _default_type (default_type) , _sendish (sendish) + , _ports (new PortSet) { _active = true; setup_bundle (); @@ -90,6 +91,7 @@ IO::IO (Session& s, const XMLNode& node, DataType dt, bool sendish) , _direction (Input) , _default_type (dt) , _sendish (sendish) + , _ports (new PortSet) { _active = true; @@ -99,42 +101,38 @@ IO::IO (Session& s, const XMLNode& node, DataType dt, bool sendish) IO::~IO () { - DEBUG_TRACE (DEBUG::Ports, string_compose ("IO %1 unregisters %2 ports\n", name(), _ports.num_ports())); + DEBUG_TRACE (DEBUG::Ports, string_compose ("IO %1 unregisters %2 ports\n", name(), ports()->num_ports())); BLOCK_PROCESS_CALLBACK (); - Glib::Threads::RWLock::WriterLock wl (_io_lock); - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - _session.engine().unregister_port (*i); + for (auto const& p : *ports()) { + _session.engine().unregister_port (p); } } +std::shared_ptr +IO::ports () { + return std::const_pointer_cast (_ports.reader ()); +} + +std::shared_ptr +IO::ports () const { + return _ports.reader (); +} + void IO::connection_change (std::shared_ptr a, std::shared_ptr b) { if (_session.deletion_in_progress ()) { return; } - /* 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::Threads::RWLock::WriterLock wl (_io_lock, Glib::Threads::TRY_LOCK); - - if (wl.locked()) { - /* we took the lock, so we cannot be here from inside - * ::disconnect() - */ - wl.release (); // release lock before emitting signal - 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. - */ + /* Note: + * this could be called from within our own ::disconnect() method(s) + * or from somewhere that operates directly on a port. + */ + std::shared_ptr ports = _ports.reader(); + if (ports->contains (a) || ports->contains (b)) { + changed (IOChange (IOChange::ConnectionsChanged), this); /* EMIT SIGNAL */ } } @@ -143,9 +141,9 @@ IO::silence (samplecnt_t nframes) { /* io_lock, not taken: function must be called from Session::process() calltree */ - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - if (i->port_handle ()) { - i->get_buffer(nframes).silence (nframes); + for (auto const& p : *ports ()) { + if (p->port_handle ()) { + p->get_buffer (nframes).silence (nframes); } } } @@ -157,24 +155,19 @@ IO::disconnect (std::shared_ptr our_port, string other_port, void* src) return 0; } - { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); + /* check that our_port is really one of ours */ + if (!ports()->contains (our_port)) { + return -1; + } - /* check that our_port is really one of ours */ + /* disconnect it from the source */ - if ( ! _ports.contains(our_port)) { - return -1; - } + DEBUG_TRACE (DEBUG::PortConnectIO, + string_compose("IO::disconnect %1 from %2\n", our_port->name(), other_port)); - /* disconnect it from the source */ - - DEBUG_TRACE (DEBUG::PortConnectIO, - string_compose("IO::disconnect %1 from %2\n", our_port->name(), other_port)); - - if (our_port->disconnect (other_port)) { - error << string_compose(_("IO: cannot disconnect port %1 from %2"), our_port->name(), other_port) << endmsg; - return -1; - } + if (our_port->disconnect (other_port)) { + error << string_compose(_("IO: cannot disconnect port %1 from %2"), our_port->name(), other_port) << endmsg; + return -1; } changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ @@ -191,24 +184,19 @@ IO::connect (std::shared_ptr our_port, string other_port, void* src) return 0; } - { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - - /* check that our_port is really one of ours */ - - if ( ! _ports.contains(our_port) ) { - return -1; - } - - /* connect it to the source */ - - DEBUG_TRACE (DEBUG::PortConnectIO, - string_compose("IO::connect %1 to %2\n", our_port->name(), other_port)); - - if (our_port->connect (other_port)) { - return -1; - } + /* check that our_port is really one of ours */ + if (!ports()->contains (our_port)) { + return -1; } + + /* connect it to the source */ + DEBUG_TRACE (DEBUG::PortConnectIO, + string_compose("IO::connect %1 to %2\n", our_port->name(), other_port)); + + if (our_port->connect (other_port)) { + return -1; + } + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ _session.set_dirty (); return 0; @@ -223,7 +211,7 @@ IO::can_add_port (DataType type) const case DataType::AUDIO: return true; case DataType::MIDI: - return _ports.count ().n_midi() < 1; + return ports()->count ().n_midi() < 1; } abort(); /*NOTREACHED*/ return false; @@ -232,7 +220,7 @@ IO::can_add_port (DataType type) const int IO::remove_port (std::shared_ptr port, void* src) { - ChanCount before = _ports.count (); + ChanCount before = ports()->count (); ChanCount after = before; after.set (port->type(), after.get (port->type()) - 1); @@ -247,26 +235,28 @@ IO::remove_port (std::shared_ptr port, void* src) BLOCK_PROCESS_CALLBACK (); { - Glib::Threads::RWLock::WriterLock wl (_io_lock); + RCUWriter writer (_ports); + std::shared_ptr p = writer.get_copy (); - if (_ports.remove(port)) { + if (p->remove (port)) { change.type = IOChange::Type (change.type | IOChange::ConfigurationChanged); change.before = before; - change.after = _ports.count (); + change.after = p->count (); if (port->connected()) { change.type = IOChange::Type (change.type | IOChange::ConnectionsChanged); } - _session.engine().unregister_port (port); } + _session.engine().unregister_port (port); } PortCountChanged (n_ports()); /* EMIT SIGNAL */ if (change.type != IOChange::NoChange) { changed (change, src); - _buffers.attach_buffers (_ports); + std::shared_ptr ports = _ports.reader(); + _buffers.attach_buffers (*ports); } } @@ -302,7 +292,7 @@ IO::add_port (string destination, void* src, DataType type) return -1; } - ChanCount before = _ports.count (); + ChanCount before = ports()->count (); ChanCount after = before; after.set (type, after.get (type) + 1); @@ -316,35 +306,35 @@ IO::add_port (string destination, void* src, DataType type) { BLOCK_PROCESS_CALLBACK (); + /* Create a new port */ + + string portname = build_legal_port_name (type); + + if (_direction == Input) { + if ((our_port = _session.engine().register_input_port (type, portname)) == 0) { + error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg; + return -1; + } + } else { + if ((our_port = _session.engine().register_output_port (type, portname)) == 0) { + error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg; + return -1; + } + } { - Glib::Threads::RWLock::WriterLock wl (_io_lock); - - /* Create a new port */ - - string portname = build_legal_port_name (type); - - if (_direction == Input) { - if ((our_port = _session.engine().register_input_port (type, portname)) == 0) { - error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg; - return -1; - } - } else { - if ((our_port = _session.engine().register_output_port (type, portname)) == 0) { - error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg; - return -1; - } - } - - change.before = _ports.count (); - _ports.add (our_port); + RCUWriter writer (_ports); + std::shared_ptr p = writer.get_copy (); + change.before = p->count (); + p->add (our_port); + change.after = p->count (); } PortCountChanged (n_ports()); /* EMIT SIGNAL */ + change.type = IOChange::ConfigurationChanged; - change.after = _ports.count (); changed (change, src); /* EMIT SIGNAL */ - _buffers.attach_buffers (_ports); + _buffers.attach_buffers (*ports()); } if (!destination.empty()) { @@ -363,12 +353,8 @@ IO::add_port (string destination, void* src, DataType type) int IO::disconnect (void* src) { - { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - i->disconnect_all (); - } + for (auto const& p : *ports()) { + p->disconnect_all (); } changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ @@ -385,85 +371,90 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed) #endif std::shared_ptr port; - vector > deleted_ports; - changed = false; + changed = false; - for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + { + RCUWriter writer (_ports); + std::shared_ptr p = writer.get_copy (); - const size_t n = count.get(*t); + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - const ChanCount n_ports = _ports.count (); - /* remove unused ports */ - for (size_t i = n_ports.get(*t); i > n; --i) { - port = _ports.port(*t, i-1); + const size_t n = count.get (*t); - assert(port); - _ports.remove(port); + const ChanCount n_ports = p->count (); - /* hold a reference to the port so that we can ensure - * that this thread, and not a JACK notification thread, - * holds the final reference. + /* remove unused ports */ + vector > deleted_ports; + for (size_t i = n_ports.get (*t); i > n; --i) { + port = p->port (*t, i-1); + + assert (port); + p->remove (port); + + /* hold a reference to the port so that we can ensure + * that this thread, and not a JACK notification thread, + * holds the final reference. + */ + + deleted_ports.push_back (port); + _session.engine().unregister_port (port); + + changed = true; + } + + /* this will drop the final reference to the deleted ports, + * which will in turn call their destructors, which will in + * turn call the backend to unregister them. + * + * There will no connect/disconnect or register/unregister + * callbacks from the backend until we get here, because + * they are driven by the Port destructor. The destructor + * will not execute until we drop the final reference, + * which all happens right .... here. */ + deleted_ports.clear (); - deleted_ports.push_back (port); - _session.engine().unregister_port (port); + /* create any necessary new ports */ + while (p->count ().get(*t) < n) { - changed = true; - } + string portname = build_legal_port_name (*t); - /* this will drop the final reference to the deleted ports, - * which will in turn call their destructors, which will in - * turn call the backend to unregister them. - * - * There will no connect/disconnect or register/unregister - * callbacks from the backend until we get here, because - * they are driven by the Port destructor. The destructor - * will not execute until we drop the final reference, - * which all happens right .... here. - */ - deleted_ports.clear (); + try { - /* create any necessary new ports */ - while (_ports.count ().get(*t) < n) { - - string portname = build_legal_port_name (*t); - - try { - - if (_direction == Input) { - if ((port = _session.engine().register_input_port (*t, portname)) == 0) { - error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg; - return -1; - } - } else { - if ((port = _session.engine().register_output_port (*t, portname)) == 0) { - error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg; - return -1; + if (_direction == Input) { + if ((port = _session.engine().register_input_port (*t, portname)) == 0) { + error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg; + return -1; + } + } else { + if ((port = _session.engine().register_output_port (*t, portname)) == 0) { + error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg; + return -1; + } } + } catch (AudioEngine::PortRegistrationFailure& err) { + /* pass it on */ + throw; } - } - catch (AudioEngine::PortRegistrationFailure& err) { - /* pass it on */ - throw; + p->add (port); + changed = true; } - - _ports.add (port); - changed = true; } + /* end of RCUWriter scope */ } if (changed) { - const ChanCount n_ports = _ports.count (); + const ChanCount n_ports = ports ()->count (); PortCountChanged (n_ports); /* EMIT SIGNAL */ _session.set_dirty (); } if (clear) { /* disconnect all existing ports so that we get a fresh start */ - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - i->disconnect_all (); + for (auto const& p : *ports ()) { + p->disconnect_all (); } } @@ -478,28 +469,24 @@ IO::ensure_ports (ChanCount count, bool clear, void* src) assert (!AudioEngine::instance()->process_lock().trylock()); #endif - bool changed = false; - if (count == n_ports() && !clear) { return 0; } + bool changed = false; IOChange change; - change.before = _ports.count (); + change.before = ports()->count (); - { - Glib::Threads::RWLock::WriterLock wl (_io_lock); - if (ensure_ports_locked (count, clear, changed)) { - return -1; - } + if (ensure_ports_locked (count, clear, changed)) { + return -1; } if (changed) { - change.after = _ports.count (); + change.after = ports()->count (); change.type = IOChange::ConfigurationChanged; this->changed (change, src); /* EMIT SIGNAL */ - _buffers.attach_buffers (_ports); + _buffers.attach_buffers (*ports()); setup_bundle (); _session.set_dirty (); } @@ -511,8 +498,8 @@ void IO::reestablish_port_subscriptions () { _port_connections.drop_connections (); - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - i->ConnectedOrDisconnected.connect_same_thread (*this, boost::bind (&IO::connection_change, this, _1, _2)); + for (auto const& p : *ports ()) { + p->ConnectedOrDisconnected.connect_same_thread (*this, boost::bind (&IO::connection_change, this, _1, _2)); } } @@ -537,7 +524,6 @@ XMLNode& IO::state () const { XMLNode* node = new XMLNode (state_node_name); - Glib::Threads::RWLock::WriterLock wl (_io_lock); node->set_property ("name", name()); node->set_property ("id", id ()); @@ -548,8 +534,8 @@ IO::state () const node->set_property("pretty-name", _pretty_name_prefix); } - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { - node->add_child_nocopy (i->get_state ()); + for (auto const& p : *_ports.reader ()) { + node->add_child_nocopy (p->get_state ()); } return *node; @@ -597,9 +583,11 @@ IO::set_state (const XMLNode& node, int version) * This is needed to properly restore connections when creating * external sends from templates because the IO name changes. */ - PortSet::iterator i = _ports.begin(); - XMLNodeConstIterator x = node.children().begin(); - for (; i != _ports.end() && x != node.children().end(); ++i, ++x) { + std::shared_ptr ports = _ports.reader (); + + PortSet::const_iterator i = ports->begin(); + XMLNodeConstIterator x = node.children().begin(); + for (; i != ports->end() && x != node.children().end(); ++i, ++x) { if ((*x)->name() == "Port") { (*x)->remove_property (X_("name")); (*x)->set_property (X_("name"), i->name()); @@ -1127,11 +1115,11 @@ IO::set_name (const string& requested_name) name = legalize_io_name (name); - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - string current_name = i->name(); + for (auto const& p : *ports ()) { + string current_name = p->name(); assert (current_name.find (_name) != std::string::npos); current_name.replace (current_name.find (_name), _name.val().length(), name); - i->set_name (current_name); + p->set_name (current_name); } bool const r = SessionObject::set_name (name); @@ -1158,11 +1146,11 @@ IO::apply_pretty_name () if (_pretty_name_prefix.empty ()) { return; } - for (PortSet::iterator i = _ports.begin (); i != _ports.end(); ++i, ++pn) { - (*i)->set_pretty_name (string_compose (("%1/%2 %3"), - _pretty_name_prefix, - _direction == Output ? S_("IO|Out") : S_("IO|In"), - pn)); + for (auto const& p : *ports ()) { + p->set_pretty_name (string_compose (("%1/%2 %3"), + _pretty_name_prefix, + _direction == Output ? S_("IO|Out") : S_("IO|In"), + pn++)); } } @@ -1171,8 +1159,8 @@ IO::set_private_port_latencies (samplecnt_t value, bool playback) { LatencyRange lat; lat.min = lat.max = value; - for (PortSet::iterator i = _ports.begin (); i != _ports.end(); ++i) { - i->set_private_latency_range (lat, playback); + for (auto const& p : *ports ()) { + p->set_private_latency_range (lat, playback); } } @@ -1186,11 +1174,13 @@ IO::set_public_port_latency_from_connections () const lr.min = ~((pframes_t) 0); lr.max = 0; - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { - if (i->connected()) { + std::shared_ptr ps = ports (); + + for (auto const& p : *ps) { + if (p->connected()) { connected = true; } - i->collect_latency_from_backend (lr, playback); + p->collect_latency_from_backend (lr, playback); } if (!connected) { @@ -1198,8 +1188,8 @@ IO::set_public_port_latency_from_connections () const lr.min = lr.max = latency (); } - for (PortSet::const_iterator i = _ports.begin (); i != _ports.end(); ++i) { - i->set_public_latency_range (lr, playback); + for (auto const& p : *ps) { + p->set_public_latency_range (lr, playback); } } @@ -1208,8 +1198,8 @@ IO::set_public_port_latencies (samplecnt_t value, bool playback) const { LatencyRange lat; lat.min = lat.max = value; - for (PortSet::const_iterator i = _ports.begin (); i != _ports.end(); ++i) { - i->set_public_latency_range (lat, playback); + for (auto const& p : *_ports.reader ()) { + p->set_public_latency_range (lat, playback); } } @@ -1218,11 +1208,9 @@ IO::latency () const { samplecnt_t max_latency = 0; - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { + for (auto const& p : *_ports.reader ()) { samplecnt_t latency; - if ((latency = i->private_latency_range (_direction == Output).max) > max_latency) { + if ((latency = p->private_latency_range (_direction == Output).max) > max_latency) { DEBUG_TRACE (DEBUG::LatencyIO, string_compose ("port %1 has %2 latency of %3 - use\n", name(), ((_direction == Output) ? "PLAYBACK" : "CAPTURE"), @@ -1232,7 +1220,7 @@ IO::latency () const } DEBUG_TRACE (DEBUG::LatencyIO, string_compose ("%1: max %4 latency from %2 ports = %3\n", - name(), _ports.num_ports(), max_latency, + name(), ports()->num_ports(), max_latency, ((_direction == Output) ? "PLAYBACK" : "CAPTURE"))); return max_latency; } @@ -1274,27 +1262,27 @@ IO::connected_latency (bool for_playback) const * -> Route::update_signal_latency () * -> IO::connected_latency () */ - Glib::Threads::RWLock::ReaderLock rl (_io_lock); + std::shared_ptr ps = ports (); samplecnt_t max_latency = 0; bool connected = false; /* if output is not connected to anything, use private latency */ - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { - if (i->connected()) { + for (auto const& p : *ps) { + if (p->connected()) { connected = true; max_latency = 0; break; } samplecnt_t latency; - if ((latency = i->private_latency_range (for_playback).max) > max_latency) { + if ((latency = p->private_latency_range (for_playback).max) > max_latency) { max_latency = latency; } } if (connected) { - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { + for (auto const& p : *ps) { LatencyRange lr; - i->get_connected_latency_range (lr, for_playback); + p->get_connected_latency_range (lr, for_playback); if (lr.max > max_latency) { max_latency = lr.max; } @@ -1314,19 +1302,14 @@ IO::connect_ports_to_bundle (std::shared_ptr c, bool exclusive, { BLOCK_PROCESS_CALLBACK (); - { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - - if (exclusive) { - for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { - i->disconnect_all (); - } + if (exclusive) { + for (auto const& p : *ports ()) { + p->disconnect_all (); } - - c->connect (_bundle, _session.engine(), allow_partial); - } + c->connect (_bundle, _session.engine(), allow_partial); + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ return 0; } @@ -1336,14 +1319,9 @@ IO::disconnect_ports_from_bundle (std::shared_ptr c, void* src) { BLOCK_PROCESS_CALLBACK (); - { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); + c->disconnect (_bundle, _session.engine()); - c->disconnect (_bundle, _session.engine()); - - /* If this is a UserBundle, make a note of what we've done */ - - } + /* If this is a UserBundle, make a note of what we've done */ changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ return 0; @@ -1416,7 +1394,9 @@ IO::find_port_hole (const char* base) uint32_t n; - if (_ports.empty()) { + std::shared_ptr ports = _ports.reader(); + + if (ports->empty()) { return 1; } @@ -1425,35 +1405,33 @@ IO::find_port_hole (const char* base) for (n = 1; n < 9999; ++n) { std::vector buf (AudioEngine::instance()->port_name_size()); - PortSet::iterator i = _ports.begin(); + PortSet::const_iterator i = ports->begin (); snprintf (&buf[0], buf.size()+1, _("%s %u"), base, n); - for ( ; i != _ports.end(); ++i) { - if (string(i->name()) == string(&buf[0])) { + for ( ; i != ports->end (); ++i) { + if (string (i->name()) == string (&buf[0])) { break; } } - if (i == _ports.end()) { + if (i == ports->end()) { break; } } return n; } - std::shared_ptr IO::audio(uint32_t n) const { - return _ports.nth_audio_port (n); - + return ports()->nth_audio_port (n); } std::shared_ptr IO::midi(uint32_t n) const { - return _ports.nth_midi_port (n); + return ports()->nth_midi_port (n); } /** @@ -1472,16 +1450,16 @@ IO::setup_bundle () _bundle->set_name (string_compose ("%1 %2", _name, _direction == Input ? _("in") : _("out"))); + std::shared_ptr ports = _ports.reader(); + int c = 0; for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) { - - uint32_t const N = _ports.count().get (*i); + uint32_t const N = ports->count().get (*i); for (uint32_t j = 0; j < N; ++j) { _bundle->add_channel (bundle_channel_name (j, N, *i), *i); - _bundle->set_port (c, _session.engine().make_port_name_non_relative (_ports.port(*i, j)->name())); + _bundle->set_port (c, _session.engine().make_port_name_non_relative (ports->port (*i, j)->name())); ++c; } - } reestablish_port_subscriptions (); @@ -1591,10 +1569,7 @@ IO::set_name_in_state (XMLNode& node, const string& new_name) bool IO::connected () const { - /* do we have any connections at all? */ - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - - for (PortSet::const_iterator p = _ports.begin(); p != _ports.end(); ++p) { + for (auto const& p : *_ports.reader ()) { if (p->connected()) { return true; } @@ -1632,30 +1607,30 @@ IO::connected_to (std::shared_ptr other) const bool IO::connected_to (const string& str) const { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { - if (i->connected_to (str)) { + for (auto const& p : *_ports.reader ()) { + if (p->connected_to (str)) { return true; } } - return false; } void IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset) { - assert(bufs.available() >= _ports.count()); + std::shared_ptr ps = ports (); - if (_ports.count() == ChanCount::ZERO) { + assert (bufs.available() >= ps->count()); + + if (ps->count() == ChanCount::ZERO) { return; } - bufs.set_count (_ports.count()); + bufs.set_count (ps->count()); for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - PortSet::iterator i = _ports.begin(*t); - BufferSet::iterator b = bufs.begin(*t); + PortSet::iterator i = ps->begin (*t); + BufferSet::iterator b = bufs.begin (*t); for (uint32_t off = 0; off < offset.get(*t); ++off, ++b) { if (b == bufs.end(*t)) { @@ -1663,7 +1638,7 @@ IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset) } } - for ( ; i != _ports.end(*t); ++i, ++b) { + for ( ; i != ps->end (*t); ++i, ++b) { const Buffer& bb (i->get_buffer (nframes)); b->read_from (bb, nframes); } @@ -1673,15 +1648,16 @@ IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset) void IO::copy_to_outputs (BufferSet& bufs, DataType type, pframes_t nframes, samplecnt_t offset) { - PortSet::iterator o = _ports.begin(type); - BufferSet::iterator i = bufs.begin(type); + std::shared_ptr ps = ports (); + + PortSet::iterator o = ps->begin (type); + BufferSet::iterator i = bufs.begin (type); BufferSet::iterator prev = i; assert(i != bufs.end(type)); // or second loop will crash - // Copy any buffers 1:1 to outputs - - while (i != bufs.end(type) && o != _ports.end (type)) { + /* Copy any buffers 1:1 to outputs */ + while (i != bufs.end (type) && o != ps->end (type)) { Buffer& port_buffer (o->get_buffer (nframes)); port_buffer.read_from (*i, nframes, offset); prev = i; @@ -1689,9 +1665,8 @@ IO::copy_to_outputs (BufferSet& bufs, DataType type, pframes_t nframes, samplecn ++o; } - // Copy last buffer to any extra outputs - - while (o != _ports.end(type)) { + /* Copy last buffer to any extra outputs */ + while (o != ps->end (type)) { Buffer& port_buffer (o->get_buffer (nframes)); port_buffer.read_from (*prev, nframes, offset); ++o; @@ -1703,7 +1678,7 @@ IO::flush_buffers (pframes_t nframes) { /* when port is both externally and internally connected, * make data available to downstream internal ports */ - for (auto const& p : _ports) { + for (auto const& p : *ports ()) { p->flush_buffers (nframes); } } @@ -1713,22 +1688,19 @@ IO::port_by_name (const std::string& str) const { /* to be called only from ::set_state() - no locking */ - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { - - if (i->name() == str) { - return std::const_pointer_cast (*i); + for (auto const& p : *_ports.reader ()) { + if (p->name() == str) { + return std::const_pointer_cast (p); } } - return std::shared_ptr (); } bool IO::physically_connected () const { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { - if (i->physically_connected()) { + for (auto const& p : *_ports.reader ()) { + if (p->physically_connected()) { return true; } } @@ -1739,28 +1711,25 @@ IO::physically_connected () const bool IO::has_ext_connection () const { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { - if (i->has_ext_connection()) { + for (auto const& p : *_ports.reader ()) { + if (p->has_ext_connection()) { return true; } } - return false; } bool IO::has_port (std::shared_ptr p) const { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - return _ports.contains (p); + return ports()->contains (p); } std::shared_ptr IO::nth (uint32_t n) const { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - if (n < _ports.num_ports()) { - return _ports.port(n); + std::shared_ptr ports = _ports.reader (); + if (n < ports->num_ports ()) { + return ports->port (n); } else { return std::shared_ptr (); } @@ -1768,6 +1737,5 @@ IO::nth (uint32_t n) const { const ChanCount& IO::n_ports () const { - Glib::Threads::RWLock::ReaderLock rl (_io_lock); - return _ports.count(); + return ports()->count(); } diff --git a/libs/ardour/io_plug.cc b/libs/ardour/io_plug.cc index b261606bb0..ae97c0b1cd 100644 --- a/libs/ardour/io_plug.cc +++ b/libs/ardour/io_plug.cc @@ -271,14 +271,14 @@ IOPlug::set_public_latency (bool playback) /* Step1: set private port latency * compare to Route::set_private_port_latencies, Route::update_port_latencies */ - PortSet& from = playback ? _output->ports () : _input->ports (); - PortSet& to = playback ? _input->ports () : _output->ports (); + std::shared_ptr from = playback ? _output->ports () : _input->ports (); + std::shared_ptr to = playback ? _input->ports () : _output->ports (); LatencyRange all_connections; all_connections.min = ~((pframes_t) 0); all_connections.max = 0; - for (auto const& p : from) { + for (auto const& p : *from) { if (!p->connected ()) { continue; } @@ -294,14 +294,14 @@ IOPlug::set_public_latency (bool playback) } /* set the "from" port latencies to the max/min range of all their connections */ - for (auto const& p : from) { + for (auto const& p : *from) { p->set_private_latency_range (all_connections, playback); } all_connections.min += _plugin_signal_latency; all_connections.max += _plugin_signal_latency; - for (auto const& p : to) { + for (auto const& p : *to) { p->set_private_latency_range (all_connections, playback); } diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 6aa5be70e1..0756e66ae3 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -475,9 +475,8 @@ MidiTrack::non_realtime_locate (samplepos_t spos) void MidiTrack::push_midi_input_to_step_edit_ringbuffer (samplecnt_t nframes) { - PortSet& ports (_input->ports()); - - for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) { + std::shared_ptr ports (_input->ports()); + for (PortSet::iterator p = ports->begin (DataType::MIDI); p != ports->end (DataType::MIDI); ++p) { Buffer& b (p->get_buffer (nframes)); const MidiBuffer* const mb = dynamic_cast(&b); @@ -874,9 +873,8 @@ MidiTrack::map_input_active (bool yn) return; } - PortSet& ports (_input->ports()); - - for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) { + std::shared_ptr ports (_input->ports()); + for (PortSet::iterator p = ports->begin (DataType::MIDI); p != ports->end (DataType::MIDI); ++p) { std::shared_ptr mp = std::dynamic_pointer_cast (*p); if (yn != mp->input_active()) { mp->set_input_active (yn); @@ -947,10 +945,8 @@ MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition * port level. */ - PortSet& ports (_output->ports()); - - for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) { - std::shared_ptr mp = std::dynamic_pointer_cast (*p); + for (auto const& p : *_output->ports()) { + std::shared_ptr mp = std::dynamic_pointer_cast (p); if (mp) { mp->require_resolve (); } diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc index 7449c0d96e..3108db4c45 100644 --- a/libs/ardour/port_insert.cc +++ b/libs/ardour/port_insert.cc @@ -147,8 +147,8 @@ PortInsert::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp if (_input->n_ports().n_audio() != 0) { - AudioBuffer& outbuf (_output->ports().nth_audio_port(0)->get_audio_buffer (nframes)); - Sample* in = _input->ports().nth_audio_port(0)->get_audio_buffer (nframes).data(); + AudioBuffer& outbuf (_output->ports()->nth_audio_port(0)->get_audio_buffer (nframes)); + Sample* in = _input->ports()->nth_audio_port(0)->get_audio_buffer (nframes).data(); Sample* out = outbuf.data(); _mtdm->process (nframes, in, out); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 4d06585ec2..cf574b2a66 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -5180,10 +5180,10 @@ Route::set_private_port_latencies (bool playback) const if (playback) { /* playback: propagate latency from "outside the route" to outputs to inputs */ - return update_port_latencies (_output->ports (), _input->ports (), true, own_latency); + return update_port_latencies (*_output->ports (), *_input->ports (), true, own_latency); } else { /* capture: propagate latency from "outside the route" to inputs to outputs */ - return update_port_latencies (_input->ports (), _output->ports (), false, own_latency); + return update_port_latencies (*_input->ports (), *_output->ports (), false, own_latency); } } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 4839b1067b..f6f4ed6c4d 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1179,8 +1179,8 @@ Session::add_monitor_section () _master_out->output()->disconnect (this); for (uint32_t n = 0; n < limit; ++n) { - std::shared_ptr p = _monitor_out->input()->ports().nth_audio_port (n); - std::shared_ptr o = _master_out->output()->ports().nth_audio_port (n); + std::shared_ptr p = _monitor_out->input()->ports()->nth_audio_port (n); + std::shared_ptr o = _master_out->output()->ports()->nth_audio_port (n); if (o) { string connect_to = o->name(); @@ -1246,7 +1246,7 @@ Session::auto_connect_monitor_bus () for (uint32_t n = 0; n < limit; ++n) { - std::shared_ptr p = _monitor_out->output()->ports().port(DataType::AUDIO, n); + std::shared_ptr p = _monitor_out->output()->ports()->port(DataType::AUDIO, n); string connect_to; if (outputs[DataType::AUDIO].size() > (n % mod)) { connect_to = outputs[DataType::AUDIO][n % mod]; @@ -1326,8 +1326,8 @@ Session::reset_monitor_section () _monitor_out->output()->ensure_io (mon_chn, false, this); for (uint32_t n = 0; n < limit; ++n) { - std::shared_ptr p = _monitor_out->input()->ports().nth_audio_port (n); - std::shared_ptr o = _master_out->output()->ports().nth_audio_port (n); + std::shared_ptr p = _monitor_out->input()->ports()->nth_audio_port (n); + std::shared_ptr o = _master_out->output()->ports()->nth_audio_port (n); if (o) { string connect_to = o->name(); @@ -1372,7 +1372,7 @@ Session::reset_monitor_section () for (uint32_t n = 0; n < limit; ++n) { - std::shared_ptr p = _monitor_out->output()->ports().port(DataType::AUDIO, n); + std::shared_ptr p = _monitor_out->output()->ports()->port(DataType::AUDIO, n); string connect_to; if (outputs[DataType::AUDIO].size() > (n % mod)) { connect_to = outputs[DataType::AUDIO][n % mod]; @@ -3447,7 +3447,7 @@ Session::new_route_from_template (uint32_t how_many, PresentationInfo::order_t i if (!io) { continue; } - for (auto const& p : io->ports()) { + for (auto const& p : *io->ports()) { p->reconnect (); } } @@ -3456,7 +3456,7 @@ Session::new_route_from_template (uint32_t how_many, PresentationInfo::order_t i if (!io) { continue; } - for (auto const& p : io->ports()) { + for (auto const& p : *io->ports()) { p->reconnect (); } } @@ -4388,9 +4388,7 @@ Session::set_exclusive_input_active (std::shared_ptr rl, bool onoff, for (RouteList::iterator rt = rl->begin(); rt != rl->end(); ++rt) { - PortSet& ps ((*rt)->input()->ports()); - - for (PortSet::iterator p = ps.begin(); p != ps.end(); ++p) { + for (auto const& p : *(*rt)->input()->ports()) { p->get_connections (connections); } @@ -7791,7 +7789,7 @@ Session::auto_connect (const AutoConnectRequest& ar) port = physinputs[(in_offset.get(*t) + i) % nphysical_in]; } - if (!port.empty() && route->input()->connect (route->input()->ports().port(*t, i), port, this)) { + if (!port.empty() && route->input()->connect (route->input()->ports()->port(*t, i), port, this)) { DEBUG_TRACE (DEBUG::PortConnectAuto, "Failed to auto-connect input."); break; } @@ -7812,12 +7810,12 @@ Session::auto_connect (const AutoConnectRequest& ar) } else if ((*t) == DataType::AUDIO && (Config->get_output_auto_connect() & AutoConnectMaster)) { /* master bus is audio only */ if (_master_out && _master_out->n_inputs().get(*t) > 0) { - port = _master_out->input()->ports().port(*t, + port = _master_out->input()->ports()->port(*t, i % _master_out->input()->n_ports().get(*t))->name(); } } - if (!port.empty() && route->output()->connect (route->output()->ports().port(*t, i), port, this)) { + if (!port.empty() && route->output()->connect (route->output()->ports()->port(*t, i), port, this)) { DEBUG_TRACE (DEBUG::PortConnectAuto, "Failed to auto-connect output."); break; } diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 619dd27e59..00f22e3956 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -314,11 +314,12 @@ bool Track::can_record() { bool will_record = true; - for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end() && will_record; ++i) { - if (!i->connected()) + for (auto const& p : *_input->ports()) { + if (!p->connected()) { will_record = false; + break; + } } - return will_record; } @@ -513,16 +514,16 @@ Track::playlist () void Track::request_input_monitoring (bool m) { - for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) { - AudioEngine::instance()->request_input_monitoring ((*i)->name(), m); + for (auto const& p : *_input->ports()) { + AudioEngine::instance()->request_input_monitoring (p->name(), m); } } void Track::ensure_input_monitoring (bool m) { - for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) { - AudioEngine::instance()->ensure_input_monitoring ((*i)->name(), m); + for (auto const& p : *_input->ports()) { + AudioEngine::instance()->ensure_input_monitoring (p->name(), m); } } diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index c542416d34..9eb60147f4 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -6402,16 +6402,16 @@ OSC::cue_new_aux (string name, string dest_1, string dest_2, uint32_t count, lo_ if (aux) { std::shared_ptr r = std::dynamic_pointer_cast(aux); if (dest_1.size()) { - PortSet& ports = r->output()->ports (); + std::shared_ptr ports = r->output()->ports (); if (atoi( dest_1.c_str())) { dest_1 = string_compose ("system:playback_%1", dest_1); } - r->output ()->connect (*(ports.begin()), dest_1, this); + r->output ()->connect (*(ports->begin()), dest_1, this); if (count == 2) { if (atoi( dest_2.c_str())) { dest_2 = string_compose ("system:playback_%1", dest_2); } - PortSet::iterator i = ports.begin(); + PortSet::iterator i = ports->begin(); ++i; r->output ()->connect (*(i), dest_2, this); } @@ -6467,8 +6467,8 @@ OSC::cue_connect_aux (std::string dest, lo_message msg) if (atoi( dest.c_str())) { dest = string_compose ("system:playback_%1", dest); } - PortSet& ports = rt->output()->ports (); - rt->output ()->connect (*(ports.begin()), dest, this); + std::shared_ptr ports = rt->output()->ports (); + rt->output ()->connect (*(ports->begin()), dest, this); session->set_dirty(); ret = 0; }