X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fio.cc;h=d6b5b1e7db3d5afea189c18d7bbe693582067140;hb=ad547e53fc168410b22628a8cb125e8d4da4b293;hp=a56f81781483951c8ef64c39c97c3f7adf7f3585;hpb=bc56eb8bd73c7b456b646ba0cc627d449baa37f2;p=ardour.git diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index a56f817814..d6b5b1e7db 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -18,12 +18,12 @@ #include #include +#include + #include #include #include -#include - #include #include @@ -41,7 +41,6 @@ #include "ardour/midi_port.h" #include "ardour/session.h" #include "ardour/cycle_timer.h" -#include "ardour/panner.h" #include "ardour/buffer_set.h" #include "ardour/meter.h" #include "ardour/amp.h" @@ -49,19 +48,7 @@ #include "i18n.h" -#include - -/* - A bug in OS X's cmath that causes isnan() and isinf() to be - "undeclared". the following works around that -*/ - -#if defined(__APPLE__) && defined(__MACH__) -extern "C" int isnan (double); -extern "C" int isinf (double); -#endif - -#define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (_session.engine().process_lock()) +#define BLOCK_PROCESS_CALLBACK() Glib::Mutex::Lock em (AudioEngine::instance()->process_lock()) using namespace std; using namespace ARDOUR; @@ -69,8 +56,8 @@ using namespace PBD; const string IO::state_node_name = "IO"; bool IO::connecting_legal = false; -sigc::signal IO::ConnectingLegal; -sigc::signal IO::PortCountChanged; +PBD::Signal0 IO::ConnectingLegal; +PBD::Signal1 IO::PortCountChanged; /** @param default_type The type of port that will be created by ensure_io * and friends if no type is explicitly requested (to avoid breakage). @@ -82,7 +69,7 @@ IO::IO (Session& s, const string& name, Direction dir, DataType default_type) { _active = true; pending_state_node = 0; - setup_bundles (); + setup_bundle (); } IO::IO (Session& s, const XMLNode& node, DataType dt) @@ -94,7 +81,7 @@ IO::IO (Session& s, const XMLNode& node, DataType dt) pending_state_node = 0; set_state (node, Stateful::loading_state_version); - setup_bundles (); + setup_bundle (); } IO::~IO () @@ -124,16 +111,20 @@ IO::check_bundles_connected () check_bundles (_bundles_connected, ports()); } +/** Check the bundles in list to see which are connected to a given PortSet, + * and update list with those that are connected such that every port on every + * bundle channel x is connected to port x in ports. + */ void -IO::check_bundles (std::vector& list, const PortSet& ports) +IO::check_bundles (std::vector& list, const PortSet& ports) { - std::vector new_list; + std::vector new_list; - for (std::vector::iterator i = list.begin(); i != list.end(); ++i) { + for (std::vector::iterator i = list.begin(); i != list.end(); ++i) { - uint32_t const N = i->bundle->nchannels (); + uint32_t const N = (*i)->bundle->nchannels().n_total(); - if (_ports.num_ports (default_type()) < N) { + if (_ports.num_ports() < N) { continue; } @@ -141,7 +132,7 @@ IO::check_bundles (std::vector& list, const PortSet& ports) for (uint32_t j = 0; j < N; ++j) { /* Every port on bundle channel j must be connected to our input j */ - Bundle::PortList const pl = i->bundle->channel_ports (j); + Bundle::PortList const pl = (*i)->bundle->channel_ports (j); for (uint32_t k = 0; k < pl.size(); ++k) { if (ports.port(j)->connected_to (pl[k]) == false) { ok = false; @@ -157,7 +148,7 @@ IO::check_bundles (std::vector& list, const PortSet& ports) if (ok) { new_list.push_back (*i); } else { - i->changed.disconnect (); + delete *i; } } @@ -195,7 +186,7 @@ IO::disconnect (Port* our_port, string other_port, void* src) } } - changed (ConnectionsChanged, src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ _session.set_dirty (); return 0; @@ -228,7 +219,7 @@ IO::connect (Port* our_port, string other_port, void* src) } } - changed (ConnectionsChanged, src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ _session.set_dirty (); return 0; } @@ -236,20 +227,23 @@ IO::connect (Port* our_port, string other_port, void* src) int IO::remove_port (Port* port, void* src) { - IOChange change (NoChange); + IOChange change; { BLOCK_PROCESS_CALLBACK (); - { Glib::Mutex::Lock lm (io_lock); + ChanCount before = _ports.count (); + if (_ports.remove(port)) { - change = IOChange (change|ConfigurationChanged); + change.type = IOChange::Type (change.type | IOChange::ConfigurationChanged); + change.before = before; + change.after = _ports.count (); if (port->connected()) { - change = IOChange (change|ConnectionsChanged); + change.type = IOChange::Type (change.type | IOChange::ConnectionsChanged); } _session.engine().unregister_port (*port); @@ -260,11 +254,11 @@ IO::remove_port (Port* port, void* src) PortCountChanged (n_ports()); /* EMIT SIGNAL */ } - if (change & ConfigurationChanged) { - setup_bundles (); + if (change.type & IOChange::ConfigurationChanged) { + setup_bundle (); } - if (change != NoChange) { + if (change.type != IOChange::NoChange) { changed (change, src); _session.set_dirty (); return 0; @@ -288,6 +282,8 @@ IO::add_port (string destination, void* src, DataType type) type = _default_type; } + IOChange change; + { BLOCK_PROCESS_CALLBACK (); @@ -311,6 +307,7 @@ IO::add_port (string destination, void* src, DataType type) } } + change.before = _ports.count (); _ports.add (our_port); } @@ -324,8 +321,10 @@ IO::add_port (string destination, void* src, DataType type) } // pan_changed (src); /* EMIT SIGNAL */ - changed (ConfigurationChanged, src); /* EMIT SIGNAL */ - setup_bundles (); + change.type = IOChange::ConfigurationChanged; + change.after = _ports.count (); + changed (change, src); /* EMIT SIGNAL */ + setup_bundle (); _session.set_dirty (); return 0; @@ -348,7 +347,7 @@ IO::disconnect (void* src) } } - changed (ConnectionsChanged, src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ return 0; } @@ -396,7 +395,7 @@ IO::ensure_ports_locked (ChanCount count, bool clear, void* /*src*/) catch (AudioEngine::PortRegistrationFailure& err) { /* pass it on */ - throw AudioEngine::PortRegistrationFailure(); + throw; } _ports.add (port); @@ -430,6 +429,10 @@ IO::ensure_ports (ChanCount count, bool clear, bool lockit, void* src) return 0; } + IOChange change; + + change.before = _ports.count (); + if (lockit) { BLOCK_PROCESS_CALLBACK (); Glib::Mutex::Lock im (io_lock); @@ -439,8 +442,10 @@ IO::ensure_ports (ChanCount count, bool clear, bool lockit, void* src) } if (changed) { - this->changed (ConfigurationChanged, src); /* EMIT SIGNAL */ - setup_bundles (); + change.after = _ports.count (); + change.type = IOChange::ConfigurationChanged; + this->changed (change, src); /* EMIT SIGNAL */ + setup_bundle (); _session.set_dirty (); } @@ -476,9 +481,9 @@ IO::state (bool /*full_state*/) node->add_property ("direction", enum_2_string (_direction)); node->add_property ("default-type", _default_type.to_string()); - for (std::vector::iterator i = _bundles_connected.begin(); i != _bundles_connected.end(); ++i) { + for (std::vector::iterator i = _bundles_connected.begin(); i != _bundles_connected.end(); ++i) { XMLNode* n = new XMLNode ("Bundle"); - n->add_property ("name", i->bundle->name ()); + n->add_property ("name", (*i)->bundle->name ()); node->add_child_nocopy (*n); } @@ -568,7 +573,7 @@ IO::set_state (const XMLNode& node, int version) pending_state_node = new XMLNode (node); pending_state_node_version = version; pending_state_node_in = false; - connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal)); + ConnectingLegal.connect_same_thread (connection_legal_c, boost::bind (&IO::connecting_became_legal, this)); } @@ -621,7 +626,7 @@ IO::set_state_2X (const XMLNode& node, int version, bool in) pending_state_node = new XMLNode (node); pending_state_node_version = version; pending_state_node_in = in; - connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal)); + ConnectingLegal.connect_same_thread (connection_legal_c, boost::bind (&IO::connecting_became_legal, this)); } return 0; @@ -676,12 +681,12 @@ IO::find_possible_bundle (const string &desired_name) // see if it's a stereo connection e.g. "in 3+4" if (last_non_digit_pos > 1 && desired_name[last_non_digit_pos] == '+') { - int left_bundle_number = 0; string::size_type left_last_non_digit_pos; left_last_non_digit_pos = desired_name.find_last_not_of(digits, last_non_digit_pos-1); if (left_last_non_digit_pos != string::npos) { + int left_bundle_number = 0; stringstream s; s << desired_name.substr(left_last_non_digit_pos, last_non_digit_pos-1); s >> left_bundle_number; @@ -750,8 +755,12 @@ IO::get_port_counts_2X (XMLNode const & node, int /*version*/, ChanCount& n, boo if ((prop = node.property ("inputs")) != 0 && _direction == Input) { n_audio = count (prop->value().begin(), prop->value().end(), '{'); + } else if ((prop = node.property ("input-connection")) != 0 && _direction == Input) { + n_audio = 1; } else if ((prop = node.property ("outputs")) != 0 && _direction == Output) { n_audio = count (prop->value().begin(), prop->value().end(), '{'); + } else if ((prop = node.property ("output-connection")) != 0 && _direction == Output) { + n_audio = 2; } } @@ -780,7 +789,7 @@ IO::get_port_counts (const XMLNode& node, int version, ChanCount& n, boost::shar if ((prop = node.property ("connection")) != 0) { if ((c = find_possible_bundle (prop->value())) != 0) { - n = ChanCount::max (n, ChanCount(c->type(), c->nchannels())); + n = ChanCount::max (n, c->nchannels()); } return 0; } @@ -789,7 +798,7 @@ IO::get_port_counts (const XMLNode& node, int version, ChanCount& n, boost::shar if ((*iter)->name() == X_("Bundle")) { if ((c = find_possible_bundle (prop->value())) != 0) { - n = ChanCount::max (n, ChanCount(c->type(), c->nchannels())); + n = ChanCount::max (n, c->nchannels()); return 0; } else { return -1; @@ -878,12 +887,12 @@ IO::make_connections (const XMLNode& node, int version, bool in) if ((prop = cnode->property (X_("other"))) == 0) { continue; } - + if (prop) { p->connect (prop->value()); } } - } + } } } @@ -1088,25 +1097,23 @@ IO::set_name (const string& requested_name) { string name = requested_name; - if (name == _name) { + if (_name == name) { return true; } /* replace all colons in the name. i wish we didn't have to do this */ - if (replace_all (name, ":", "-")) { - warning << _("you cannot use colons to name objects with I/O connections") << endmsg; - } + replace_all (name, ":", "-"); for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) { string current_name = i->name(); - current_name.replace (current_name.find (_name), _name.length(), name); + current_name.replace (current_name.find (_name), _name.val().length(), name); i->set_name (current_name); } bool const r = SessionObject::set_name (name); - setup_bundles (); + setup_bundle (); return r; } @@ -1165,19 +1172,19 @@ IO::connect_ports_to_bundle (boost::shared_ptr c, void* src) if (ub) { /* See if we already know about this one */ - std::vector::iterator i = _bundles_connected.begin(); - while (i != _bundles_connected.end() && i->bundle != ub) { + std::vector::iterator i = _bundles_connected.begin(); + while (i != _bundles_connected.end() && (*i)->bundle != ub) { ++i; } if (i == _bundles_connected.end()) { /* We don't, so make a note */ - _bundles_connected.push_back (UserBundleInfo (this, ub)); + _bundles_connected.push_back (new UserBundleInfo (this, ub)); } } } - changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ return 0; } @@ -1195,18 +1202,19 @@ IO::disconnect_ports_from_bundle (boost::shared_ptr c, void* src) boost::shared_ptr ub = boost::dynamic_pointer_cast (c); if (ub) { - std::vector::iterator i = _bundles_connected.begin(); - while (i != _bundles_connected.end() && i->bundle != ub) { + std::vector::iterator i = _bundles_connected.begin(); + while (i != _bundles_connected.end() && (*i)->bundle != ub) { ++i; } if (i != _bundles_connected.end()) { + delete *i; _bundles_connected.erase (i); } } } - changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */ + changed (IOChange (IOChange::ConnectionsChanged), src); /* EMIT SIGNAL */ return 0; } @@ -1222,7 +1230,8 @@ int IO::enable_connecting () { connecting_legal = true; - return ConnectingLegal (); + boost::optional r = ConnectingLegal (); + return r.get_value_or (0); } void @@ -1267,7 +1276,7 @@ IO::build_legal_port_name (DataType type) char buf1[name_size+1]; char buf2[name_size+1]; - snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str()); + snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.val().c_str(), suffix.c_str()); int port_number = find_port_hole (buf1); snprintf (buf2, name_size+1, "%s %d", buf1, port_number); @@ -1323,11 +1332,11 @@ IO::midi(uint32_t n) const } /** - * Setup bundles that describe our inputs and outputs. Also creates bundles if necessary. + * Setup a bundle that describe our inputs or outputs. Also creates the bundle if necessary. */ void -IO::setup_bundles () +IO::setup_bundle () { char buf[32]; @@ -1337,20 +1346,25 @@ IO::setup_bundles () _bundle->suspend_signals (); - _bundle->set_type (default_type ()); - _bundle->remove_channels (); if (_direction == Input) { - snprintf(buf, sizeof (buf), _("%s in"), _name.c_str()); + snprintf(buf, sizeof (buf), _("%s in"), _name.val().c_str()); } else { - snprintf(buf, sizeof (buf), _("%s out"), _name.c_str()); + snprintf(buf, sizeof (buf), _("%s out"), _name.val().c_str()); } _bundle->set_name (buf); - uint32_t const ni = _ports.num_ports(); - for (uint32_t i = 0; i < ni; ++i) { - _bundle->add_channel (bundle_channel_name (i, ni)); - _bundle->set_port (i, _session.engine().make_port_name_non_relative (_ports.port(i)->name())); + + int c = 0; + for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++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())); + ++c; + } + } _bundle->resume_signals (); @@ -1363,8 +1377,8 @@ IO::bundles_connected () BundleList bundles; /* User bundles */ - for (std::vector::iterator i = _bundles_connected.begin(); i != _bundles_connected.end(); ++i) { - bundles.push_back (i->bundle); + for (std::vector::iterator i = _bundles_connected.begin(); i != _bundles_connected.end(); ++i) { + bundles.push_back ((*i)->bundle); } /* Session bundles */ @@ -1400,24 +1414,31 @@ IO::bundles_connected () IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr b) { bundle = b; - changed = b->Changed.connect ( - sigc::mem_fun (*io, &IO::bundle_changed) - ); + b->Changed.connect_same_thread (changed, boost::bind (&IO::bundle_changed, io, _1)); } std::string -IO::bundle_channel_name (uint32_t c, uint32_t n) const +IO::bundle_channel_name (uint32_t c, uint32_t n, DataType t) const { char buf[32]; - switch (n) { - case 1: - return _("mono"); - case 2: - return c == 0 ? _("L") : _("R"); - default: + if (t == DataType::AUDIO) { + + switch (n) { + case 1: + return _("mono"); + case 2: + return c == 0 ? _("L") : _("R"); + default: + snprintf (buf, sizeof(buf), _("%d"), (c + 1)); + return buf; + } + + } else { + snprintf (buf, sizeof(buf), _("%d"), (c + 1)); return buf; + } return ""; @@ -1445,19 +1466,25 @@ IO::set_name_in_state (XMLNode& node, const string& new_name) } } +bool +IO::connected () const +{ + /* do we have any connections at all? */ + + for (PortSet::const_iterator p = _ports.begin(); p != _ports.end(); ++p) { + if (p->connected()) { + return true; + } + } + + return false; +} + bool IO::connected_to (boost::shared_ptr other) const { if (!other) { - /* do we have any connections at all? */ - - for (PortSet::const_iterator p = _ports.begin(); p != _ports.end(); ++p) { - if (p->connected()) { - return true; - } - } - - return false; + return connected (); } assert (_direction != other->direction()); @@ -1485,7 +1512,7 @@ IO::process_input (boost::shared_ptr proc, sframes_t start_frame, sfr /* don't read the data into new buffers - just use the port buffers directly */ bufs.attach_buffers (_ports, nframes, 0); - proc->run (bufs, start_frame, end_frame, nframes); + proc->run (bufs, start_frame, end_frame, nframes, true); } void @@ -1558,3 +1585,15 @@ IO::port_by_name (const std::string& str) const return 0; } + +bool +IO::physically_connected () const +{ + for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { + if (i->physically_connected()) { + return true; + } + } + + return false; +}