mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
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
This commit is contained in:
parent
dbcf3cfd67
commit
0cb42dffec
18 changed files with 318 additions and 356 deletions
|
|
@ -733,8 +733,8 @@ TrackExportChannelSelector::sync_with_manager_state ()
|
||||||
PortExportChannel::PortSet route_ports;
|
PortExportChannel::PortSet route_ports;
|
||||||
PortExportChannel::PortSet intersection;
|
PortExportChannel::PortSet intersection;
|
||||||
|
|
||||||
PortSet& ps (route->output()->ports ());
|
std::shared_ptr<PortSet> ps (route->output()->ports ());
|
||||||
for (PortSet::audio_iterator p = ps.audio_begin (); p != ps.audio_end (); ++p) {
|
for (PortSet::audio_iterator p = ps->audio_begin (); p != ps->audio_end (); ++p) {
|
||||||
route_ports.insert (*p);
|
route_ports.insert (*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,11 @@ exclusively_connected (std::shared_ptr<IO> dest_io, std::shared_ptr<IO> io, Data
|
||||||
uint32_t n = 0;
|
uint32_t n = 0;
|
||||||
uint32_t cnt = 0;
|
uint32_t cnt = 0;
|
||||||
std::set<uint32_t> pn;
|
std::set<uint32_t> pn;
|
||||||
PortSet const& psa (dest_io->ports ());
|
std::shared_ptr<PortSet const> psa (dest_io->ports ());
|
||||||
PortSet const& psb (io->ports ());
|
std::shared_ptr<PortSet const> psb (io->ports ());
|
||||||
|
|
||||||
for (auto a = psa.begin (dt); a != psa.end (dt); ++a, ++n) {
|
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 b = psb->begin (dt); b != psb->end (dt); ++b) {
|
||||||
if (a->connected_to (b->name ())) {
|
if (a->connected_to (b->name ())) {
|
||||||
++cnt;
|
++cnt;
|
||||||
pn.insert (n);
|
pn.insert (n);
|
||||||
|
|
@ -117,7 +117,7 @@ IOButtonBase::guess_main_type (std::shared_ptr<IO> io)
|
||||||
|
|
||||||
/* Find most likely type among connected ports */
|
/* Find most likely type among connected ports */
|
||||||
DataType type = DataType::NIL; /* NIL is always last so least likely */
|
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)
|
if (p->connected () && p->type () < type)
|
||||||
type = p->type ();
|
type = p->type ();
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +213,7 @@ IOButtonBase::set_label (IOButtonBase& self, ARDOUR::Session& session, std::shar
|
||||||
|
|
||||||
vector<string> port_connections;
|
vector<string> port_connections;
|
||||||
|
|
||||||
for (auto const& port : io->ports ()) {
|
for (auto const& port : *io->ports ()) {
|
||||||
port_connections.clear ();
|
port_connections.clear ();
|
||||||
port->get_connections (port_connections);
|
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);
|
session.engine ().get_physical_outputs (dt, phys);
|
||||||
playorcapture = "playback_";
|
playorcapture = "playback_";
|
||||||
}
|
}
|
||||||
for (PortSet::iterator port = io->ports ().begin (dt);
|
std::shared_ptr<PortSet> ps (io->ports ());
|
||||||
port != io->ports ().end (dt);
|
for (PortSet::iterator port = ps->begin (dt);
|
||||||
|
port != ps->end (dt);
|
||||||
++port) {
|
++port) {
|
||||||
string pn = "";
|
string pn = "";
|
||||||
for (auto const& s : phys) {
|
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 */
|
temp_label.str (""); /* erase the failed attempt */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (port != io->ports ().begin (dt)) {
|
if (port != ps->begin (dt)) {
|
||||||
temp_label << "/";
|
temp_label << "/";
|
||||||
}
|
}
|
||||||
temp_label << pn;
|
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
|
/* Is each main-typed channel connected to a single and different port with
|
||||||
* the same client name (e.g. another JACK client) ? */
|
* the same client name (e.g. another JACK client) ? */
|
||||||
if (!have_label && each_typed_port_has_one_connection) {
|
if (!have_label && each_typed_port_has_one_connection) {
|
||||||
string maybe_client = "";
|
string maybe_client = "";
|
||||||
vector<string> connections;
|
vector<string> connections;
|
||||||
for (PortSet::iterator port = io->ports ().begin (dt);
|
std::shared_ptr<PortSet> ps (io->ports ());
|
||||||
port != io->ports ().end (dt);
|
for (PortSet::iterator port = ps->begin (dt);
|
||||||
|
port != ps->end (dt);
|
||||||
++port) {
|
++port) {
|
||||||
port_connections.clear ();
|
port_connections.clear ();
|
||||||
port->get_connections (port_connections);
|
port->get_connections (port_connections);
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ IOSelector::setup_type ()
|
||||||
int N = 0;
|
int N = 0;
|
||||||
DataType type_with_ports = DataType::NIL;
|
DataType type_with_ports = DataType::NIL;
|
||||||
for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
|
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;
|
type_with_ports = *i;
|
||||||
++N;
|
++N;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -482,12 +482,12 @@ PluginPinWidget::refill_sidechain_table ()
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t r = 0;
|
uint32_t r = 0;
|
||||||
PortSet& p (io->ports ());
|
std::shared_ptr<PortSet> p (io->ports ());
|
||||||
bool can_remove = p.num_ports () > 1;
|
bool can_remove = p->num_ports () > 1;
|
||||||
for (PortSet::iterator i = p.begin (DataType::MIDI); i != p.end (DataType::MIDI); ++i) {
|
for (PortSet::iterator i = p->begin (DataType::MIDI); i != p->end (DataType::MIDI); ++i) {
|
||||||
r += add_port_to_table (*i, r, can_remove);
|
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);
|
r += add_port_to_table (*i, r, can_remove);
|
||||||
}
|
}
|
||||||
_sidechain_tbl->show_all ();
|
_sidechain_tbl->show_all ();
|
||||||
|
|
@ -1857,8 +1857,8 @@ PluginPinWidget::add_send_from (std::weak_ptr<ARDOUR::Port> wp, std::weak_ptr<AR
|
||||||
p->disconnect_all ();
|
p->disconnect_all ();
|
||||||
|
|
||||||
DataType dt = p->type ();
|
DataType dt = p->type ();
|
||||||
PortSet& ps (send->output ()->ports ());
|
std::shared_ptr<PortSet> ps (send->output ()->ports ());
|
||||||
for (PortSet::iterator i = ps.begin (dt); i != ps.end (dt); ++i) {
|
for (PortSet::iterator i = ps->begin (dt); i != ps->end (dt); ++i) {
|
||||||
p->connect (&(**i));
|
p->connect (&(**i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -636,8 +636,8 @@ ProcessorEntry::name (Width w) const
|
||||||
|
|
||||||
if (send->remove_on_disconnect ()) {
|
if (send->remove_on_disconnect ()) {
|
||||||
// assume it's a sidechain, find pretty name of connected port(s)
|
// assume it's a sidechain, find pretty name of connected port(s)
|
||||||
PortSet& ps (send->output ()->ports ());
|
shared_ptr<PortSet const> ps (send->output ()->ports ());
|
||||||
for (PortSet::iterator i = ps.begin (); i != ps.end () && pretty_ok; ++i) {
|
for (auto i = ps->begin (); i != ps->end () && pretty_ok; ++i) {
|
||||||
vector<string> connections;
|
vector<string> connections;
|
||||||
if (i->get_connections (connections)) {
|
if (i->get_connections (connections)) {
|
||||||
vector<string>::const_iterator ci;
|
vector<string>::const_iterator ci;
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ public:
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void attach_buffers (PortSet& ports);
|
void attach_buffers (PortSet const& ports);
|
||||||
void get_backend_port_addresses (PortSet &, samplecnt_t);
|
void get_backend_port_addresses (PortSet&, samplecnt_t);
|
||||||
|
|
||||||
/* the capacity here is a size_t and has a different interpretation depending
|
/* 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
|
on the DataType of the buffers. for audio, its a sample count. for MIDI
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#include "pbd/fastlog.h"
|
#include "pbd/fastlog.h"
|
||||||
#include "pbd/undo.h"
|
#include "pbd/undo.h"
|
||||||
|
#include "pbd/rcu.h"
|
||||||
#include "pbd/statefuldestructible.h"
|
#include "pbd/statefuldestructible.h"
|
||||||
#include "pbd/controllable.h"
|
#include "pbd/controllable.h"
|
||||||
#include "pbd/enum_convert.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_latencies (samplecnt_t value, bool playback) const;
|
||||||
void set_public_port_latency_from_connections () const;
|
void set_public_port_latency_from_connections () const;
|
||||||
|
|
||||||
PortSet& ports() { return _ports; }
|
std::shared_ptr<PortSet> ports ();
|
||||||
const PortSet& ports() const { return _ports; }
|
std::shared_ptr<PortSet const> ports () const;
|
||||||
|
|
||||||
bool has_port (std::shared_ptr<Port>) const;
|
bool has_port (std::shared_ptr<Port>) const;
|
||||||
|
|
||||||
|
|
@ -205,8 +206,7 @@ protected:
|
||||||
bool _sendish;
|
bool _sendish;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable Glib::Threads::RWLock _io_lock;
|
SerializedRCUManager<PortSet> _ports;
|
||||||
PortSet _ports;
|
|
||||||
|
|
||||||
void reestablish_port_subscriptions ();
|
void reestablish_port_subscriptions ();
|
||||||
PBD::ScopedConnectionList _port_connections;
|
PBD::ScopedConnectionList _port_connections;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class MidiPort;
|
||||||
* and once in a vector of all port (_all_ports). This is to speed up the
|
* and once in a vector of all port (_all_ports). This is to speed up the
|
||||||
* fairly common case of iterating over all ports.
|
* fairly common case of iterating over all ports.
|
||||||
*/
|
*/
|
||||||
class LIBARDOUR_API PortSet : public boost::noncopyable {
|
class LIBARDOUR_API PortSet {
|
||||||
public:
|
public:
|
||||||
PortSet();
|
PortSet();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ BufferSet::clear()
|
||||||
* XXX: this *is* called in a process context; I'm not sure quite what `should not' means above.
|
* XXX: this *is* called in a process context; I'm not sure quite what `should not' means above.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
BufferSet::attach_buffers (PortSet& ports)
|
BufferSet::attach_buffers (PortSet const& ports)
|
||||||
{
|
{
|
||||||
const ChanCount& count (ports.count());
|
const ChanCount& count (ports.count());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -262,10 +262,10 @@ Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortSet& ports (_output->ports());
|
std::shared_ptr<PortSet> ports (_output->ports());
|
||||||
gain_t tgain;
|
gain_t tgain;
|
||||||
|
|
||||||
if (ports.num_ports () == 0) {
|
if (ports->num_ports () == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,7 +274,7 @@ Delivery::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO delayline -- latency-compensation
|
// 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
|
// this Delivery processor is not a derived type, and thus we assume
|
||||||
// we really can modify the buffers passed in (it is almost certainly
|
// 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) {
|
if (_output) {
|
||||||
PortSet& ports (_output->ports());
|
for (auto const& p : *_output->ports()) {
|
||||||
|
p->transport_stopped ();
|
||||||
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
|
||||||
i->transport_stopped ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -567,10 +565,8 @@ void
|
||||||
Delivery::realtime_locate (bool for_loop_end)
|
Delivery::realtime_locate (bool for_loop_end)
|
||||||
{
|
{
|
||||||
if (_output) {
|
if (_output) {
|
||||||
PortSet& ports (_output->ports());
|
for (auto const& p : *_output->ports()) {
|
||||||
|
p->realtime_locate (for_loop_end);
|
||||||
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
|
|
||||||
i->realtime_locate (for_loop_end);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -601,6 +597,7 @@ Delivery::target_gain ()
|
||||||
case Listen:
|
case Listen:
|
||||||
mp = MuteMaster::Listen;
|
mp = MuteMaster::Listen;
|
||||||
break;
|
break;
|
||||||
|
case DirectOuts:
|
||||||
case Send:
|
case Send:
|
||||||
case Insert:
|
case Insert:
|
||||||
case Aux:
|
case Aux:
|
||||||
|
|
@ -673,7 +670,7 @@ Delivery::output_changed (IOChange change, void* /*src*/)
|
||||||
{
|
{
|
||||||
if (change.type & IOChange::ConfigurationChanged) {
|
if (change.type & IOChange::ConfigurationChanged) {
|
||||||
reset_panner ();
|
reset_panner ();
|
||||||
_output_buffers->attach_buffers (_output->ports ());
|
_output_buffers->attach_buffers (*_output->ports ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ IO::IO (Session& s, const string& name, Direction dir, DataType default_type, bo
|
||||||
, _direction (dir)
|
, _direction (dir)
|
||||||
, _default_type (default_type)
|
, _default_type (default_type)
|
||||||
, _sendish (sendish)
|
, _sendish (sendish)
|
||||||
|
, _ports (new PortSet)
|
||||||
{
|
{
|
||||||
_active = true;
|
_active = true;
|
||||||
setup_bundle ();
|
setup_bundle ();
|
||||||
|
|
@ -90,6 +91,7 @@ IO::IO (Session& s, const XMLNode& node, DataType dt, bool sendish)
|
||||||
, _direction (Input)
|
, _direction (Input)
|
||||||
, _default_type (dt)
|
, _default_type (dt)
|
||||||
, _sendish (sendish)
|
, _sendish (sendish)
|
||||||
|
, _ports (new PortSet)
|
||||||
{
|
{
|
||||||
_active = true;
|
_active = true;
|
||||||
|
|
||||||
|
|
@ -99,42 +101,38 @@ IO::IO (Session& s, const XMLNode& node, DataType dt, bool sendish)
|
||||||
|
|
||||||
IO::~IO ()
|
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 ();
|
BLOCK_PROCESS_CALLBACK ();
|
||||||
Glib::Threads::RWLock::WriterLock wl (_io_lock);
|
|
||||||
|
|
||||||
for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *ports()) {
|
||||||
_session.engine().unregister_port (*i);
|
_session.engine().unregister_port (p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<PortSet>
|
||||||
|
IO::ports () {
|
||||||
|
return std::const_pointer_cast<PortSet> (_ports.reader ());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<PortSet const>
|
||||||
|
IO::ports () const {
|
||||||
|
return _ports.reader ();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IO::connection_change (std::shared_ptr<Port> a, std::shared_ptr<Port> b)
|
IO::connection_change (std::shared_ptr<Port> a, std::shared_ptr<Port> b)
|
||||||
{
|
{
|
||||||
if (_session.deletion_in_progress ()) {
|
if (_session.deletion_in_progress ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* this could be called from within our own ::disconnect() method(s)
|
/* Note:
|
||||||
or from somewhere that operates directly on a port. so, we don't
|
* this could be called from within our own ::disconnect() method(s)
|
||||||
know for sure if we can take this lock or not. if we fail,
|
* or from somewhere that operates directly on a port.
|
||||||
we assume that its safely locked by our own ::disconnect().
|
*/
|
||||||
*/
|
std::shared_ptr<PortSet const> ports = _ports.reader();
|
||||||
|
if (ports->contains (a) || ports->contains (b)) {
|
||||||
Glib::Threads::RWLock::WriterLock wl (_io_lock, Glib::Threads::TRY_LOCK);
|
changed (IOChange (IOChange::ConnectionsChanged), this); /* EMIT SIGNAL */
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,9 +141,9 @@ IO::silence (samplecnt_t nframes)
|
||||||
{
|
{
|
||||||
/* io_lock, not taken: function must be called from Session::process() calltree */
|
/* io_lock, not taken: function must be called from Session::process() calltree */
|
||||||
|
|
||||||
for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *ports ()) {
|
||||||
if (i->port_handle ()) {
|
if (p->port_handle ()) {
|
||||||
i->get_buffer(nframes).silence (nframes);
|
p->get_buffer (nframes).silence (nframes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,24 +155,19 @@ IO::disconnect (std::shared_ptr<Port> our_port, string other_port, void* src)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/* check that our_port is really one of ours */
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
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)) {
|
DEBUG_TRACE (DEBUG::PortConnectIO,
|
||||||
return -1;
|
string_compose("IO::disconnect %1 from %2\n", our_port->name(), other_port));
|
||||||
}
|
|
||||||
|
|
||||||
/* disconnect it from the source */
|
if (our_port->disconnect (other_port)) {
|
||||||
|
error << string_compose(_("IO: cannot disconnect port %1 from %2"), our_port->name(), other_port) << endmsg;
|
||||||
DEBUG_TRACE (DEBUG::PortConnectIO,
|
return -1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
|
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
|
||||||
|
|
@ -191,24 +184,19 @@ IO::connect (std::shared_ptr<Port> our_port, string other_port, void* src)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/* check that our_port is really one of ours */
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
if (!ports()->contains (our_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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
|
||||||
_session.set_dirty ();
|
_session.set_dirty ();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -223,7 +211,7 @@ IO::can_add_port (DataType type) const
|
||||||
case DataType::AUDIO:
|
case DataType::AUDIO:
|
||||||
return true;
|
return true;
|
||||||
case DataType::MIDI:
|
case DataType::MIDI:
|
||||||
return _ports.count ().n_midi() < 1;
|
return ports()->count ().n_midi() < 1;
|
||||||
}
|
}
|
||||||
abort(); /*NOTREACHED*/
|
abort(); /*NOTREACHED*/
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -232,7 +220,7 @@ IO::can_add_port (DataType type) const
|
||||||
int
|
int
|
||||||
IO::remove_port (std::shared_ptr<Port> port, void* src)
|
IO::remove_port (std::shared_ptr<Port> port, void* src)
|
||||||
{
|
{
|
||||||
ChanCount before = _ports.count ();
|
ChanCount before = ports()->count ();
|
||||||
ChanCount after = before;
|
ChanCount after = before;
|
||||||
after.set (port->type(), after.get (port->type()) - 1);
|
after.set (port->type(), after.get (port->type()) - 1);
|
||||||
|
|
||||||
|
|
@ -247,26 +235,28 @@ IO::remove_port (std::shared_ptr<Port> port, void* src)
|
||||||
BLOCK_PROCESS_CALLBACK ();
|
BLOCK_PROCESS_CALLBACK ();
|
||||||
|
|
||||||
{
|
{
|
||||||
Glib::Threads::RWLock::WriterLock wl (_io_lock);
|
RCUWriter<PortSet> writer (_ports);
|
||||||
|
std::shared_ptr<PortSet> p = writer.get_copy ();
|
||||||
|
|
||||||
if (_ports.remove(port)) {
|
if (p->remove (port)) {
|
||||||
change.type = IOChange::Type (change.type | IOChange::ConfigurationChanged);
|
change.type = IOChange::Type (change.type | IOChange::ConfigurationChanged);
|
||||||
change.before = before;
|
change.before = before;
|
||||||
change.after = _ports.count ();
|
change.after = p->count ();
|
||||||
|
|
||||||
if (port->connected()) {
|
if (port->connected()) {
|
||||||
change.type = IOChange::Type (change.type | IOChange::ConnectionsChanged);
|
change.type = IOChange::Type (change.type | IOChange::ConnectionsChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
_session.engine().unregister_port (port);
|
|
||||||
}
|
}
|
||||||
|
_session.engine().unregister_port (port);
|
||||||
}
|
}
|
||||||
|
|
||||||
PortCountChanged (n_ports()); /* EMIT SIGNAL */
|
PortCountChanged (n_ports()); /* EMIT SIGNAL */
|
||||||
|
|
||||||
if (change.type != IOChange::NoChange) {
|
if (change.type != IOChange::NoChange) {
|
||||||
changed (change, src);
|
changed (change, src);
|
||||||
_buffers.attach_buffers (_ports);
|
std::shared_ptr<PortSet const> ports = _ports.reader();
|
||||||
|
_buffers.attach_buffers (*ports);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -302,7 +292,7 @@ IO::add_port (string destination, void* src, DataType type)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChanCount before = _ports.count ();
|
ChanCount before = ports()->count ();
|
||||||
ChanCount after = before;
|
ChanCount after = before;
|
||||||
after.set (type, after.get (type) + 1);
|
after.set (type, after.get (type) + 1);
|
||||||
|
|
||||||
|
|
@ -316,35 +306,35 @@ IO::add_port (string destination, void* src, DataType type)
|
||||||
{
|
{
|
||||||
BLOCK_PROCESS_CALLBACK ();
|
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);
|
RCUWriter<PortSet> writer (_ports);
|
||||||
|
std::shared_ptr<PortSet> p = writer.get_copy ();
|
||||||
/* Create a new port */
|
change.before = p->count ();
|
||||||
|
p->add (our_port);
|
||||||
string portname = build_legal_port_name (type);
|
change.after = p->count ();
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PortCountChanged (n_ports()); /* EMIT SIGNAL */
|
PortCountChanged (n_ports()); /* EMIT SIGNAL */
|
||||||
|
|
||||||
change.type = IOChange::ConfigurationChanged;
|
change.type = IOChange::ConfigurationChanged;
|
||||||
change.after = _ports.count ();
|
|
||||||
changed (change, src); /* EMIT SIGNAL */
|
changed (change, src); /* EMIT SIGNAL */
|
||||||
_buffers.attach_buffers (_ports);
|
_buffers.attach_buffers (*ports());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!destination.empty()) {
|
if (!destination.empty()) {
|
||||||
|
|
@ -363,12 +353,8 @@ IO::add_port (string destination, void* src, DataType type)
|
||||||
int
|
int
|
||||||
IO::disconnect (void* src)
|
IO::disconnect (void* src)
|
||||||
{
|
{
|
||||||
{
|
for (auto const& p : *ports()) {
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
p->disconnect_all ();
|
||||||
|
|
||||||
for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
|
||||||
i->disconnect_all ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
|
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
|
||||||
|
|
@ -385,85 +371,90 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::shared_ptr<Port> port;
|
std::shared_ptr<Port> port;
|
||||||
vector<std::shared_ptr<Port> > deleted_ports;
|
|
||||||
|
|
||||||
changed = false;
|
changed = false;
|
||||||
|
|
||||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
{
|
||||||
|
RCUWriter<PortSet> writer (_ports);
|
||||||
|
std::shared_ptr<PortSet> 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 ();
|
const size_t n = count.get (*t);
|
||||||
/* remove unused ports */
|
|
||||||
for (size_t i = n_ports.get(*t); i > n; --i) {
|
|
||||||
port = _ports.port(*t, i-1);
|
|
||||||
|
|
||||||
assert(port);
|
const ChanCount n_ports = p->count ();
|
||||||
_ports.remove(port);
|
|
||||||
|
|
||||||
/* hold a reference to the port so that we can ensure
|
/* remove unused ports */
|
||||||
* that this thread, and not a JACK notification thread,
|
vector<std::shared_ptr<Port> > deleted_ports;
|
||||||
* holds the final reference.
|
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);
|
/* create any necessary new ports */
|
||||||
_session.engine().unregister_port (port);
|
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,
|
try {
|
||||||
* 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 ();
|
|
||||||
|
|
||||||
/* create any necessary new ports */
|
if (_direction == Input) {
|
||||||
while (_ports.count ().get(*t) < n) {
|
if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
|
||||||
|
error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
|
||||||
string portname = build_legal_port_name (*t);
|
return -1;
|
||||||
|
}
|
||||||
try {
|
} else {
|
||||||
|
if ((port = _session.engine().register_output_port (*t, portname)) == 0) {
|
||||||
if (_direction == Input) {
|
error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
|
||||||
if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
|
return -1;
|
||||||
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) {
|
p->add (port);
|
||||||
/* pass it on */
|
changed = true;
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ports.add (port);
|
|
||||||
changed = true;
|
|
||||||
}
|
}
|
||||||
|
/* end of RCUWriter scope */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
const ChanCount n_ports = _ports.count ();
|
const ChanCount n_ports = ports ()->count ();
|
||||||
PortCountChanged (n_ports); /* EMIT SIGNAL */
|
PortCountChanged (n_ports); /* EMIT SIGNAL */
|
||||||
_session.set_dirty ();
|
_session.set_dirty ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
/* disconnect all existing ports so that we get a fresh start */
|
/* disconnect all existing ports so that we get a fresh start */
|
||||||
for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *ports ()) {
|
||||||
i->disconnect_all ();
|
p->disconnect_all ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -478,28 +469,24 @@ IO::ensure_ports (ChanCount count, bool clear, void* src)
|
||||||
assert (!AudioEngine::instance()->process_lock().trylock());
|
assert (!AudioEngine::instance()->process_lock().trylock());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool changed = false;
|
|
||||||
|
|
||||||
if (count == n_ports() && !clear) {
|
if (count == n_ports() && !clear) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
IOChange change;
|
IOChange change;
|
||||||
|
|
||||||
change.before = _ports.count ();
|
change.before = ports()->count ();
|
||||||
|
|
||||||
{
|
if (ensure_ports_locked (count, clear, changed)) {
|
||||||
Glib::Threads::RWLock::WriterLock wl (_io_lock);
|
return -1;
|
||||||
if (ensure_ports_locked (count, clear, changed)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
change.after = _ports.count ();
|
change.after = ports()->count ();
|
||||||
change.type = IOChange::ConfigurationChanged;
|
change.type = IOChange::ConfigurationChanged;
|
||||||
this->changed (change, src); /* EMIT SIGNAL */
|
this->changed (change, src); /* EMIT SIGNAL */
|
||||||
_buffers.attach_buffers (_ports);
|
_buffers.attach_buffers (*ports());
|
||||||
setup_bundle ();
|
setup_bundle ();
|
||||||
_session.set_dirty ();
|
_session.set_dirty ();
|
||||||
}
|
}
|
||||||
|
|
@ -511,8 +498,8 @@ void
|
||||||
IO::reestablish_port_subscriptions ()
|
IO::reestablish_port_subscriptions ()
|
||||||
{
|
{
|
||||||
_port_connections.drop_connections ();
|
_port_connections.drop_connections ();
|
||||||
for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *ports ()) {
|
||||||
i->ConnectedOrDisconnected.connect_same_thread (*this, boost::bind (&IO::connection_change, this, _1, _2));
|
p->ConnectedOrDisconnected.connect_same_thread (*this, boost::bind (&IO::connection_change, this, _1, _2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -537,7 +524,6 @@ XMLNode&
|
||||||
IO::state () const
|
IO::state () const
|
||||||
{
|
{
|
||||||
XMLNode* node = new XMLNode (state_node_name);
|
XMLNode* node = new XMLNode (state_node_name);
|
||||||
Glib::Threads::RWLock::WriterLock wl (_io_lock);
|
|
||||||
|
|
||||||
node->set_property ("name", name());
|
node->set_property ("name", name());
|
||||||
node->set_property ("id", id ());
|
node->set_property ("id", id ());
|
||||||
|
|
@ -548,8 +534,8 @@ IO::state () const
|
||||||
node->set_property("pretty-name", _pretty_name_prefix);
|
node->set_property("pretty-name", _pretty_name_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *_ports.reader ()) {
|
||||||
node->add_child_nocopy (i->get_state ());
|
node->add_child_nocopy (p->get_state ());
|
||||||
}
|
}
|
||||||
|
|
||||||
return *node;
|
return *node;
|
||||||
|
|
@ -597,9 +583,11 @@ IO::set_state (const XMLNode& node, int version)
|
||||||
* This is needed to properly restore connections when creating
|
* This is needed to properly restore connections when creating
|
||||||
* external sends from templates because the IO name changes.
|
* external sends from templates because the IO name changes.
|
||||||
*/
|
*/
|
||||||
PortSet::iterator i = _ports.begin();
|
std::shared_ptr<PortSet const> ports = _ports.reader ();
|
||||||
XMLNodeConstIterator x = node.children().begin();
|
|
||||||
for (; i != _ports.end() && x != node.children().end(); ++i, ++x) {
|
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") {
|
if ((*x)->name() == "Port") {
|
||||||
(*x)->remove_property (X_("name"));
|
(*x)->remove_property (X_("name"));
|
||||||
(*x)->set_property (X_("name"), i->name());
|
(*x)->set_property (X_("name"), i->name());
|
||||||
|
|
@ -1127,11 +1115,11 @@ IO::set_name (const string& requested_name)
|
||||||
|
|
||||||
name = legalize_io_name (name);
|
name = legalize_io_name (name);
|
||||||
|
|
||||||
for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *ports ()) {
|
||||||
string current_name = i->name();
|
string current_name = p->name();
|
||||||
assert (current_name.find (_name) != std::string::npos);
|
assert (current_name.find (_name) != std::string::npos);
|
||||||
current_name.replace (current_name.find (_name), _name.val().length(), name);
|
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);
|
bool const r = SessionObject::set_name (name);
|
||||||
|
|
@ -1158,11 +1146,11 @@ IO::apply_pretty_name ()
|
||||||
if (_pretty_name_prefix.empty ()) {
|
if (_pretty_name_prefix.empty ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (PortSet::iterator i = _ports.begin (); i != _ports.end(); ++i, ++pn) {
|
for (auto const& p : *ports ()) {
|
||||||
(*i)->set_pretty_name (string_compose (("%1/%2 %3"),
|
p->set_pretty_name (string_compose (("%1/%2 %3"),
|
||||||
_pretty_name_prefix,
|
_pretty_name_prefix,
|
||||||
_direction == Output ? S_("IO|Out") : S_("IO|In"),
|
_direction == Output ? S_("IO|Out") : S_("IO|In"),
|
||||||
pn));
|
pn++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1171,8 +1159,8 @@ IO::set_private_port_latencies (samplecnt_t value, bool playback)
|
||||||
{
|
{
|
||||||
LatencyRange lat;
|
LatencyRange lat;
|
||||||
lat.min = lat.max = value;
|
lat.min = lat.max = value;
|
||||||
for (PortSet::iterator i = _ports.begin (); i != _ports.end(); ++i) {
|
for (auto const& p : *ports ()) {
|
||||||
i->set_private_latency_range (lat, playback);
|
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.min = ~((pframes_t) 0);
|
||||||
lr.max = 0;
|
lr.max = 0;
|
||||||
|
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
std::shared_ptr<PortSet const> ps = ports ();
|
||||||
if (i->connected()) {
|
|
||||||
|
for (auto const& p : *ps) {
|
||||||
|
if (p->connected()) {
|
||||||
connected = true;
|
connected = true;
|
||||||
}
|
}
|
||||||
i->collect_latency_from_backend (lr, playback);
|
p->collect_latency_from_backend (lr, playback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
|
|
@ -1198,8 +1188,8 @@ IO::set_public_port_latency_from_connections () const
|
||||||
lr.min = lr.max = latency ();
|
lr.min = lr.max = latency ();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PortSet::const_iterator i = _ports.begin (); i != _ports.end(); ++i) {
|
for (auto const& p : *ps) {
|
||||||
i->set_public_latency_range (lr, playback);
|
p->set_public_latency_range (lr, playback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1208,8 +1198,8 @@ IO::set_public_port_latencies (samplecnt_t value, bool playback) const
|
||||||
{
|
{
|
||||||
LatencyRange lat;
|
LatencyRange lat;
|
||||||
lat.min = lat.max = value;
|
lat.min = lat.max = value;
|
||||||
for (PortSet::const_iterator i = _ports.begin (); i != _ports.end(); ++i) {
|
for (auto const& p : *_ports.reader ()) {
|
||||||
i->set_public_latency_range (lat, playback);
|
p->set_public_latency_range (lat, playback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1218,11 +1208,9 @@ IO::latency () const
|
||||||
{
|
{
|
||||||
samplecnt_t max_latency = 0;
|
samplecnt_t max_latency = 0;
|
||||||
|
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
for (auto const& p : *_ports.reader ()) {
|
||||||
|
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
|
||||||
samplecnt_t latency;
|
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",
|
DEBUG_TRACE (DEBUG::LatencyIO, string_compose ("port %1 has %2 latency of %3 - use\n",
|
||||||
name(),
|
name(),
|
||||||
((_direction == Output) ? "PLAYBACK" : "CAPTURE"),
|
((_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",
|
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")));
|
((_direction == Output) ? "PLAYBACK" : "CAPTURE")));
|
||||||
return max_latency;
|
return max_latency;
|
||||||
}
|
}
|
||||||
|
|
@ -1274,27 +1262,27 @@ IO::connected_latency (bool for_playback) const
|
||||||
* -> Route::update_signal_latency ()
|
* -> Route::update_signal_latency ()
|
||||||
* -> IO::connected_latency ()
|
* -> IO::connected_latency ()
|
||||||
*/
|
*/
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
std::shared_ptr<PortSet const> ps = ports ();
|
||||||
|
|
||||||
samplecnt_t max_latency = 0;
|
samplecnt_t max_latency = 0;
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
|
|
||||||
/* if output is not connected to anything, use private latency */
|
/* if output is not connected to anything, use private latency */
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *ps) {
|
||||||
if (i->connected()) {
|
if (p->connected()) {
|
||||||
connected = true;
|
connected = true;
|
||||||
max_latency = 0;
|
max_latency = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
samplecnt_t latency;
|
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;
|
max_latency = latency;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (connected) {
|
if (connected) {
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *ps) {
|
||||||
LatencyRange lr;
|
LatencyRange lr;
|
||||||
i->get_connected_latency_range (lr, for_playback);
|
p->get_connected_latency_range (lr, for_playback);
|
||||||
if (lr.max > max_latency) {
|
if (lr.max > max_latency) {
|
||||||
max_latency = lr.max;
|
max_latency = lr.max;
|
||||||
}
|
}
|
||||||
|
|
@ -1314,19 +1302,14 @@ IO::connect_ports_to_bundle (std::shared_ptr<Bundle> c, bool exclusive,
|
||||||
{
|
{
|
||||||
BLOCK_PROCESS_CALLBACK ();
|
BLOCK_PROCESS_CALLBACK ();
|
||||||
|
|
||||||
{
|
if (exclusive) {
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
for (auto const& p : *ports ()) {
|
||||||
|
p->disconnect_all ();
|
||||||
if (exclusive) {
|
|
||||||
for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
|
||||||
i->disconnect_all ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c->connect (_bundle, _session.engine(), allow_partial);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->connect (_bundle, _session.engine(), allow_partial);
|
||||||
|
|
||||||
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
|
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1336,14 +1319,9 @@ IO::disconnect_ports_from_bundle (std::shared_ptr<Bundle> c, void* src)
|
||||||
{
|
{
|
||||||
BLOCK_PROCESS_CALLBACK ();
|
BLOCK_PROCESS_CALLBACK ();
|
||||||
|
|
||||||
{
|
c->disconnect (_bundle, _session.engine());
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
|
||||||
|
|
||||||
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 */
|
changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1416,7 +1394,9 @@ IO::find_port_hole (const char* base)
|
||||||
|
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
|
|
||||||
if (_ports.empty()) {
|
std::shared_ptr<PortSet const> ports = _ports.reader();
|
||||||
|
|
||||||
|
if (ports->empty()) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1425,35 +1405,33 @@ IO::find_port_hole (const char* base)
|
||||||
|
|
||||||
for (n = 1; n < 9999; ++n) {
|
for (n = 1; n < 9999; ++n) {
|
||||||
std::vector<char> buf (AudioEngine::instance()->port_name_size());
|
std::vector<char> 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);
|
snprintf (&buf[0], buf.size()+1, _("%s %u"), base, n);
|
||||||
|
|
||||||
for ( ; i != _ports.end(); ++i) {
|
for ( ; i != ports->end (); ++i) {
|
||||||
if (string(i->name()) == string(&buf[0])) {
|
if (string (i->name()) == string (&buf[0])) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == _ports.end()) {
|
if (i == ports->end()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<AudioPort>
|
std::shared_ptr<AudioPort>
|
||||||
IO::audio(uint32_t n) const
|
IO::audio(uint32_t n) const
|
||||||
{
|
{
|
||||||
return _ports.nth_audio_port (n);
|
return ports()->nth_audio_port (n);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MidiPort>
|
std::shared_ptr<MidiPort>
|
||||||
IO::midi(uint32_t n) const
|
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")));
|
_bundle->set_name (string_compose ("%1 %2", _name, _direction == Input ? _("in") : _("out")));
|
||||||
|
|
||||||
|
std::shared_ptr<PortSet const> ports = _ports.reader();
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
|
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) {
|
for (uint32_t j = 0; j < N; ++j) {
|
||||||
_bundle->add_channel (bundle_channel_name (j, N, *i), *i);
|
_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;
|
++c;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reestablish_port_subscriptions ();
|
reestablish_port_subscriptions ();
|
||||||
|
|
@ -1591,10 +1569,7 @@ IO::set_name_in_state (XMLNode& node, const string& new_name)
|
||||||
bool
|
bool
|
||||||
IO::connected () const
|
IO::connected () const
|
||||||
{
|
{
|
||||||
/* do we have any connections at all? */
|
for (auto const& p : *_ports.reader ()) {
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
|
||||||
|
|
||||||
for (PortSet::const_iterator p = _ports.begin(); p != _ports.end(); ++p) {
|
|
||||||
if (p->connected()) {
|
if (p->connected()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1632,30 +1607,30 @@ IO::connected_to (std::shared_ptr<const IO> other) const
|
||||||
bool
|
bool
|
||||||
IO::connected_to (const string& str) const
|
IO::connected_to (const string& str) const
|
||||||
{
|
{
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
for (auto const& p : *_ports.reader ()) {
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
if (p->connected_to (str)) {
|
||||||
if (i->connected_to (str)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset)
|
IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset)
|
||||||
{
|
{
|
||||||
assert(bufs.available() >= _ports.count());
|
std::shared_ptr<PortSet> ps = ports ();
|
||||||
|
|
||||||
if (_ports.count() == ChanCount::ZERO) {
|
assert (bufs.available() >= ps->count());
|
||||||
|
|
||||||
|
if (ps->count() == ChanCount::ZERO) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufs.set_count (_ports.count());
|
bufs.set_count (ps->count());
|
||||||
|
|
||||||
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
||||||
PortSet::iterator i = _ports.begin(*t);
|
PortSet::iterator i = ps->begin (*t);
|
||||||
BufferSet::iterator b = bufs.begin(*t);
|
BufferSet::iterator b = bufs.begin (*t);
|
||||||
|
|
||||||
for (uint32_t off = 0; off < offset.get(*t); ++off, ++b) {
|
for (uint32_t off = 0; off < offset.get(*t); ++off, ++b) {
|
||||||
if (b == bufs.end(*t)) {
|
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));
|
const Buffer& bb (i->get_buffer (nframes));
|
||||||
b->read_from (bb, nframes);
|
b->read_from (bb, nframes);
|
||||||
}
|
}
|
||||||
|
|
@ -1673,15 +1648,16 @@ IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset)
|
||||||
void
|
void
|
||||||
IO::copy_to_outputs (BufferSet& bufs, DataType type, pframes_t nframes, samplecnt_t offset)
|
IO::copy_to_outputs (BufferSet& bufs, DataType type, pframes_t nframes, samplecnt_t offset)
|
||||||
{
|
{
|
||||||
PortSet::iterator o = _ports.begin(type);
|
std::shared_ptr<PortSet> ps = ports ();
|
||||||
BufferSet::iterator i = bufs.begin(type);
|
|
||||||
|
PortSet::iterator o = ps->begin (type);
|
||||||
|
BufferSet::iterator i = bufs.begin (type);
|
||||||
BufferSet::iterator prev = i;
|
BufferSet::iterator prev = i;
|
||||||
|
|
||||||
assert(i != bufs.end(type)); // or second loop will crash
|
assert(i != bufs.end(type)); // or second loop will crash
|
||||||
|
|
||||||
// Copy any buffers 1:1 to outputs
|
/* Copy any buffers 1:1 to outputs */
|
||||||
|
while (i != bufs.end (type) && o != ps->end (type)) {
|
||||||
while (i != bufs.end(type) && o != _ports.end (type)) {
|
|
||||||
Buffer& port_buffer (o->get_buffer (nframes));
|
Buffer& port_buffer (o->get_buffer (nframes));
|
||||||
port_buffer.read_from (*i, nframes, offset);
|
port_buffer.read_from (*i, nframes, offset);
|
||||||
prev = i;
|
prev = i;
|
||||||
|
|
@ -1689,9 +1665,8 @@ IO::copy_to_outputs (BufferSet& bufs, DataType type, pframes_t nframes, samplecn
|
||||||
++o;
|
++o;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy last buffer to any extra outputs
|
/* Copy last buffer to any extra outputs */
|
||||||
|
while (o != ps->end (type)) {
|
||||||
while (o != _ports.end(type)) {
|
|
||||||
Buffer& port_buffer (o->get_buffer (nframes));
|
Buffer& port_buffer (o->get_buffer (nframes));
|
||||||
port_buffer.read_from (*prev, nframes, offset);
|
port_buffer.read_from (*prev, nframes, offset);
|
||||||
++o;
|
++o;
|
||||||
|
|
@ -1703,7 +1678,7 @@ IO::flush_buffers (pframes_t nframes)
|
||||||
{
|
{
|
||||||
/* when port is both externally and internally connected,
|
/* when port is both externally and internally connected,
|
||||||
* make data available to downstream internal ports */
|
* make data available to downstream internal ports */
|
||||||
for (auto const& p : _ports) {
|
for (auto const& p : *ports ()) {
|
||||||
p->flush_buffers (nframes);
|
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 */
|
/* to be called only from ::set_state() - no locking */
|
||||||
|
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
for (auto const& p : *_ports.reader ()) {
|
||||||
|
if (p->name() == str) {
|
||||||
if (i->name() == str) {
|
return std::const_pointer_cast<Port> (p);
|
||||||
return std::const_pointer_cast<Port> (*i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::shared_ptr<Port> ();
|
return std::shared_ptr<Port> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IO::physically_connected () const
|
IO::physically_connected () const
|
||||||
{
|
{
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
for (auto const& p : *_ports.reader ()) {
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
if (p->physically_connected()) {
|
||||||
if (i->physically_connected()) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1739,28 +1711,25 @@ IO::physically_connected () const
|
||||||
bool
|
bool
|
||||||
IO::has_ext_connection () const
|
IO::has_ext_connection () const
|
||||||
{
|
{
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
for (auto const& p : *_ports.reader ()) {
|
||||||
for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
|
if (p->has_ext_connection()) {
|
||||||
if (i->has_ext_connection()) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IO::has_port (std::shared_ptr<Port> p) const
|
IO::has_port (std::shared_ptr<Port> p) const
|
||||||
{
|
{
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
return ports()->contains (p);
|
||||||
return _ports.contains (p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Port>
|
std::shared_ptr<Port>
|
||||||
IO::nth (uint32_t n) const {
|
IO::nth (uint32_t n) const {
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
std::shared_ptr<PortSet const> ports = _ports.reader ();
|
||||||
if (n < _ports.num_ports()) {
|
if (n < ports->num_ports ()) {
|
||||||
return _ports.port(n);
|
return ports->port (n);
|
||||||
} else {
|
} else {
|
||||||
return std::shared_ptr<Port> ();
|
return std::shared_ptr<Port> ();
|
||||||
}
|
}
|
||||||
|
|
@ -1768,6 +1737,5 @@ IO::nth (uint32_t n) const {
|
||||||
|
|
||||||
const ChanCount&
|
const ChanCount&
|
||||||
IO::n_ports () const {
|
IO::n_ports () const {
|
||||||
Glib::Threads::RWLock::ReaderLock rl (_io_lock);
|
return ports()->count();
|
||||||
return _ports.count();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -271,14 +271,14 @@ IOPlug::set_public_latency (bool playback)
|
||||||
/* Step1: set private port latency
|
/* Step1: set private port latency
|
||||||
* compare to Route::set_private_port_latencies, Route::update_port_latencies
|
* compare to Route::set_private_port_latencies, Route::update_port_latencies
|
||||||
*/
|
*/
|
||||||
PortSet& from = playback ? _output->ports () : _input->ports ();
|
std::shared_ptr<PortSet> from = playback ? _output->ports () : _input->ports ();
|
||||||
PortSet& to = playback ? _input->ports () : _output->ports ();
|
std::shared_ptr<PortSet> to = playback ? _input->ports () : _output->ports ();
|
||||||
|
|
||||||
LatencyRange all_connections;
|
LatencyRange all_connections;
|
||||||
all_connections.min = ~((pframes_t) 0);
|
all_connections.min = ~((pframes_t) 0);
|
||||||
all_connections.max = 0;
|
all_connections.max = 0;
|
||||||
|
|
||||||
for (auto const& p : from) {
|
for (auto const& p : *from) {
|
||||||
if (!p->connected ()) {
|
if (!p->connected ()) {
|
||||||
continue;
|
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 */
|
/* 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);
|
p->set_private_latency_range (all_connections, playback);
|
||||||
}
|
}
|
||||||
|
|
||||||
all_connections.min += _plugin_signal_latency;
|
all_connections.min += _plugin_signal_latency;
|
||||||
all_connections.max += _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);
|
p->set_private_latency_range (all_connections, playback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -475,9 +475,8 @@ MidiTrack::non_realtime_locate (samplepos_t spos)
|
||||||
void
|
void
|
||||||
MidiTrack::push_midi_input_to_step_edit_ringbuffer (samplecnt_t nframes)
|
MidiTrack::push_midi_input_to_step_edit_ringbuffer (samplecnt_t nframes)
|
||||||
{
|
{
|
||||||
PortSet& ports (_input->ports());
|
std::shared_ptr<PortSet> ports (_input->ports());
|
||||||
|
for (PortSet::iterator p = ports->begin (DataType::MIDI); p != ports->end (DataType::MIDI); ++p) {
|
||||||
for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
|
|
||||||
|
|
||||||
Buffer& b (p->get_buffer (nframes));
|
Buffer& b (p->get_buffer (nframes));
|
||||||
const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
|
const MidiBuffer* const mb = dynamic_cast<MidiBuffer*>(&b);
|
||||||
|
|
@ -874,9 +873,8 @@ MidiTrack::map_input_active (bool yn)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PortSet& ports (_input->ports());
|
std::shared_ptr<PortSet> ports (_input->ports());
|
||||||
|
for (PortSet::iterator p = ports->begin (DataType::MIDI); p != ports->end (DataType::MIDI); ++p) {
|
||||||
for (PortSet::iterator p = ports.begin(DataType::MIDI); p != ports.end(DataType::MIDI); ++p) {
|
|
||||||
std::shared_ptr<MidiPort> mp = std::dynamic_pointer_cast<MidiPort> (*p);
|
std::shared_ptr<MidiPort> mp = std::dynamic_pointer_cast<MidiPort> (*p);
|
||||||
if (yn != mp->input_active()) {
|
if (yn != mp->input_active()) {
|
||||||
mp->set_input_active (yn);
|
mp->set_input_active (yn);
|
||||||
|
|
@ -947,10 +945,8 @@ MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition
|
||||||
* port level.
|
* port level.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PortSet& ports (_output->ports());
|
for (auto const& p : *_output->ports()) {
|
||||||
|
std::shared_ptr<MidiPort> mp = std::dynamic_pointer_cast<MidiPort> (p);
|
||||||
for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
|
|
||||||
std::shared_ptr<MidiPort> mp = std::dynamic_pointer_cast<MidiPort> (*p);
|
|
||||||
if (mp) {
|
if (mp) {
|
||||||
mp->require_resolve ();
|
mp->require_resolve ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,8 +147,8 @@ PortInsert::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
||||||
|
|
||||||
if (_input->n_ports().n_audio() != 0) {
|
if (_input->n_ports().n_audio() != 0) {
|
||||||
|
|
||||||
AudioBuffer& outbuf (_output->ports().nth_audio_port(0)->get_audio_buffer (nframes));
|
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* in = _input->ports()->nth_audio_port(0)->get_audio_buffer (nframes).data();
|
||||||
Sample* out = outbuf.data();
|
Sample* out = outbuf.data();
|
||||||
|
|
||||||
_mtdm->process (nframes, in, out);
|
_mtdm->process (nframes, in, out);
|
||||||
|
|
|
||||||
|
|
@ -5180,10 +5180,10 @@ Route::set_private_port_latencies (bool playback) const
|
||||||
|
|
||||||
if (playback) {
|
if (playback) {
|
||||||
/* playback: propagate latency from "outside the route" to outputs to inputs */
|
/* 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 {
|
} else {
|
||||||
/* capture: propagate latency from "outside the route" to inputs to outputs */
|
/* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1179,8 +1179,8 @@ Session::add_monitor_section ()
|
||||||
_master_out->output()->disconnect (this);
|
_master_out->output()->disconnect (this);
|
||||||
|
|
||||||
for (uint32_t n = 0; n < limit; ++n) {
|
for (uint32_t n = 0; n < limit; ++n) {
|
||||||
std::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
|
std::shared_ptr<AudioPort> p = _monitor_out->input()->ports()->nth_audio_port (n);
|
||||||
std::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
|
std::shared_ptr<AudioPort> o = _master_out->output()->ports()->nth_audio_port (n);
|
||||||
|
|
||||||
if (o) {
|
if (o) {
|
||||||
string connect_to = o->name();
|
string connect_to = o->name();
|
||||||
|
|
@ -1246,7 +1246,7 @@ Session::auto_connect_monitor_bus ()
|
||||||
|
|
||||||
for (uint32_t n = 0; n < limit; ++n) {
|
for (uint32_t n = 0; n < limit; ++n) {
|
||||||
|
|
||||||
std::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
|
std::shared_ptr<Port> p = _monitor_out->output()->ports()->port(DataType::AUDIO, n);
|
||||||
string connect_to;
|
string connect_to;
|
||||||
if (outputs[DataType::AUDIO].size() > (n % mod)) {
|
if (outputs[DataType::AUDIO].size() > (n % mod)) {
|
||||||
connect_to = outputs[DataType::AUDIO][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);
|
_monitor_out->output()->ensure_io (mon_chn, false, this);
|
||||||
|
|
||||||
for (uint32_t n = 0; n < limit; ++n) {
|
for (uint32_t n = 0; n < limit; ++n) {
|
||||||
std::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
|
std::shared_ptr<AudioPort> p = _monitor_out->input()->ports()->nth_audio_port (n);
|
||||||
std::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
|
std::shared_ptr<AudioPort> o = _master_out->output()->ports()->nth_audio_port (n);
|
||||||
|
|
||||||
if (o) {
|
if (o) {
|
||||||
string connect_to = o->name();
|
string connect_to = o->name();
|
||||||
|
|
@ -1372,7 +1372,7 @@ Session::reset_monitor_section ()
|
||||||
|
|
||||||
for (uint32_t n = 0; n < limit; ++n) {
|
for (uint32_t n = 0; n < limit; ++n) {
|
||||||
|
|
||||||
std::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
|
std::shared_ptr<Port> p = _monitor_out->output()->ports()->port(DataType::AUDIO, n);
|
||||||
string connect_to;
|
string connect_to;
|
||||||
if (outputs[DataType::AUDIO].size() > (n % mod)) {
|
if (outputs[DataType::AUDIO].size() > (n % mod)) {
|
||||||
connect_to = outputs[DataType::AUDIO][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) {
|
if (!io) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (auto const& p : io->ports()) {
|
for (auto const& p : *io->ports()) {
|
||||||
p->reconnect ();
|
p->reconnect ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3456,7 +3456,7 @@ Session::new_route_from_template (uint32_t how_many, PresentationInfo::order_t i
|
||||||
if (!io) {
|
if (!io) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (auto const& p : io->ports()) {
|
for (auto const& p : *io->ports()) {
|
||||||
p->reconnect ();
|
p->reconnect ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4388,9 +4388,7 @@ Session::set_exclusive_input_active (std::shared_ptr<RouteList> rl, bool onoff,
|
||||||
|
|
||||||
for (RouteList::iterator rt = rl->begin(); rt != rl->end(); ++rt) {
|
for (RouteList::iterator rt = rl->begin(); rt != rl->end(); ++rt) {
|
||||||
|
|
||||||
PortSet& ps ((*rt)->input()->ports());
|
for (auto const& p : *(*rt)->input()->ports()) {
|
||||||
|
|
||||||
for (PortSet::iterator p = ps.begin(); p != ps.end(); ++p) {
|
|
||||||
p->get_connections (connections);
|
p->get_connections (connections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7791,7 +7789,7 @@ Session::auto_connect (const AutoConnectRequest& ar)
|
||||||
port = physinputs[(in_offset.get(*t) + i) % nphysical_in];
|
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.");
|
DEBUG_TRACE (DEBUG::PortConnectAuto, "Failed to auto-connect input.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -7812,12 +7810,12 @@ Session::auto_connect (const AutoConnectRequest& ar)
|
||||||
} else if ((*t) == DataType::AUDIO && (Config->get_output_auto_connect() & AutoConnectMaster)) {
|
} else if ((*t) == DataType::AUDIO && (Config->get_output_auto_connect() & AutoConnectMaster)) {
|
||||||
/* master bus is audio only */
|
/* master bus is audio only */
|
||||||
if (_master_out && _master_out->n_inputs().get(*t) > 0) {
|
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();
|
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.");
|
DEBUG_TRACE (DEBUG::PortConnectAuto, "Failed to auto-connect output.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,11 +314,12 @@ bool
|
||||||
Track::can_record()
|
Track::can_record()
|
||||||
{
|
{
|
||||||
bool will_record = true;
|
bool will_record = true;
|
||||||
for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end() && will_record; ++i) {
|
for (auto const& p : *_input->ports()) {
|
||||||
if (!i->connected())
|
if (!p->connected()) {
|
||||||
will_record = false;
|
will_record = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return will_record;
|
return will_record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,16 +514,16 @@ Track::playlist ()
|
||||||
void
|
void
|
||||||
Track::request_input_monitoring (bool m)
|
Track::request_input_monitoring (bool m)
|
||||||
{
|
{
|
||||||
for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) {
|
for (auto const& p : *_input->ports()) {
|
||||||
AudioEngine::instance()->request_input_monitoring ((*i)->name(), m);
|
AudioEngine::instance()->request_input_monitoring (p->name(), m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Track::ensure_input_monitoring (bool m)
|
Track::ensure_input_monitoring (bool m)
|
||||||
{
|
{
|
||||||
for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) {
|
for (auto const& p : *_input->ports()) {
|
||||||
AudioEngine::instance()->ensure_input_monitoring ((*i)->name(), m);
|
AudioEngine::instance()->ensure_input_monitoring (p->name(), m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6402,16 +6402,16 @@ OSC::cue_new_aux (string name, string dest_1, string dest_2, uint32_t count, lo_
|
||||||
if (aux) {
|
if (aux) {
|
||||||
std::shared_ptr<Route> r = std::dynamic_pointer_cast<Route>(aux);
|
std::shared_ptr<Route> r = std::dynamic_pointer_cast<Route>(aux);
|
||||||
if (dest_1.size()) {
|
if (dest_1.size()) {
|
||||||
PortSet& ports = r->output()->ports ();
|
std::shared_ptr<PortSet> ports = r->output()->ports ();
|
||||||
if (atoi( dest_1.c_str())) {
|
if (atoi( dest_1.c_str())) {
|
||||||
dest_1 = string_compose ("system:playback_%1", dest_1);
|
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 (count == 2) {
|
||||||
if (atoi( dest_2.c_str())) {
|
if (atoi( dest_2.c_str())) {
|
||||||
dest_2 = string_compose ("system:playback_%1", dest_2);
|
dest_2 = string_compose ("system:playback_%1", dest_2);
|
||||||
}
|
}
|
||||||
PortSet::iterator i = ports.begin();
|
PortSet::iterator i = ports->begin();
|
||||||
++i;
|
++i;
|
||||||
r->output ()->connect (*(i), dest_2, this);
|
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())) {
|
if (atoi( dest.c_str())) {
|
||||||
dest = string_compose ("system:playback_%1", dest);
|
dest = string_compose ("system:playback_%1", dest);
|
||||||
}
|
}
|
||||||
PortSet& ports = rt->output()->ports ();
|
std::shared_ptr<PortSet> ports = rt->output()->ports ();
|
||||||
rt->output ()->connect (*(ports.begin()), dest, this);
|
rt->output ()->connect (*(ports->begin()), dest, this);
|
||||||
session->set_dirty();
|
session->set_dirty();
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue