+bool
+PortGroup::has_port (std::string const& p) const
+{
+ for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
+ if ((*i)->bundle->offers_port_alone (p)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+boost::shared_ptr<Bundle>
+PortGroup::only_bundle ()
+{
+ assert (_bundles.size() == 1);
+ return _bundles.front()->bundle;
+}
+
+
+ChanCount
+PortGroup::total_channels () const
+{
+ ChanCount n;
+ for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
+ n += (*i)->bundle->nchannels ();
+ }
+
+ return n;
+}
+
+boost::shared_ptr<IO>
+PortGroup::io_from_bundle (boost::shared_ptr<ARDOUR::Bundle> b) const
+{
+ BundleList::const_iterator i = _bundles.begin ();
+ while (i != _bundles.end() && (*i)->bundle != b) {
+ ++i;
+ }
+
+ if (i == _bundles.end()) {
+ return boost::shared_ptr<IO> ();
+ }
+
+ boost::shared_ptr<IO> io ((*i)->io.lock ());
+ return io;
+}
+
+/** Remove bundles whose channels are already represented by other, larger bundles */
+void
+PortGroup::remove_duplicates ()
+{
+ BundleList::iterator i = _bundles.begin();
+ while (i != _bundles.end()) {
+
+ BundleList::iterator tmp = i;
+ ++tmp;
+
+ bool remove = false;
+
+ for (BundleList::iterator j = _bundles.begin(); j != _bundles.end(); ++j) {
+
+ if ((*j)->bundle->nchannels() > (*i)->bundle->nchannels()) {
+ /* this bundle is larger */
+
+ uint32_t k = 0;
+ while (k < (*i)->bundle->nchannels().n_total()) {
+ /* see if this channel on *i has an equivalent on *j */
+ uint32_t l = 0;
+ while (l < (*j)->bundle->nchannels().n_total() && (*i)->bundle->channel_ports (k) != (*j)->bundle->channel_ports (l)) {
+ ++l;
+ }
+
+ if (l == (*j)->bundle->nchannels().n_total()) {
+ /* it does not */
+ break;
+ }
+
+ ++k;
+ }
+
+ if (k == (*i)->bundle->nchannels().n_total()) {
+ /* all channels on *i are represented by the larger bundle *j, so remove *i */
+ remove = true;
+ break;
+ }
+ }
+ }
+
+ if (remove) {
+ _bundles.erase (i);
+ }
+
+ i = tmp;
+ }
+}
+
+