allow to customize variable i/o plugin inputs
[ardour.git] / libs / ardour / io.cc
index ebd295411e9cdfaf3d5198e0c36f0a737cd86d92..87bac6b8f49beac392913cf55c7ec2a61fdc2798 100644 (file)
@@ -16,7 +16,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <fstream>
 #include <algorithm>
 #include <cmath>
 #include <vector>
@@ -39,6 +38,7 @@
 #include "ardour/debug.h"
 #include "ardour/io.h"
 #include "ardour/port.h"
+#include "ardour/profile.h"
 #include "ardour/route.h"
 #include "ardour/session.h"
 #include "ardour/user_bundle.h"
@@ -99,6 +99,9 @@ IO::~IO ()
 void
 IO::disconnect_check (boost::shared_ptr<Port> a, boost::shared_ptr<Port> b)
 {
+       if (_session.state_of_the_state () & Session::Deletion) {
+               return;
+       }
        /* this could be called from within our own ::disconnect() method(s)
           or from somewhere that operates directly on a port. so, we don't
           know for sure if we can take this lock or not. if we fail,
@@ -112,7 +115,7 @@ IO::disconnect_check (boost::shared_ptr<Port> a, boost::shared_ptr<Port> b)
                 * ::disconnect()
                 */
                if (_ports.contains (a) || _ports.contains (b)) {
-                       changed (IOChange (IOChange::ConnectionsChanged), this); /* EMIT SIGNAL */              
+                       changed (IOChange (IOChange::ConnectionsChanged), this); /* EMIT SIGNAL */
                }
        } else {
                /* we didn't get the lock, so assume that we're inside
@@ -298,7 +301,7 @@ IO::remove_port (boost::shared_ptr<Port> port, void* src)
        }
 
        _session.set_dirty ();
-       
+
        return 0;
 }
 
@@ -320,12 +323,12 @@ IO::add_port (string destination, void* src, DataType type)
        ChanCount before = _ports.count ();
        ChanCount after = before;
        after.set (type, after.get (type) + 1);
-       
+
        bool const r = PortCountChanging (after); /* EMIT SIGNAL */
        if (r) {
                return -1;
        }
-       
+
        IOChange change;
 
        {
@@ -338,7 +341,7 @@ IO::add_port (string destination, void* src, DataType type)
                        /* Create a new port */
 
                        string portname = build_legal_port_name (type);
-                       
+
                        if (_direction == Input) {
                                if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
                                        error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
@@ -354,7 +357,7 @@ IO::add_port (string destination, void* src, DataType type)
                        change.before = _ports.count ();
                        _ports.add (our_port);
                }
-               
+
                PortCountChanged (n_ports()); /* EMIT SIGNAL */
                change.type = IOChange::ConfigurationChanged;
                change.after = _ports.count ();
@@ -368,6 +371,7 @@ IO::add_port (string destination, void* src, DataType type)
                }
        }
 
+       apply_pretty_name ();
        setup_bundle ();
        _session.set_dirty ();
 
@@ -525,9 +529,8 @@ IO::state (bool /*full_state*/)
        XMLNode* node = new XMLNode (state_node_name);
        char buf[64];
        string str;
-       vector<string>::iterator ci;
        int n;
-       LocaleGuard lg (X_("POSIX"));
+       LocaleGuard lg (X_("C"));
        Glib::Threads::Mutex::Lock lm (io_lock);
 
        node->add_property("name", _name);
@@ -536,6 +539,10 @@ IO::state (bool /*full_state*/)
        node->add_property ("direction", enum_2_string (_direction));
        node->add_property ("default-type", _default_type.to_string());
 
+       if (!_pretty_name_prefix.empty ()) {
+               node->add_property("pretty-name", _pretty_name_prefix);
+       }
+
        for (std::vector<UserBundleInfo*>::iterator i = _bundles_connected.begin(); i != _bundles_connected.end(); ++i) {
                XMLNode* n = new XMLNode ("Bundle");
                n->add_property ("name", (*i)->bundle->name ());
@@ -551,6 +558,8 @@ IO::state (bool /*full_state*/)
                pnode->add_property (X_("name"), i->name());
 
                if (i->get_connections (connections)) {
+                       vector<string>::const_iterator ci;
+                       std::sort (connections.begin(), connections.end());
 
                        for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
 
@@ -573,7 +582,7 @@ IO::state (bool /*full_state*/)
 
        snprintf (buf, sizeof (buf), "%" PRId64, _user_latency);
        node->add_property (X_("user-latency"), buf);
-       
+
        return *node;
 }
 
@@ -588,7 +597,7 @@ IO::set_state (const XMLNode& node, int version)
 
        const XMLProperty* prop;
        XMLNodeConstIterator iter;
-       LocaleGuard lg (X_("POSIX"));
+       LocaleGuard lg (X_("C"));
 
        /* force use of non-localized representation of decimal point,
           since we use it a lot in XML files and so forth.
@@ -618,6 +627,11 @@ IO::set_state (const XMLNode& node, int version)
                return -1;
        }
 
+       // after create_ports, updates names
+       if ((prop = node.property ("pretty-name")) != 0) {
+               set_pretty_name (prop->value());
+       }
+
        if (connecting_legal) {
 
                if (make_connections (node, version, false)) {
@@ -644,7 +658,7 @@ IO::set_state_2X (const XMLNode& node, int version, bool in)
 {
        const XMLProperty* prop;
        XMLNodeConstIterator iter;
-       LocaleGuard lg (X_("POSIX"));
+       LocaleGuard lg (X_("C"));
 
        /* force use of non-localized representation of decimal point,
           since we use it a lot in XML files and so forth.
@@ -692,13 +706,16 @@ IO::set_state_2X (const XMLNode& node, int version, bool in)
 int
 IO::connecting_became_legal ()
 {
-       int ret;
+       int ret = 0;
 
        assert (pending_state_node);
 
        connection_legal_c.disconnect ();
 
-       ret = make_connections (*pending_state_node, pending_state_node_version, pending_state_node_in);
+    // it's not required for TracksLive, as long as TracksLive's session does all the connections when it's being loaded
+    if (!Profile->get_trx() ) {
+        ret = make_connections (*pending_state_node, pending_state_node_version, pending_state_node_in);
+    }
 
        delete pending_state_node;
        pending_state_node = 0;
@@ -854,6 +871,7 @@ IO::get_port_counts (const XMLNode& node, int version, ChanCount& n, boost::shar
        for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
 
                if ((*iter)->name() == X_("Bundle")) {
+                       prop = (*iter)->property ("name");
                        if ((c = find_possible_bundle (prop->value())) != 0) {
                                n = ChanCount::max (n, c->nchannels());
                                return 0;
@@ -977,9 +995,9 @@ IO::prepare_for_reset (XMLNode& node, const std::string& name)
        for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) {
 
                if ((*i)->name() == "Port") {
-                       
+
                        prop = (*i)->property (X_("name"));
-                       
+
                        if (prop) {
                                string new_name;
                                string old = prop->value();
@@ -987,10 +1005,10 @@ IO::prepare_for_reset (XMLNode& node, const std::string& name)
 
                                if (slash != string::npos) {
                                        /* port name is of form: <IO-name>/<port-name> */
-                                       
+
                                        new_name = name;
                                        new_name += old.substr (old.find ('/'));
-                                       
+
                                        prop->set_value (new_name);
                                }
                        }
@@ -1039,7 +1057,8 @@ IO::make_connections_2X (const XMLNode& node, int /*version*/, bool in)
                                        if (p != string::npos) {
                                                ports[x].replace (p, 4, "/audio_out");
                                        }
-                                       nth(i)->connect (ports[x]);
+                                       if (NULL != nth(i).get())
+                                               nth(i)->connect (ports[x]);
                                }
                        }
 
@@ -1081,7 +1100,8 @@ IO::make_connections_2X (const XMLNode& node, int /*version*/, bool in)
                                        if (p != string::npos) {
                                                ports[x].replace (p, 3, "/audio_in");
                                        }
-                                       nth(i)->connect (ports[x]);
+                                       if (NULL != nth(i).get())
+                                               nth(i)->connect (ports[x]);
                                }
                        }
 
@@ -1097,7 +1117,6 @@ int
 IO::set_ports (const string& str)
 {
        vector<string> ports;
-       int i;
        int n;
        uint32_t nports;
 
@@ -1114,14 +1133,10 @@ IO::set_ports (const string& str)
                }
        }
 
-       string::size_type start, end, ostart;
-
-       ostart = 0;
-       start = 0;
-       end = 0;
-       i = 0;
-
-       while ((start = str.find_first_of ('{', ostart)) != string::npos) {
+       string::size_type start  = 0;
+       string::size_type end    = 0;
+       string::size_type ostart = 0;
+       for (int i = 0; (start = str.find_first_of ('{', ostart)) != string::npos; ++i) {
                start += 1;
 
                if ((end = str.find_first_of ('}', start)) == string::npos) {
@@ -1142,7 +1157,6 @@ IO::set_ports (const string& str)
                }
 
                ostart = end+1;
-               i++;
        }
 
        return 0;
@@ -1157,7 +1171,6 @@ IO::parse_io_string (const string& str, vector<string>& ports)
                return 0;
        }
 
-       pos = 0;
        opos = 0;
 
        ports.clear ();
@@ -1179,7 +1192,6 @@ IO::parse_gain_string (const string& str, vector<string>& ports)
 {
        string::size_type pos, opos;
 
-       pos = 0;
        opos = 0;
        ports.clear ();
 
@@ -1221,6 +1233,31 @@ IO::set_name (const string& requested_name)
        return r;
 }
 
+void
+IO::set_pretty_name (const std::string& str)
+{
+       if (_pretty_name_prefix == str) {
+               return;
+       }
+       _pretty_name_prefix = str;
+       apply_pretty_name ();
+}
+
+void
+IO::apply_pretty_name ()
+{
+       uint32_t pn = 1;
+       if (_pretty_name_prefix.empty ()) {
+               return;
+       }
+       for (PortSet::iterator i = _ports.begin (); i != _ports.end(); ++i, ++pn) {
+               (*i)->set_pretty_name (string_compose (("%1/%2 %3"),
+                                       _pretty_name_prefix,
+                                       _direction == Output ? _("Out") : _("In"),
+                                       pn));
+       }
+}
+
 framecnt_t
 IO::latency () const
 {
@@ -1414,7 +1451,7 @@ IO::find_port_hole (const char* base)
                std::vector<char> buf (AudioEngine::instance()->port_name_size());
                PortSet::iterator i = _ports.begin();
 
-               snprintf (&buf[0], jack_port_name_size(), _("%s %u"), base, n);
+               snprintf (&buf[0], buf.size()+1, _("%s %u"), base, n);
 
                for ( ; i != _ports.end(); ++i) {
                        if (string(i->name()) == string(&buf[0])) {
@@ -1611,8 +1648,10 @@ IO::connected_to (boost::shared_ptr<const IO> other) const
 
        for (i = 0; i < no; ++i) {
                for (j = 0; j < ni; ++j) {
-                       if (nth(i)->connected_to (other->nth(j)->name())) {
-                               return true;
+                       if ((NULL != nth(i).get()) && (NULL != other->nth(j).get())) {
+                               if (nth(i)->connected_to (other->nth(j)->name())) {
+                                       return true;
+                               }
                        }
                }
        }
@@ -1673,7 +1712,7 @@ IO::collect_input (BufferSet& bufs, pframes_t nframes, ChanCount offset)
                }
 
                for ( ; i != _ports.end(*t); ++i, ++b) {
-                       Buffer& bb (i->get_buffer (nframes));
+                       const Buffer& bb (i->get_buffer (nframes));
                        b->read_from (bb, nframes);
                }
        }