Create sidechain ports when created from template (#0007680)
[ardour.git] / libs / ardour / route_group.cc
1 /*
2     Copyright (C) 2000-2016 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <inttypes.h>
21
22 #include <algorithm>
23
24 #include "pbd/error.h"
25 #include "pbd/enumwriter.h"
26 #include "pbd/strsplit.h"
27 #include "pbd/types_convert.h"
28 #include "pbd/debug.h"
29
30 #include "ardour/amp.h"
31 #include "ardour/audio_track.h"
32 #include "ardour/debug.h"
33 #include "ardour/monitor_control.h"
34 #include "ardour/route.h"
35 #include "ardour/route_group.h"
36 #include "ardour/session.h"
37 #include "ardour/vca.h"
38 #include "ardour/vca_manager.h"
39
40 #include "pbd/i18n.h"
41
42 using namespace ARDOUR;
43 using namespace PBD;
44 using namespace std;
45
46 namespace ARDOUR {
47         namespace Properties {
48                 PropertyDescriptor<bool> active;
49                 PropertyDescriptor<bool> group_relative;
50                 PropertyDescriptor<bool> group_gain;
51                 PropertyDescriptor<bool> group_mute;
52                 PropertyDescriptor<bool> group_solo;
53                 PropertyDescriptor<bool> group_recenable;
54                 PropertyDescriptor<bool> group_select;
55                 PropertyDescriptor<bool> group_route_active;
56                 PropertyDescriptor<bool> group_color;
57                 PropertyDescriptor<bool> group_monitoring;
58                 PropertyDescriptor<int32_t> group_master_number;
59         }
60 }
61
62 void
63 RouteGroup::make_property_quarks ()
64 {
65         Properties::active.property_id = g_quark_from_static_string (X_("active"));
66         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for active = %1\n",      Properties::active.property_id));
67
68         Properties::group_relative.property_id = g_quark_from_static_string (X_("relative"));
69         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for relative = %1\n",    Properties::group_relative.property_id));
70         Properties::group_gain.property_id = g_quark_from_static_string (X_("gain"));
71         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for gain = %1\n",        Properties::group_gain.property_id));
72         Properties::group_mute.property_id = g_quark_from_static_string (X_("mute"));
73         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for mute = %1\n",        Properties::group_mute.property_id));
74         Properties::group_solo.property_id = g_quark_from_static_string (X_("solo"));
75         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for solo = %1\n",        Properties::group_solo.property_id));
76         Properties::group_recenable.property_id = g_quark_from_static_string (X_("recenable"));
77         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for recenable = %1\n",   Properties::group_recenable.property_id));
78         Properties::group_select.property_id = g_quark_from_static_string (X_("select"));
79         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for select = %1\n",      Properties::group_select.property_id));
80         Properties::group_route_active.property_id = g_quark_from_static_string (X_("route-active"));
81         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for route-active = %1\n", Properties::group_route_active.property_id));
82         Properties::group_color.property_id = g_quark_from_static_string (X_("color"));
83         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for color = %1\n", Properties::group_color.property_id));
84         Properties::group_monitoring.property_id = g_quark_from_static_string (X_("monitoring"));
85         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for monitoring = %1\n", Properties::group_monitoring.property_id));
86         Properties::group_master_number.property_id = g_quark_from_static_string (X_("group-master-number"));
87         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for group-master-number = %1\n", Properties::group_master_number.property_id));
88 }
89
90 #define ROUTE_GROUP_DEFAULT_PROPERTIES  _relative (Properties::group_relative, true) \
91         , _active (Properties::active, true) \
92         , _hidden (Properties::hidden, false) \
93         , _gain (Properties::group_gain, true) \
94         , _mute (Properties::group_mute, true) \
95         , _solo (Properties::group_solo, true) \
96         , _recenable (Properties::group_recenable, true) \
97         , _select (Properties::group_select, true) \
98         , _route_active (Properties::group_route_active, true) \
99         , _color (Properties::group_color, true) \
100         , _monitoring (Properties::group_monitoring, true) \
101         , _group_master_number (Properties::group_master_number, -1)
102
103 RouteGroup::RouteGroup (Session& s, const string &n)
104         : SessionObject (s, n)
105         , routes (new RouteList)
106         , ROUTE_GROUP_DEFAULT_PROPERTIES
107         , _solo_group (new ControlGroup (SoloAutomation))
108         , _mute_group (new ControlGroup (MuteAutomation))
109         , _rec_enable_group (new ControlGroup (RecEnableAutomation))
110         , _gain_group (new GainControlGroup ())
111         , _monitoring_group (new ControlGroup (MonitoringAutomation))
112         , _rgba (0)
113         , _used_to_share_gain (false)
114 {
115         _xml_node_name = X_("RouteGroup");
116
117         add_property (_relative);
118         add_property (_active);
119         add_property (_hidden);
120         add_property (_gain);
121         add_property (_mute);
122         add_property (_solo);
123         add_property (_recenable);
124         add_property (_select);
125         add_property (_route_active);
126         add_property (_color);
127         add_property (_monitoring);
128         add_property (_group_master_number);
129 }
130
131 RouteGroup::~RouteGroup ()
132 {
133         _solo_group->clear ();
134         _mute_group->clear ();
135         _gain_group->clear ();
136         _rec_enable_group->clear ();
137         _monitoring_group->clear ();
138
139         boost::shared_ptr<VCA> vca (group_master.lock());
140
141         for (RouteList::iterator i = routes->begin(); i != routes->end();) {
142                 RouteList::iterator tmp = i;
143                 ++tmp;
144
145                 (*i)->set_route_group (0);
146
147                 if (vca) {
148                         (*i)->unassign (vca);
149                 }
150
151                 i = tmp;
152         }
153 }
154
155 /** Add a route to a group.  Adding a route which is already in the group is allowed; nothing will happen.
156  *  @param r Route to add.
157  */
158 int
159 RouteGroup::add (boost::shared_ptr<Route> r)
160 {
161         if (r->is_master()) {
162                 return 0;
163         }
164
165         if (find (routes->begin(), routes->end(), r) != routes->end()) {
166                 return 0;
167         }
168
169         if (r->route_group()) {
170                 r->route_group()->remove (r);
171         }
172
173         routes->push_back (r);
174
175         _solo_group->add_control (r->solo_control());
176         _mute_group->add_control (r->mute_control());
177         _gain_group->add_control (r->gain_control());
178         boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (r);
179         if (trk) {
180                 _rec_enable_group->add_control (trk->rec_enable_control());
181                 _monitoring_group->add_control (trk->monitoring_control());
182         }
183
184         r->set_route_group (this);
185         r->DropReferences.connect_same_thread (*this, boost::bind (&RouteGroup::remove_when_going_away, this, boost::weak_ptr<Route> (r)));
186
187         boost::shared_ptr<VCA> vca (group_master.lock());
188
189         if (vca) {
190                 r->assign (vca);
191         }
192
193         _session.set_dirty ();
194         RouteAdded (this, boost::weak_ptr<Route> (r)); /* EMIT SIGNAL */
195         return 0;
196 }
197
198 void
199 RouteGroup::remove_when_going_away (boost::weak_ptr<Route> wr)
200 {
201         boost::shared_ptr<Route> r (wr.lock());
202
203         if (r) {
204                 remove (r);
205         }
206 }
207
208 int
209 RouteGroup::remove (boost::shared_ptr<Route> r)
210 {
211         RouteList::iterator i;
212
213         if ((i = find (routes->begin(), routes->end(), r)) != routes->end()) {
214                 r->set_route_group (0);
215
216                 boost::shared_ptr<VCA> vca = group_master.lock();
217
218                 if (vca) {
219                         r->unassign (vca);
220                 }
221
222                 _solo_group->remove_control (r->solo_control());
223                 _mute_group->remove_control (r->mute_control());
224                 _gain_group->remove_control (r->gain_control());
225                 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (r);
226                 if (trk) {
227                         _rec_enable_group->remove_control (trk->rec_enable_control());
228                         _monitoring_group->remove_control (trk->monitoring_control());
229                 }
230                 routes->erase (i);
231                 _session.set_dirty ();
232                 RouteRemoved (this, boost::weak_ptr<Route> (r)); /* EMIT SIGNAL */
233                 return 0;
234         }
235
236         return -1;
237 }
238
239 void
240 RouteGroup::set_rgba (uint32_t color) {
241         _rgba = color;
242
243         PBD::PropertyChange change;
244         change.add (Properties::color);
245         PropertyChanged (change);
246
247         if (!is_color ()) {
248                 return;
249         }
250
251         for (RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
252                 (*i)->presentation_info().PropertyChanged (Properties::color);
253         }
254 }
255
256 XMLNode&
257 RouteGroup::get_state ()
258 {
259         XMLNode *node = new XMLNode ("RouteGroup");
260
261         node->set_property ("id", id());
262         node->set_property ("rgba", _rgba);
263         node->set_property ("used-to-share-gain", _used_to_share_gain);
264         if (_subgroup_bus) {
265                 node->set_property ("subgroup-bus", _subgroup_bus->id ());
266         }
267
268         add_properties (*node);
269
270         if (!routes->empty()) {
271                 stringstream str;
272
273                 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
274                         str << (*i)->id () << ' ';
275                 }
276
277                 node->set_property ("routes", str.str());
278         }
279
280         return *node;
281 }
282
283 int
284 RouteGroup::set_state (const XMLNode& node, int version)
285 {
286         if (version < 3000) {
287                 return set_state_2X (node, version);
288         }
289
290         set_id (node);
291         set_values (node);
292         node.get_property ("rgba", _rgba);
293         node.get_property ("used-to-share-gain", _used_to_share_gain);
294
295         std::string routes;
296         if (node.get_property ("routes", routes)) {
297                 stringstream str (routes);
298                 vector<string> ids;
299                 split (str.str(), ids, ' ');
300
301                 for (vector<string>::iterator i = ids.begin(); i != ids.end(); ++i) {
302                         PBD::ID id (*i);
303                         boost::shared_ptr<Route> r = _session.route_by_id (id);
304
305                         if (r) {
306                                 add (r);
307                         }
308                 }
309         }
310
311         PBD::ID subgroup_id (0);
312         if (node.get_property ("subgroup-bus", subgroup_id)) {
313                 boost::shared_ptr<Route> r = _session.route_by_id (subgroup_id);
314                 if (r) {
315                         _subgroup_bus = r;
316                 }
317         }
318
319         if (_group_master_number.val() > 0) {
320                 boost::shared_ptr<VCA> vca = _session.vca_manager().vca_by_number (_group_master_number.val());
321                 if (vca) {
322                         /* no need to do the assignment because slaves will
323                            handle that themselves. But we can set group_master
324                            to use with future assignments of newly added routes.
325                         */
326                         group_master = vca;
327                 }
328         }
329
330         push_to_groups ();
331
332         return 0;
333 }
334
335 int
336 RouteGroup::set_state_2X (const XMLNode& node, int /*version*/)
337 {
338         set_values (node);
339
340         if (node.name() == "MixGroup") {
341                 _gain = true;
342                 _mute = true;
343                 _solo = true;
344                 _recenable = true;
345                 _route_active = true;
346                 _color = false;
347         } else if (node.name() == "EditGroup") {
348                 _gain = false;
349                 _mute = false;
350                 _solo = false;
351                 _recenable = false;
352                 _route_active = false;
353                 _color = false;
354         }
355
356         push_to_groups ();
357
358         return 0;
359 }
360
361 void
362 RouteGroup::set_gain (bool yn)
363 {
364         if (is_gain() == yn) {
365                 return;
366         }
367
368         _gain = yn;
369         _gain_group->set_active (yn);
370
371         send_change (PropertyChange (Properties::group_gain));
372 }
373
374 void
375 RouteGroup::set_mute (bool yn)
376 {
377         if (is_mute() == yn) {
378                 return;
379         }
380         _mute = yn;
381         _mute_group->set_active (yn);
382
383         send_change (PropertyChange (Properties::group_mute));
384 }
385
386 void
387 RouteGroup::set_solo (bool yn)
388 {
389         if (is_solo() == yn) {
390                 return;
391         }
392         _solo = yn;
393         _solo_group->set_active (yn);
394
395         send_change (PropertyChange (Properties::group_solo));
396 }
397
398 void
399 RouteGroup::set_recenable (bool yn)
400 {
401         if (is_recenable() == yn) {
402                 return;
403         }
404         _recenable = yn;
405         _rec_enable_group->set_active (yn);
406         send_change (PropertyChange (Properties::group_recenable));
407 }
408
409 void
410 RouteGroup::set_select (bool yn)
411 {
412         if (is_select() == yn) {
413                 return;
414         }
415         _select = yn;
416         send_change (PropertyChange (Properties::group_select));
417 }
418
419 void
420 RouteGroup::set_route_active (bool yn)
421 {
422         if (is_route_active() == yn) {
423                 return;
424         }
425         _route_active = yn;
426         send_change (PropertyChange (Properties::group_route_active));
427 }
428
429 void
430 RouteGroup::set_color (bool yn)
431 {
432         if (is_color() == yn) {
433                 return;
434         }
435         _color = yn;
436
437         send_change (PropertyChange (Properties::group_color));
438
439         /* This is a bit of a hack, but this might change
440            our route's effective color, so emit gui_changed
441            for our routes.
442         */
443
444         for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
445                 (*i)->gui_changed (X_("color"), this);
446         }
447 }
448
449 void
450 RouteGroup::set_monitoring (bool yn)
451 {
452         if (is_monitoring() == yn) {
453                 return;
454         }
455
456         _monitoring = yn;
457         _monitoring_group->set_active (yn);
458
459         send_change (PropertyChange (Properties::group_monitoring));
460
461         _session.set_dirty ();
462 }
463
464 void
465 RouteGroup::set_active (bool yn, void* /*src*/)
466 {
467         if (is_active() == yn) {
468                 return;
469         }
470
471         _active = yn;
472
473         push_to_groups ();
474
475         send_change (PropertyChange (Properties::active));
476         _session.set_dirty ();
477 }
478
479 void
480 RouteGroup::set_relative (bool yn, void* /*src*/)
481 {
482         if (is_relative() == yn) {
483                 return;
484         }
485
486         _relative = yn;
487
488         push_to_groups ();
489
490         send_change (PropertyChange (Properties::group_relative));
491         _session.set_dirty ();
492 }
493
494 void
495 RouteGroup::set_hidden (bool yn, void* /*src*/)
496 {
497         if (is_hidden() == yn) {
498                 return;
499         }
500
501         if (yn) {
502                 _hidden = true;
503                 if (Config->get_hiding_groups_deactivates_groups()) {
504                         _active = false;
505                 }
506         } else {
507                 _hidden = false;
508                 if (Config->get_hiding_groups_deactivates_groups()) {
509                         _active = true;
510                 }
511         }
512
513         send_change (Properties::hidden);
514
515         _session.set_dirty ();
516 }
517
518 void
519 RouteGroup::audio_track_group (set<boost::shared_ptr<AudioTrack> >& ats)
520 {
521         for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
522                 boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(*i);
523                 if (at) {
524                         ats.insert (at);
525                 }
526         }
527 }
528
529 void
530 RouteGroup::make_subgroup (bool aux, Placement placement)
531 {
532         RouteList rl;
533         uint32_t nin = 0;
534
535         /* since we don't do MIDI Busses yet, check quickly ... */
536
537         for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
538                 if ((*i)->output()->n_ports().n_midi() != 0) {
539                         PBD::warning << _("You cannot subgroup MIDI tracks at this time") << endmsg;
540                         return;
541                 }
542         }
543
544         for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
545                 if (!aux && nin != 0 && nin != (*i)->output()->n_ports().n_audio()) {
546                         PBD::warning << _("You cannot subgroup tracks with different number of outputs at this time.") << endmsg;
547                         return;
548                 }
549                 nin = max (nin, (*i)->output()->n_ports().n_audio());
550         }
551
552         try {
553                 /* use master bus etc. to determine default nouts.
554                  *
555                  * (since tracks can't have fewer outs than ins,
556                  * "nin" currently defines the number of outpus if nin > 2)
557                  */
558                 rl = _session.new_audio_route (nin, 2, 0, 1, string(), PresentationInfo::AudioBus, PresentationInfo::max_order);
559         } catch (...) {
560                 return;
561         }
562
563         _subgroup_bus = rl.front();
564         _subgroup_bus->set_name (_name);
565
566         if (aux) {
567
568                 _session.add_internal_sends (_subgroup_bus, placement, routes);
569
570         } else {
571
572                 boost::shared_ptr<Bundle> bundle = _subgroup_bus->input()->bundle ();
573
574                 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
575                         (*i)->output()->disconnect (this);
576                         (*i)->output()->connect_ports_to_bundle (bundle, false, this);
577                 }
578         }
579 }
580
581 void
582 RouteGroup::destroy_subgroup ()
583 {
584         if (!_subgroup_bus) {
585                 return;
586         }
587
588         for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
589                 (*i)->output()->disconnect (this);
590                 /* XXX find a new bundle to connect to */
591         }
592
593         _session.remove_route (_subgroup_bus);
594         _subgroup_bus.reset ();
595 }
596
597 bool
598 RouteGroup::has_subgroup() const
599 {
600         return _subgroup_bus != 0;
601 }
602
603 bool
604 RouteGroup::enabled_property (PBD::PropertyID prop)
605 {
606         OwnedPropertyList::iterator i = _properties->find (prop);
607         if (i == _properties->end()) {
608                 return false;
609         }
610
611         return dynamic_cast<const PropertyTemplate<bool>* > (i->second)->val ();
612 }
613
614 void
615 RouteGroup::post_set (PBD::PropertyChange const &)
616 {
617         push_to_groups ();
618 }
619
620 void
621 RouteGroup::push_to_groups ()
622 {
623         if (is_relative()) {
624                 _gain_group->set_mode (ControlGroup::Mode (_gain_group->mode()|ControlGroup::Relative));
625         } else {
626                 _gain_group->set_mode (ControlGroup::Mode (_gain_group->mode()&~ControlGroup::Relative));
627         }
628
629         if (_active) {
630                 _gain_group->set_active (is_gain());
631                 _solo_group->set_active (is_solo());
632                 _mute_group->set_active (is_mute());
633                 _rec_enable_group->set_active (is_recenable());
634                 _monitoring_group->set_active (is_monitoring());
635         } else {
636                 _gain_group->set_active (false);
637                 _solo_group->set_active (false);
638                 _mute_group->set_active (false);
639
640                 _rec_enable_group->set_active (false);
641                 _monitoring_group->set_active (false);
642         }
643 }
644
645 void
646 RouteGroup::assign_master (boost::shared_ptr<VCA> master)
647 {
648         if (!routes || routes->empty()) {
649                 return;
650         }
651
652         boost::shared_ptr<Route> front = routes->front ();
653
654         if (front->slaved_to (master)) {
655                 return;
656         }
657
658         for (RouteList::iterator r = routes->begin(); r != routes->end(); ++r) {
659                 (*r)->assign (master);
660         }
661
662         group_master = master;
663         _group_master_number = master->number();
664
665         _used_to_share_gain = is_gain ();
666         set_gain (false);
667 }
668
669 void
670 RouteGroup::unassign_master (boost::shared_ptr<VCA> master)
671 {
672         if (!routes || routes->empty()) {
673                 return;
674         }
675
676         boost::shared_ptr<Route> front = routes->front ();
677
678         if (!front->slaved_to (master)) {
679                 return;
680         }
681
682         for (RouteList::iterator r = routes->begin(); r != routes->end(); ++r) {
683                 (*r)->unassign (master);
684         }
685
686         group_master.reset ();
687         _group_master_number = -1;
688
689         set_gain (_used_to_share_gain);
690 }
691
692 bool
693 RouteGroup::slaved () const
694 {
695         if (!routes || routes->empty()) {
696                 return false;
697         }
698
699         return routes->front()->slaved ();
700 }
701
702 bool
703 RouteGroup::has_control_master() const
704 {
705         return group_master.lock() != 0;
706 }