X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fport.cc;h=3473b73617a84226bb442a1bc421bc717fc1ce57;hb=86f1b8c71f7cfae210d66bb97d3c513eade0c40e;hp=bd3004ba02f0c70262dbc15b77f9c2f682c5195b;hpb=148c1f805bca9d459d9a24a6b5c8d5f277680a9e;p=ardour.git diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index bd3004ba02..3473b73617 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -21,17 +21,15 @@ #include "libardour-config.h" #endif -#include - #include // so that we can test for new functions at runtime -#include "pbd/error.h" #include "pbd/compose.h" +#include "pbd/error.h" +#include "pbd/failed_constructor.h" +#include "ardour/audioengine.h" #include "ardour/debug.h" #include "ardour/port.h" -#include "ardour/audioengine.h" -#include "pbd/failed_constructor.h" #include "i18n.h" @@ -39,6 +37,9 @@ using namespace std; using namespace ARDOUR; using namespace PBD; +PBD::Signal2, boost::shared_ptr > Port::PostDisconnect; +PBD::Signal0 Port::PortDrop; + AudioEngine* Port::_engine = 0; bool Port::_connecting_blocked = false; pframes_t Port::_global_port_buffer_offset = 0; @@ -68,16 +69,27 @@ Port::Port (std::string const & n, DataType t, Flags f) } if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) { - cerr << "Failed to register JACK port, reason is unknown from here\n"; + cerr << "Failed to register JACK port \"" << _name << "\", reason is unknown from here\n"; throw failed_constructor (); } + + PortDrop.connect_same_thread (drop_connection, boost::bind (&Port::drop, this)); } /** Port destructor */ Port::~Port () { - if (_engine->jack ()) { - jack_port_unregister (_engine->jack (), _jack_port); + drop (); +} + +void +Port::drop () +{ + if (_jack_port) { + if (_engine->jack ()) { + jack_port_unregister (_engine->jack (), _jack_port); + } + _jack_port = 0; } } @@ -94,6 +106,11 @@ Port::disconnect_all () jack_port_disconnect (_engine->jack(), _jack_port); _connections.clear (); + /* a cheaper, less hacky way to do boost::shared_from_this() ... + */ + boost::shared_ptr pself = _engine->get_port_by_name (name()); + PostDisconnect (pself, boost::shared_ptr()); // emit signal + return 0; } @@ -104,7 +121,7 @@ bool Port::connected_to (std::string const & o) const { if (!_engine->connected()) { - /* in some senses, this answer isn't the right one all the time, + /* 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 JACK. */ @@ -128,8 +145,12 @@ Port::get_connections (std::vector & c) const c.push_back (jc[i]); ++n; } - - jack_free (jc); + + if (jack_free) { + jack_free (jc); + } else { + free (jc); + } } } @@ -164,21 +185,34 @@ Port::connect (std::string const & other) int Port::disconnect (std::string const & other) { - std::string const other_shrt = _engine->make_port_name_non_relative (other); - std::string const this_shrt = _engine->make_port_name_non_relative (_name); + std::string const other_fullname = _engine->make_port_name_non_relative (other); + std::string const this_fullname = _engine->make_port_name_non_relative (_name); int r = 0; if (sends_output ()) { - r = jack_disconnect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ()); + r = jack_disconnect (_engine->jack (), this_fullname.c_str (), other_fullname.c_str ()); } else { - r = jack_disconnect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str ()); + r = jack_disconnect (_engine->jack (), other_fullname.c_str (), this_fullname.c_str ()); } if (r == 0) { _connections.erase (other); } + /* a cheaper, less hacky way to do boost::shared_from_this() ... + */ + boost::shared_ptr pself = _engine->get_port_by_name (name()); + boost::shared_ptr pother = _engine->get_port_by_name (other); + + if (pself && pother) { + /* Disconnecting from another Ardour port: need to allow + a check on whether this may affect anything that we + need to know about. + */ + PostDisconnect (pself, pother); // emit signal + } + return r; } @@ -208,13 +242,13 @@ Port::set_engine (AudioEngine* e) } void -Port::ensure_monitor_input (bool yn) +Port::ensure_jack_monitors_input (bool yn) { jack_port_ensure_monitor (_jack_port, yn); } bool -Port::monitoring_input () const +Port::jack_monitoring_input () const { return jack_port_monitoring_input (_jack_port); } @@ -226,7 +260,7 @@ Port::reset () } void -Port::cycle_start (pframes_t nframes) +Port::cycle_start (pframes_t) { _port_buffer_offset = 0; } @@ -236,7 +270,7 @@ Port::increment_port_buffer_offset (pframes_t nframes) { _port_buffer_offset += nframes; } - + void Port::set_public_latency_range (jack_latency_range_t& range, bool playback) const { @@ -247,7 +281,7 @@ Port::set_public_latency_range (jack_latency_range_t& range, bool playback) cons if (!jack_port_set_latency_range) { return; } - + DEBUG_TRACE (DEBUG::Latency, string_compose ("SET PORT %1 %4 PUBLIC latency now [%2 - %3]\n", name(), range.min, range.max, @@ -266,14 +300,14 @@ Port::set_private_latency_range (jack_latency_range_t& range, bool playback) DEBUG_TRACE (DEBUG::Latency, string_compose ( "SET PORT %1 playback PRIVATE latency now [%2 - %3]\n", name(), - _private_playback_latency.min, + _private_playback_latency.min, _private_playback_latency.max)); } else { _private_capture_latency = range; DEBUG_TRACE (DEBUG::Latency, string_compose ( "SET PORT %1 capture PRIVATE latency now [%2 - %3]\n", - name(), - _private_capture_latency.min, + name(), + _private_capture_latency.min, _private_capture_latency.max)); } @@ -288,30 +322,30 @@ Port::private_latency_range (bool playback) const if (playback) { DEBUG_TRACE (DEBUG::Latency, string_compose ( "GET PORT %1 playback PRIVATE latency now [%2 - %3]\n", - name(), - _private_playback_latency.min, - _private_playback_latency.max)); + name(), + _private_playback_latency.min, + _private_playback_latency.max)); return _private_playback_latency; } else { DEBUG_TRACE (DEBUG::Latency, string_compose ( "GET PORT %1 capture PRIVATE latency now [%2 - %3]\n", - name(), - _private_playback_latency.min, + name(), + _private_playback_latency.min, _private_playback_latency.max)); return _private_capture_latency; } } jack_latency_range_t -Port::public_latency_range (bool playback) const +Port::public_latency_range (bool /*playback*/) const { jack_latency_range_t r; - jack_port_get_latency_range (_jack_port, + jack_port_get_latency_range (_jack_port, sends_output() ? JackPlaybackLatency : JackCaptureLatency, &r); DEBUG_TRACE (DEBUG::Latency, string_compose ( - "GET PORT %1: %4 PUBLIC latency range %2 .. %3\n", + "GET PORT %1: %4 PUBLIC latency range %2 .. %3\n", name(), r.min, r.max, sends_output() ? "PLAYBACK" : "CAPTURE")); return r; @@ -326,7 +360,7 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c vector connections; jack_client_t* jack = _engine->jack(); - + if (!jack) { range.min = 0; range.max = 0; @@ -337,37 +371,68 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c get_connections (connections); if (!connections.empty()) { - + range.min = ~((jack_nframes_t) 0); range.max = 0; + DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: %2 connections to check for latency range\n", name(), connections.size())); + for (vector::const_iterator c = connections.begin(); c != connections.end(); ++c) { - cerr << "Connection between " << name() << " and " << *c << endl; - - jack_port_t* remote_port = jack_port_by_name (_engine->jack(), (*c).c_str()); - jack_latency_range_t lr; - - if (remote_port) { - jack_port_get_latency_range ( - remote_port, - (playback ? JackPlaybackLatency : JackCaptureLatency), - &lr); - DEBUG_TRACE (DEBUG::Latency, string_compose ( - "\t%1 <-> %2 : latter has latency range %3 .. %4\n", - name(), *c, lr.min, lr.max)); - range.min = min (range.min, lr.min); - range.max = max (range.max, lr.max); + jack_latency_range_t lr; + + if (!AudioEngine::instance()->port_is_mine (*c)) { + + /* port belongs to some other JACK client, use + * JACK to lookup its latency information. + */ + + jack_port_t* remote_port = jack_port_by_name (_engine->jack(), (*c).c_str()); + + if (remote_port) { + jack_port_get_latency_range ( + remote_port, + (playback ? JackPlaybackLatency : JackCaptureLatency), + &lr); + + DEBUG_TRACE (DEBUG::Latency, string_compose ( + "\t%1 <-> %2 : latter has latency range %3 .. %4\n", + name(), *c, lr.min, lr.max)); + + range.min = min (range.min, lr.min); + range.max = max (range.max, lr.max); + } + } else { - cerr << "\t NO PORT BY NAME!\n"; - } + + /* port belongs to this instance of ardour, + so look up its latency information + internally, because our published/public + values already contain our plugin + latency compensation. + */ + + boost::shared_ptr remote_port = AudioEngine::instance()->get_port_by_name (*c); + if (remote_port) { + lr = remote_port->private_latency_range ((playback ? JackPlaybackLatency : JackCaptureLatency)); + DEBUG_TRACE (DEBUG::Latency, string_compose ( + "\t%1 <-LOCAL-> %2 : latter has latency range %3 .. %4\n", + name(), *c, lr.min, lr.max)); + + range.min = min (range.min, lr.min); + range.max = max (range.max, lr.max); + } + } } } else { + DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: not connected to anything\n", name())); range.min = 0; range.max = 0; } + + DEBUG_TRACE (DEBUG::Latency, string_compose ("%1: final connected latency range [ %2 .. %3 ] \n", name(), range.min, range.max)); } int @@ -417,14 +482,16 @@ Port::set_name (std::string const & n) int const r = jack_port_set_name (_jack_port, n.c_str()); if (r == 0) { + _engine->port_renamed (_name, n); _name = n; } + return r; } void -Port::request_monitor_input (bool yn) +Port::request_jack_monitors_input (bool yn) { jack_port_request_monitor (_jack_port, yn); } @@ -438,14 +505,21 @@ Port::physically_connected () const for (int i = 0; jc[i]; ++i) { jack_port_t* port = jack_port_by_name (_engine->jack(), jc[i]); - + if (port && (jack_port_flags (port) & JackPortIsPhysical)) { - jack_free (jc); + if (jack_free) { + jack_free (jc); + } else { + free (jc); + } return true; } } - - jack_free (jc); + if (jack_free) { + jack_free (jc); + } else { + free (jc); + } } return false;