SoloSelection: libardour part.
[ardour.git] / libs / ardour / bundle.cc
index 33f71dcecd2149cca3341aca399cdc51bf0408f9..65f0c8e127e468da830916ee799e27b4a235fe47 100644 (file)
@@ -361,16 +361,23 @@ Bundle::connect (boost::shared_ptr<Bundle> other, AudioEngine & engine,
 void
 Bundle::disconnect (boost::shared_ptr<Bundle> other, AudioEngine & engine)
 {
-       uint32_t const N = n_total();
-       assert (N == other->n_total());
+       ChanCount our_count = nchannels();
+       ChanCount other_count = other->nchannels();
 
-       for (uint32_t i = 0; i < N; ++i) {
-               Bundle::PortList const & our_ports = channel_ports (i);
-               Bundle::PortList const & other_ports = other->channel_ports (i);
+       for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+               uint32_t N = min(our_count.n(*t), other_count.n(*t));
+               for (uint32_t i = 0; i < N; ++i) {
+                       Bundle::PortList const & our_ports =
+                               channel_ports (type_channel_to_overall(*t, i));
+                       Bundle::PortList const & other_ports =
+                               other->channel_ports (other->type_channel_to_overall(*t, i));
 
-               for (Bundle::PortList::const_iterator j = our_ports.begin(); j != our_ports.end(); ++j) {
-                       for (Bundle::PortList::const_iterator k = other_ports.begin(); k != other_ports.end(); ++k) {
-                               engine.disconnect (*j, *k);
+                       for (Bundle::PortList::const_iterator j = our_ports.begin();
+                                               j != our_ports.end(); ++j) {
+                               for (Bundle::PortList::const_iterator k = other_ports.begin();
+                                                       k != other_ports.end(); ++k) {
+                                       engine.disconnect (*j, *k);
+                               }
                        }
                }
        }
@@ -434,8 +441,12 @@ Bundle::emit_changed (Change c)
        }
 }
 
-/* @return true if a Bundle is connected to another.
- * @param type: if not NIL, restrict the check to channels of that type. */
+/** This must not be called in code executed as a response to a backend event,
+ *  as it may query the backend in the same thread where it's waiting for us.
+ * @return true if a Bundle is connected to another.
+ * @param type: if not NIL, restrict the check to channels of that type.
+ * @param exclusive: if true, additionally check if the bundle is connected
+ *                   only to |other|, and return false if not. */
 bool
 Bundle::connected_to (boost::shared_ptr<Bundle> other, AudioEngine & engine,
                       DataType type, bool exclusive)
@@ -446,7 +457,7 @@ Bundle::connected_to (boost::shared_ptr<Bundle> other, AudioEngine & engine,
        if (type == DataType::NIL) {
                for (DataType::iterator t = DataType::begin();
                                        t != DataType::end(); ++t) {
-                       if (!connected_to(other, engine, *t))
+                       if (!connected_to(other, engine, *t, exclusive))
                                return false;
                }
                return true;
@@ -456,6 +467,8 @@ Bundle::connected_to (boost::shared_ptr<Bundle> other, AudioEngine & engine,
        if (other->nchannels().n(type) != N)
                return false;
 
+       vector<string> port_connections;
+
        for (uint32_t i = 0; i < N; ++i) {
                Bundle::PortList const & our_ports =
                        channel_ports (type_channel_to_overall(type, i));
@@ -480,6 +493,13 @@ Bundle::connected_to (boost::shared_ptr<Bundle> other, AudioEngine & engine,
                                        return false;
                                }
                        }
+
+                       if (exclusive && p) {
+                               port_connections.clear();
+                               p->get_connections(port_connections);
+                               if (port_connections.size() != other_ports.size())
+                                       return false;
+                       }
                }
        }
 
@@ -543,17 +563,22 @@ Bundle::set_name (string const & n)
 bool
 Bundle::has_same_ports (boost::shared_ptr<Bundle> b) const
 {
-       uint32_t const N = n_total();
+       ChanCount our_count = nchannels();
+       ChanCount other_count = b->nchannels();
 
-       if (b->n_total() != N) {
+       if (our_count != other_count)
                return false;
-       }
 
-       /* XXX: probably should sort channel port lists before comparing them */
+       for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+               uint32_t N = our_count.n(*t);
+               for (uint32_t i = 0; i < N; ++i) {
+                       Bundle::PortList const & our_ports =
+                               channel_ports (type_channel_to_overall(*t, i));
+                       Bundle::PortList const & other_ports =
+                               b->channel_ports (b->type_channel_to_overall(*t, i));
 
-       for (uint32_t i = 0; i < N; ++i) {
-               if (channel_ports (i) != b->channel_ports (i)) {
-                       return false;
+                       if (our_ports != other_ports)
+                               return false;
                }
        }