+ PortDrop.connect_same_thread (drop_connection, boost::bind (&Port::drop, this));
+ PortSignalDrop.connect_same_thread (drop_connection, boost::bind (&Port::signal_drop, this));
+ port_manager->PortConnectedOrDisconnected.connect_same_thread (engine_connection,
+ boost::bind (&Port::port_connected_or_disconnected, this, _1, _3, _5));
+}
+
+/** Port destructor */
+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 "";
+}
+
+bool
+Port::set_pretty_name(const std::string& n)
+{
+ if (_port_handle) {
+ if (0 == port_engine.set_port_property (_port_handle,
+ "http://jackaudio.org/metadata/pretty-name", n, ""))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+Port::signal_drop ()
+{
+ engine_connection.disconnect ();
+}
+
+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;
+ }
+}
+
+void
+Port::port_connected_or_disconnected (boost::weak_ptr<Port> w0, boost::weak_ptr<Port> w1, bool con)
+{
+ if (con) {
+ /* we're only interested in disconnect */
+ return;
+ }
+ boost::shared_ptr<Port> p0 = w0.lock ();
+ boost::shared_ptr<Port> p1 = w1.lock ();
+ /* a cheaper, less hacky way to do boost::shared_from_this() ... */
+ boost::shared_ptr<Port> pself = AudioEngine::instance()->get_port_by_name (name());
+
+ if (p0 == pself) {
+ PostDisconnect (p0, p1); // emit signal
+ }
+ if (p1 == pself) {
+ PostDisconnect (p1, p0); // emit signal
+ }
+}
+
+/** @return true if this port is connected to anything */
+bool
+Port::connected () const
+{
+ if (_port_handle) {
+ return (port_engine.connected (_port_handle) != 0);
+ }
+ return false;
+}
+
+int
+Port::disconnect_all ()
+{
+ if (_port_handle) {
+
+ std::vector<std::string> 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<Port> pself = port_manager->get_port_by_name (name());
+ for (vector<string>::const_iterator c = connections.begin(); c != connections.end() && pself; ++c) {
+ boost::shared_ptr<Port> pother = AudioEngine::instance()->get_port_by_name (*c);
+ if (pother) {
+ PostDisconnect (pself, pother); // emit signal
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** @param o Port name
+ * @return true if this port is connected to o, otherwise false.
+ */
+bool
+Port::connected_to (std::string const & o) const
+{
+ if (!_port_handle) {
+ return false;
+ }
+
+ if (!port_engine.available()) {
+ return false;
+ }
+
+ return port_engine.connected_to (_port_handle, AudioEngine::instance()->make_port_name_non_relative (o));
+}
+
+int
+Port::get_connections (std::vector<std::string> & c) const
+{
+ 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 = AudioEngine::instance()->make_port_name_non_relative (other);
+ std::string const our_name = AudioEngine::instance()->make_port_name_non_relative (_name);
+
+ int r = 0;
+
+ if (_connecting_blocked) {
+ return r;
+ }
+
+ if (sends_output ()) {
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2\n", our_name, other_name));
+ r = port_engine.connect (our_name, other_name);
+ } else {
+ 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) {
+ _connections.insert (other);
+ }
+
+ return r;
+}
+
+int
+Port::disconnect (std::string const & other)
+{
+ 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;
+
+ if (sends_output ()) {
+ r = port_engine.disconnect (this_fullname, other_fullname);
+ } else {
+ r = port_engine.disconnect (other_fullname, this_fullname);
+ }
+
+ if (r == 0) {
+ _connections.erase (other);
+ }
+
+ /* a cheaper, less hacky way to do boost::shared_from_this() ... */
+ boost::shared_ptr<Port> pself = AudioEngine::instance()->get_port_by_name (name());
+ boost::shared_ptr<Port> pother = AudioEngine::instance()->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;
+}
+
+
+bool
+Port::connected_to (Port* o) const
+{
+ return connected_to (o->name ());
+}
+
+int
+Port::connect (Port* o)
+{
+ return connect (o->name ());
+}
+
+int
+Port::disconnect (Port* o)
+{
+ return disconnect (o->name ());
+}
+
+void
+Port::request_input_monitoring (bool yn)
+{
+ if (_port_handle) {
+ port_engine.request_input_monitoring (_port_handle, yn);
+ }
+}
+
+void
+Port::ensure_input_monitoring (bool yn)
+{
+ if (_port_handle) {
+ port_engine.ensure_input_monitoring (_port_handle, yn);
+ }
+}
+
+bool
+Port::monitoring_input () const
+{
+ if (_port_handle) {
+ return port_engine.monitoring_input (_port_handle);
+ }
+ return false;