start removal of NoteFixer code
[ardour.git] / libs / ardour / bundle.cc
1 /*
2  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
3  * Copyright (C) 2008-2016 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2009-2012 David Robillard <d@drobilla.net>
5  * Copyright (C) 2013-2015 Robin Gareus <robin@gareus.org>
6  * Copyright (C) 2017 Julien "_FrnchFrgg_" RIVAUD <frnchfrgg@free.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include <algorithm>
24
25 #include "ardour/bundle.h"
26 #include "ardour/audioengine.h"
27 #include "ardour/port.h"
28
29 #include "pbd/i18n.h"
30
31 using namespace std;
32 using namespace ARDOUR;
33 using namespace PBD;
34
35 /** Construct an audio bundle.
36  *  @param i true if ports are inputs, otherwise false.
37  */
38 Bundle::Bundle (bool i)
39         : _ports_are_inputs (i),
40           _signals_suspended (false),
41           _pending_change (Change (0))
42 {
43
44 }
45
46
47 /** Construct an audio bundle.
48  *  @param n Name.
49  *  @param i true if ports are inputs, otherwise false.
50  */
51 Bundle::Bundle (std::string const & n, bool i)
52         : _name (n),
53           _ports_are_inputs (i),
54           _signals_suspended (false),
55           _pending_change (Change (0))
56 {
57
58 }
59
60 Bundle::Bundle (boost::shared_ptr<Bundle> other)
61         : _channel (other->_channel),
62           _name (other->_name),
63           _ports_are_inputs (other->_ports_are_inputs),
64           _signals_suspended (other->_signals_suspended),
65           _pending_change (other->_pending_change)
66 {
67
68 }
69
70 ChanCount
71 Bundle::nchannels () const
72 {
73         Glib::Threads::Mutex::Lock lm (_channel_mutex);
74
75         ChanCount c;
76         for (vector<Channel>::const_iterator i = _channel.begin(); i != _channel.end(); ++i) {
77                 c.set (i->type, c.get (i->type) + 1);
78         }
79
80         return c;
81 }
82
83 uint32_t
84 Bundle::n_total () const
85 {
86     /* Simpler and far more efficient than nchannels.n_total() */
87     return _channel.size();
88 }
89
90 Bundle::PortList const &
91 Bundle::channel_ports (uint32_t c) const
92 {
93         assert (c < n_total());
94
95         Glib::Threads::Mutex::Lock lm (_channel_mutex);
96         return _channel[c].ports;
97 }
98
99 /** Add an association between one of our channels and a port.
100  *  @param ch Channel index.
101  *  @param portname full port name to associate with (including prefix).
102  */
103 void
104 Bundle::add_port_to_channel (uint32_t ch, string portname)
105 {
106         assert (ch < n_total());
107         assert (portname.find_first_of (':') != string::npos);
108
109         {
110                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
111                 _channel[ch].ports.push_back (portname);
112         }
113
114         emit_changed (PortsChanged);
115 }
116
117 /** Disassociate a port from one of our channels.
118  *  @param ch Channel index.
119  *  @param portname port name to disassociate from.
120  */
121 void
122 Bundle::remove_port_from_channel (uint32_t ch, string portname)
123 {
124         assert (ch < n_total());
125
126         bool changed = false;
127
128         {
129                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
130                 PortList& pl = _channel[ch].ports;
131                 PortList::iterator i = find (pl.begin(), pl.end(), portname);
132
133                 if (i != pl.end()) {
134                         pl.erase (i);
135                         changed = true;
136                 }
137         }
138
139         if (changed) {
140                 emit_changed (PortsChanged);
141         }
142 }
143
144 /** Set a single port to be associated with a channel, removing any others.
145  *  @param ch Channel.
146  *  @param portname Full port name, including prefix.
147  */
148 void
149 Bundle::set_port (uint32_t ch, string portname)
150 {
151         assert (ch < n_total());
152         assert (portname.find_first_of (':') != string::npos);
153
154         {
155                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
156                 _channel[ch].ports.clear ();
157                 _channel[ch].ports.push_back (portname);
158         }
159
160         emit_changed (PortsChanged);
161 }
162
163 /** @param n Channel name */
164 void
165 Bundle::add_channel (std::string const & n, DataType t)
166 {
167         {
168                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
169                 _channel.push_back (Channel (n, t));
170         }
171
172         emit_changed (ConfigurationChanged);
173 }
174
175 /** @param n Channel name */
176 void
177 Bundle::add_channel (std::string const & n, DataType t, PortList p)
178 {
179         {
180                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
181                 _channel.push_back (Channel (n, t, p));
182         }
183
184         emit_changed (ConfigurationChanged);
185 }
186
187 /** @param n Channel name */
188 void
189 Bundle::add_channel (std::string const & n, DataType t, std::string const & p)
190 {
191         {
192                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
193                 _channel.push_back (Channel (n, t, p));
194         }
195
196         emit_changed (ConfigurationChanged);
197 }
198
199 bool
200 Bundle::port_attached_to_channel (uint32_t ch, std::string portname)
201 {
202         assert (ch < n_total());
203
204         Glib::Threads::Mutex::Lock lm (_channel_mutex);
205         return (std::find (_channel[ch].ports.begin (), _channel[ch].ports.end (), portname) != _channel[ch].ports.end ());
206 }
207
208 /** Remove a channel.
209  *  @param ch Channel.
210  */
211 void
212 Bundle::remove_channel (uint32_t ch)
213 {
214         assert (ch < n_total());
215
216         Glib::Threads::Mutex::Lock lm (_channel_mutex);
217         _channel.erase (_channel.begin () + ch);
218
219         lm.release();
220         emit_changed (ConfigurationChanged);
221 }
222
223 /** Remove all channels */
224 void
225 Bundle::remove_channels ()
226 {
227         Glib::Threads::Mutex::Lock lm (_channel_mutex);
228
229         _channel.clear ();
230
231         lm.release();
232         emit_changed (ConfigurationChanged);
233 }
234
235 /** @param p Port name.
236  *  @return true if any channel is associated with p.
237  */
238 bool
239 Bundle::offers_port (std::string p) const
240 {
241         Glib::Threads::Mutex::Lock lm (_channel_mutex);
242
243         for (std::vector<Channel>::const_iterator i = _channel.begin(); i != _channel.end(); ++i) {
244                 for (PortList::const_iterator j = i->ports.begin(); j != i->ports.end(); ++j) {
245                         if (*j == p) {
246                                 return true;
247                         }
248                 }
249         }
250
251         return false;
252 }
253
254 /** @param p Port name.
255  *  @return true if this bundle offers this port on its own on a channel.
256  */
257 bool
258 Bundle::offers_port_alone (std::string p) const
259 {
260         Glib::Threads::Mutex::Lock lm (_channel_mutex);
261
262         for (std::vector<Channel>::const_iterator i = _channel.begin(); i != _channel.end(); ++i) {
263                 if (i->ports.size() == 1 && i->ports[0] == p) {
264                         return true;
265                 }
266         }
267
268         return false;
269 }
270
271
272 /** @param ch Channel.
273  *  @return Channel name.
274  */
275 std::string
276 Bundle::channel_name (uint32_t ch) const
277 {
278         assert (ch < n_total());
279
280         Glib::Threads::Mutex::Lock lm (_channel_mutex);
281         return _channel[ch].name;
282 }
283
284 /** Set the name of a channel.
285  *  @param ch Channel.
286  *  @param n New name.
287  */
288 void
289 Bundle::set_channel_name (uint32_t ch, std::string const & n)
290 {
291         assert (ch < n_total());
292
293         {
294                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
295                 _channel[ch].name = n;
296         }
297
298         emit_changed (NameChanged);
299 }
300
301 /** Take the channels from another bundle and add them to this bundle,
302  *  so that channels from other are added to this (with their ports)
303  *  and are named "<other_bundle_name> <other_channel_name>".
304  */
305 void
306 Bundle::add_channels_from_bundle (boost::shared_ptr<Bundle> other)
307 {
308         uint32_t const ch = n_total();
309
310         for (uint32_t i = 0; i < other->n_total(); ++i) {
311
312                 std::stringstream s;
313                 s << other->name() << " " << other->channel_name(i);
314
315                 add_channel (s.str(), other->channel_type(i));
316
317                 PortList const& pl = other->channel_ports (i);
318                 for (uint32_t j = 0; j < pl.size(); ++j) {
319                         add_port_to_channel (ch + i, pl[j]);
320                 }
321         }
322 }
323
324 /** Connect the ports associated with our channels to the ports associated
325  *  with another bundle's channels.
326  *  @param other Other bundle.
327  *  @param engine AudioEngine to use to make the connections.
328  *  @param allow_partial whether to allow leaving unconnected channels types,
329  *              or require that the ChanCounts match exactly (default false).
330  */
331 void
332 Bundle::connect (boost::shared_ptr<Bundle> other, AudioEngine & engine,
333                  bool allow_partial)
334 {
335         ChanCount our_count = nchannels();
336         ChanCount other_count = other->nchannels();
337
338         if (!allow_partial && our_count != other_count) {
339                 assert (our_count == other_count);
340                 return;
341         }
342
343         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
344                 uint32_t N = our_count.n(*t);
345                 if (N != other_count.n(*t))
346                         continue;
347                 for (uint32_t i = 0; i < N; ++i) {
348                         Bundle::PortList const & our_ports =
349                                 channel_ports (type_channel_to_overall(*t, i));
350                         Bundle::PortList const & other_ports =
351                                 other->channel_ports (other->type_channel_to_overall(*t, i));
352
353                         for (Bundle::PortList::const_iterator j = our_ports.begin();
354                                                 j != our_ports.end(); ++j) {
355                                 for (Bundle::PortList::const_iterator k = other_ports.begin();
356                                                         k != other_ports.end(); ++k) {
357                                         engine.connect (*j, *k);
358                                 }
359                         }
360                 }
361         }
362 }
363
364 void
365 Bundle::disconnect (boost::shared_ptr<Bundle> other, AudioEngine & engine)
366 {
367         ChanCount our_count = nchannels();
368         ChanCount other_count = other->nchannels();
369
370         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
371                 uint32_t N = min(our_count.n(*t), other_count.n(*t));
372                 for (uint32_t i = 0; i < N; ++i) {
373                         Bundle::PortList const & our_ports =
374                                 channel_ports (type_channel_to_overall(*t, i));
375                         Bundle::PortList const & other_ports =
376                                 other->channel_ports (other->type_channel_to_overall(*t, i));
377
378                         for (Bundle::PortList::const_iterator j = our_ports.begin();
379                                                 j != our_ports.end(); ++j) {
380                                 for (Bundle::PortList::const_iterator k = other_ports.begin();
381                                                         k != other_ports.end(); ++k) {
382                                         engine.disconnect (*j, *k);
383                                 }
384                         }
385                 }
386         }
387 }
388
389 /** Remove all ports from all channels */
390 void
391 Bundle::remove_ports_from_channels ()
392 {
393         {
394                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
395                 for (uint32_t c = 0; c < n_total(); ++c) {
396                         _channel[c].ports.clear ();
397                 }
398
399         }
400
401         emit_changed (PortsChanged);
402 }
403
404 /** Remove all ports from a given channel.
405  *  @param ch Channel.
406  */
407 void
408 Bundle::remove_ports_from_channel (uint32_t ch)
409 {
410         assert (ch < n_total());
411
412         {
413                 Glib::Threads::Mutex::Lock lm (_channel_mutex);
414                 _channel[ch].ports.clear ();
415         }
416
417         emit_changed (PortsChanged);
418 }
419
420 void
421 Bundle::suspend_signals ()
422 {
423         _signals_suspended = true;
424 }
425
426 void
427 Bundle::resume_signals ()
428 {
429         if (_pending_change) {
430                 Changed (_pending_change);
431                 _pending_change = Change (0);
432         }
433
434         _signals_suspended = false;
435 }
436
437 void
438 Bundle::emit_changed (Change c)
439 {
440         if (_signals_suspended) {
441                 _pending_change = Change (int (_pending_change) | int (c));
442         } else {
443                 Changed (c);
444         }
445 }
446
447 /** This must not be called in code executed as a response to a backend event,
448  *  as it may query the backend in the same thread where it's waiting for us.
449  * @return true if a Bundle is connected to another.
450  * @param type: if not NIL, restrict the check to channels of that type.
451  * @param exclusive: if true, additionally check if the bundle is connected
452  *                   only to |other|, and return false if not. */
453 bool
454 Bundle::connected_to (boost::shared_ptr<Bundle> other, AudioEngine & engine,
455                       DataType type, bool exclusive)
456 {
457         if (_ports_are_inputs == other->_ports_are_inputs)
458                 return false;
459
460         if (type == DataType::NIL) {
461                 for (DataType::iterator t = DataType::begin();
462                                         t != DataType::end(); ++t) {
463                         if (!connected_to(other, engine, *t, exclusive))
464                                 return false;
465                 }
466                 return true;
467         }
468
469         uint32_t N = nchannels().n(type);
470         if (other->nchannels().n(type) != N)
471                 return false;
472
473         vector<string> port_connections;
474
475         for (uint32_t i = 0; i < N; ++i) {
476                 Bundle::PortList const & our_ports =
477                         channel_ports (type_channel_to_overall(type, i));
478                 Bundle::PortList const & other_ports =
479                         other->channel_ports (other->type_channel_to_overall(type, i));
480
481                 for (Bundle::PortList::const_iterator j = our_ports.begin(); j != our_ports.end(); ++j) {
482
483                         boost::shared_ptr<Port> p = engine.get_port_by_name(*j);
484
485                         for (Bundle::PortList::const_iterator k = other_ports.begin();
486                                                            k != other_ports.end(); ++k) {
487                                 boost::shared_ptr<Port> q = engine.get_port_by_name(*k);
488
489                                 if (!p && !q) {
490                                         return false;
491                                 }
492
493                                 if (p && !p->connected_to (*k)) {
494                                         return false;
495                                 } else if (q && !q->connected_to (*j)) {
496                                         return false;
497                                 }
498                         }
499
500                         if (exclusive && p) {
501                                 port_connections.clear();
502                                 p->get_connections(port_connections);
503                                 if (port_connections.size() != other_ports.size())
504                                         return false;
505                         }
506                 }
507         }
508
509         return true;
510 }
511
512 /** This must not be called in code executed as a response to a backend event,
513  *  as it uses the backend port_get_all_connections().
514  *  @return true if any of this bundle's channels are connected to anything.
515  */
516 bool
517 Bundle::connected_to_anything (AudioEngine& engine)
518 {
519         PortManager& pm (engine);
520
521         for (uint32_t i = 0; i < n_total(); ++i) {
522                 Bundle::PortList const & ports = channel_ports (i);
523
524                 for (uint32_t j = 0; j < ports.size(); ++j) {
525
526                         /* ports[j] may not be an Ardour port, so use the port manager directly
527                            rather than doing it with Port.
528                         */
529
530                         if (pm.connected (ports[j])) {
531                                 return true;
532                         }
533                 }
534         }
535
536         return false;
537 }
538
539 void
540 Bundle::set_ports_are_inputs ()
541 {
542         _ports_are_inputs = true;
543         emit_changed (DirectionChanged);
544 }
545
546 void
547 Bundle::set_ports_are_outputs ()
548 {
549         _ports_are_inputs = false;
550         emit_changed (DirectionChanged);
551 }
552
553 /** Set the name.
554  *  @param n New name.
555  */
556 void
557 Bundle::set_name (string const & n)
558 {
559         _name = n;
560         emit_changed (NameChanged);
561 }
562
563 /** @param b Other bundle.
564  *  @return true if b has the same number of channels as this bundle, and those channels have corresponding ports.
565  */
566 bool
567 Bundle::has_same_ports (boost::shared_ptr<Bundle> b) const
568 {
569         ChanCount our_count = nchannels();
570         ChanCount other_count = b->nchannels();
571
572         if (our_count != other_count)
573                 return false;
574
575         for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
576                 uint32_t N = our_count.n(*t);
577                 for (uint32_t i = 0; i < N; ++i) {
578                         Bundle::PortList const & our_ports =
579                                 channel_ports (type_channel_to_overall(*t, i));
580                         Bundle::PortList const & other_ports =
581                                 b->channel_ports (b->type_channel_to_overall(*t, i));
582
583                         if (our_ports != other_ports)
584                                 return false;
585                 }
586         }
587
588         return true;
589 }
590
591 DataType
592 Bundle::channel_type (uint32_t c) const
593 {
594         assert (c < n_total());
595
596         Glib::Threads::Mutex::Lock lm (_channel_mutex);
597         return _channel[c].type;
598 }
599
600 ostream &
601 operator<< (ostream& os, Bundle const & b)
602 {
603         os << "BUNDLE " << b.nchannels() << " channels: ";
604         for (uint32_t i = 0; i < b.n_total(); ++i) {
605                 os << "( ";
606                 Bundle::PortList const & pl = b.channel_ports (i);
607                 for (Bundle::PortList::const_iterator j = pl.begin(); j != pl.end(); ++j) {
608                         os << *j << " ";
609                 }
610                 os << ") ";
611         }
612
613         return os;
614 }
615
616 bool
617 Bundle::operator== (Bundle const & other)
618 {
619         return _channel == other._channel;
620 }
621
622 /** Given an index of a channel as the nth channel of a particular type,
623  *  return an index of that channel when considering channels of all types.
624  *
625  *  e.g. given a bundle with channels:
626  *          fred   [audio]
627  *          jim    [audio]
628  *          sheila [midi]
629  *
630  * If t == MIDI and c == 0, then we would return 2, as 2 is the index of the
631  * 0th MIDI channel.
632  *
633  * If t == NIL, we just return c.
634  */
635
636 uint32_t
637 Bundle::type_channel_to_overall (DataType t, uint32_t c) const
638 {
639         if (t == DataType::NIL) {
640                 return c;
641         }
642
643         Glib::Threads::Mutex::Lock lm (_channel_mutex);
644
645         vector<Channel>::const_iterator i = _channel.begin ();
646
647         uint32_t o = 0;
648
649         while (1) {
650
651                 assert (i != _channel.end ());
652
653                 if (i->type != t) {
654                         ++i;
655                 } else {
656                         if (c == 0) {
657                                 return o;
658                         }
659                         --c;
660                 }
661
662                 ++o;
663         }
664
665         abort(); /* NOTREACHED */
666         return -1;
667 }
668
669 /** Perform the reverse of type_channel_to_overall */
670 uint32_t
671 Bundle::overall_channel_to_type (DataType t, uint32_t c) const
672 {
673         if (t == DataType::NIL) {
674                 return c;
675         }
676
677         Glib::Threads::Mutex::Lock lm (_channel_mutex);
678
679         uint32_t s = 0;
680
681         vector<Channel>::const_iterator i = _channel.begin ();
682         for (uint32_t j = 0; j < c; ++j) {
683                 if (i->type == t) {
684                         ++s;
685                 }
686                 ++i;
687         }
688
689         return s;
690 }