Merge branch 'master' into cairocanvas
[ardour.git] / libs / ardour / port.cc
index 571d227711669f9fbd64b8feafdd395d1baeacb0..bc5d26fb805431059246f5f29dd46c820ea125d0 100644 (file)
@@ -21,7 +21,9 @@
 #include "libardour-config.h"
 #endif
 
+#ifndef PLATFORM_WINDOWS
 #include <jack/weakjack.h> // so that we can test for new functions at runtime
+#endif
 
 #include "pbd/compose.h"
 #include "pbd/error.h"
@@ -44,6 +46,7 @@ PBD::Signal0<void> 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
@@ -88,6 +91,7 @@ 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;
        }
@@ -120,12 +124,21 @@ Port::disconnect_all ()
 bool
 Port::connected_to (std::string const & o) const
 {
+       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();
+       }
+
        return port_engine.get_connections (_port_handle, c);
 }
 
@@ -142,9 +155,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) {
@@ -327,7 +342,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()));
@@ -390,6 +405,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) {
@@ -408,6 +424,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<string>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
                if (connect (*i)) {
                        return -1;
@@ -442,3 +460,61 @@ Port::physically_connected () const
        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<string> c;
+       
+       get_connections (c);
+
+       for (vector<string>::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;
+}