X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fardour%2Fport.cc;h=06169dd576634441afc378027c5df063ece1bd9f;hb=dac57703ccd7205ac94c14b407b802a69f4187f1;hp=fea2a041e0693c100bbd3b124cc2823936bef00d;hpb=20b1a7d9d8800f8fdca8379cba01cc39757c34fc;p=ardour.git diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index fea2a041e0..06169dd576 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -21,8 +21,6 @@ #include "libardour-config.h" #endif -#include // so that we can test for new functions at runtime - #include "pbd/compose.h" #include "pbd/error.h" #include "pbd/failed_constructor.h" @@ -44,11 +42,13 @@ PBD::Signal0 Port::PortDrop; bool Port::_connecting_blocked = false; pframes_t Port::_global_port_buffer_offset = 0; pframes_t Port::_cycle_nframes = 0; +std::string Port::state_node_name = X_("Port"); /* a handy define to shorten what would otherwise be a needlessly verbose * repeated phrase */ #define port_engine AudioEngine::instance()->port_engine() +#define port_manager AudioEngine::instance() /** @param n Port short name */ Port::Port (std::string const & n, DataType t, PortFlags f) @@ -69,15 +69,11 @@ Port::Port (std::string const & n, DataType t, PortFlags f) assert (_name.find_first_of (':') == std::string::npos); - if (!port_engine.connected()) { - throw failed_constructor (); - } - if ((_port_handle = port_engine.register_port (_name, t, _flags)) == 0) { cerr << "Failed to register port \"" << _name << "\", reason is unknown from here\n"; throw failed_constructor (); } - + PortDrop.connect_same_thread (drop_connection, boost::bind (&Port::drop, this)); } @@ -87,10 +83,31 @@ Port::~Port () drop (); } + +std::string +Port::pretty_name(bool fallback_to_name) const +{ + if (_port_handle) { + std::string value; + std::string type; + if (0 == port_engine.get_port_property (_port_handle, + "http://jackaudio.org/metadata/pretty-name", + value, type)) + { + return value; + } + } + if (fallback_to_name) { + return name (); + } + return ""; +} + void Port::drop () { if (_port_handle) { + DEBUG_TRACE (DEBUG::Ports, string_compose ("drop handle for port %1\n", name())); port_engine.unregister_port (_port_handle); _port_handle = 0; } @@ -100,19 +117,33 @@ Port::drop () bool Port::connected () const { - return (port_engine.connected (_port_handle) != 0); + if (_port_handle) { + return (port_engine.connected (_port_handle) != 0); + } + return false; } int Port::disconnect_all () { - port_engine.disconnect_all (_port_handle); - _connections.clear (); + if (_port_handle) { - /* a cheaper, less hacky way to do boost::shared_from_this() ... - */ - boost::shared_ptr pself = AudioEngine::instance()->get_port_by_name (name()); - PostDisconnect (pself, boost::shared_ptr()); // emit signal + std::vector connections; + get_connections (connections); + + port_engine.disconnect_all (_port_handle); + _connections.clear (); + + /* a cheaper, less hacky way to do boost::shared_from_this() ... + */ + boost::shared_ptr pself = port_manager->get_port_by_name (name()); + for (vector::const_iterator c = connections.begin(); c != connections.end() && pself; ++c) { + boost::shared_ptr pother = AudioEngine::instance()->get_port_by_name (*c); + if (pother) { + PostDisconnect (pself, pother); // emit signal + } + } + } return 0; } @@ -123,28 +154,37 @@ Port::disconnect_all () bool Port::connected_to (std::string const & o) const { - if (!port_engine.connected()) { - /* in some senses, this answer isn't the right one all the time, - because we know about our connections and will re-establish - them when we reconnect to the port engine. - */ + if (!_port_handle) { + return false; + } + + if (!port_engine.available()) { return false; } - return port_engine.connected_to (_port_handle, port_engine.make_port_name_non_relative (o)); + return port_engine.connected_to (_port_handle, AudioEngine::instance()->make_port_name_non_relative (o)); } int Port::get_connections (std::vector & c) const { - return port_engine.get_connections (_port_handle, c); + if (!port_engine.available()) { + c.insert (c.end(), _connections.begin(), _connections.end()); + return c.size(); + } + + if (_port_handle) { + return port_engine.get_connections (_port_handle, c); + } + + return 0; } int Port::connect (std::string const & other) { - std::string const other_name = port_engine.make_port_name_non_relative (other); - std::string const our_name = port_engine.make_port_name_non_relative (_name); + std::string const other_name = AudioEngine::instance()->make_port_name_non_relative (other); + std::string const our_name = AudioEngine::instance()->make_port_name_non_relative (_name); int r = 0; @@ -153,9 +193,11 @@ Port::connect (std::string const & other) } if (sends_output ()) { - port_engine.connect (our_name, other_name); + DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2\n", our_name, other_name)); + r = port_engine.connect (our_name, other_name); } else { - port_engine.connect (other_name, our_name); + DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2\n", other_name, our_name)); + r = port_engine.connect (other_name, our_name); } if (r == 0) { @@ -168,8 +210,8 @@ Port::connect (std::string const & other) int Port::disconnect (std::string const & other) { - std::string const other_fullname = port_engine.make_port_name_non_relative (other); - std::string const this_fullname = port_engine.make_port_name_non_relative (_name); + std::string const other_fullname = port_manager->make_port_name_non_relative (other); + std::string const this_fullname = port_manager->make_port_name_non_relative (_name); int r = 0; @@ -183,7 +225,7 @@ Port::disconnect (std::string const & other) _connections.erase (other); } - /* a cheaper, less hacky way to do boost::shared_from_this() ... + /* a cheaper, less hacky way to do boost::shared_from_this() ... */ boost::shared_ptr pself = AudioEngine::instance()->get_port_by_name (name()); boost::shared_ptr pother = AudioEngine::instance()->get_port_by_name (other); @@ -193,7 +235,7 @@ Port::disconnect (std::string const & other) a check on whether this may affect anything that we need to know about. */ - PostDisconnect (pself, pother); // emit signal + PostDisconnect (pself, pother); // emit signal } return r; @@ -221,20 +263,26 @@ Port::disconnect (Port* o) void Port::request_input_monitoring (bool yn) { - port_engine.request_input_monitoring (_port_handle, yn); + if (_port_handle) { + port_engine.request_input_monitoring (_port_handle, yn); + } } void Port::ensure_input_monitoring (bool yn) { - port_engine.ensure_input_monitoring (_port_handle, yn); + if (_port_handle) { + port_engine.ensure_input_monitoring (_port_handle, yn); + } } bool Port::monitoring_input () const { - - return port_engine.monitoring_input (_port_handle); + if (_port_handle) { + return port_engine.monitoring_input (_port_handle); + } + return false; } void @@ -268,7 +316,9 @@ Port::set_public_latency_range (LatencyRange& range, bool playback) const name(), range.min, range.max, (playback ? "PLAYBACK" : "CAPTURE")));; - port_engine.set_latency_range (_port_handle, playback, range); + if (_port_handle) { + port_engine.set_latency_range (_port_handle, playback, range); + } } void @@ -320,12 +370,16 @@ Port::public_latency_range (bool /*playback*/) const { LatencyRange r; - r = port_engine.get_latency_range (_port_handle, sends_output() ? true : false); - DEBUG_TRACE (DEBUG::Latency, string_compose ( - "GET PORT %1: %4 PUBLIC latency range %2 .. %3\n", - name(), r.min, r.max, - sends_output() ? "PLAYBACK" : "CAPTURE")); + if (_port_handle) { + r = port_engine.get_latency_range (_port_handle, sends_output() ? true : false); + + DEBUG_TRACE (DEBUG::Latency, string_compose ( + "GET PORT %1: %4 PUBLIC latency range %2 .. %3\n", + name(), r.min, r.max, + sends_output() ? "PLAYBACK" : "CAPTURE")); + } + return r; } @@ -338,7 +392,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const if (!connections.empty()) { - range.min = ~((jack_nframes_t) 0); + range.min = ~((pframes_t) 0); range.max = 0; DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: %2 connections to check for latency range\n", name(), connections.size())); @@ -378,7 +432,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const boost::shared_ptr remote_port = AudioEngine::instance()->get_port_by_name (*c); if (remote_port) { - lr = remote_port->private_latency_range ((playback ? JackPlaybackLatency : JackCaptureLatency)); + lr = remote_port->private_latency_range ((playback ? true : false)); DEBUG_TRACE (DEBUG::Latency, string_compose ( "\t%1 <-LOCAL-> %2 : latter has latency range %3 .. %4\n", name(), *c, lr.min, lr.max)); @@ -401,6 +455,7 @@ Port::get_connected_latency_range (LatencyRange& range, bool playback) const int Port::reestablish () { + DEBUG_TRACE (DEBUG::Ports, string_compose ("re-establish %1 port %2\n", type().to_string(), _name)); _port_handle = port_engine.register_port (_name, type(), _flags); if (_port_handle == 0) { @@ -419,6 +474,8 @@ Port::reconnect () { /* caller must hold process lock; intended to be used only after reestablish() */ + DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2 destinations\n",name(), _connections.size())); + for (std::set::iterator i = _connections.begin(); i != _connections.end(); ++i) { if (connect (*i)) { return -1; @@ -432,7 +489,7 @@ Port::reconnect () int Port::set_name (std::string const & n) { - if (n == _name) { + if (n == _name || !_port_handle) { return 0; } @@ -450,6 +507,68 @@ Port::set_name (std::string const & n) bool Port::physically_connected () const { + if (!_port_handle) { + return false; + } + return port_engine.physically_connected (_port_handle); } +XMLNode& +Port::get_state () const +{ + XMLNode* root = new XMLNode (state_node_name); + + root->add_property (X_("name"), AudioEngine::instance()->make_port_name_relative (name())); + + if (receives_input()) { + root->add_property (X_("direction"), X_("input")); + } else { + root->add_property (X_("direction"), X_("output")); + } + + vector c; + + get_connections (c); + + for (vector::const_iterator i = c.begin(); i != c.end(); ++i) { + XMLNode* child = new XMLNode (X_("Connection")); + child->add_property (X_("other"), *i); + root->add_child_nocopy (*child); + } + + return *root; +} + +int +Port::set_state (const XMLNode& node, int) +{ + const XMLProperty* prop; + + if (node.name() != state_node_name) { + return -1; + } + + if ((prop = node.property (X_("name"))) != 0) { + set_name (prop->value()); + } + + const XMLNodeList& children (node.children()); + + _connections.clear (); + + for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) { + + if ((*c)->name() != X_("Connection")) { + continue; + } + + if ((prop = (*c)->property (X_("other"))) == 0) { + continue; + } + + _connections.insert (prop->value()); + } + + return 0; +}