ardour
route_group.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000-2009 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 
28 #include "ardour/amp.h"
29 #include "ardour/audio_track.h"
30 #include "ardour/route.h"
31 #include "ardour/route_group.h"
32 #include "ardour/session.h"
33 
34 #include "i18n.h"
35 
36 using namespace ARDOUR;
37 using namespace PBD;
38 using namespace std;
39 
40 namespace ARDOUR {
41  namespace Properties {
52  }
53 }
54 
55 void
57 {
58  Properties::relative.property_id = g_quark_from_static_string (X_("relative"));
59  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for relative = %1\n", Properties::relative.property_id));
60  Properties::active.property_id = g_quark_from_static_string (X_("active"));
61  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for active = %1\n", Properties::active.property_id));
62  Properties::hidden.property_id = g_quark_from_static_string (X_("hidden"));
63  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for hidden = %1\n", Properties::hidden.property_id));
64  Properties::gain.property_id = g_quark_from_static_string (X_("gain"));
65  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for gain = %1\n", Properties::gain.property_id));
66  Properties::mute.property_id = g_quark_from_static_string (X_("mute"));
67  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for mute = %1\n", Properties::mute.property_id));
68  Properties::solo.property_id = g_quark_from_static_string (X_("solo"));
69  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for solo = %1\n", Properties::solo.property_id));
70  Properties::recenable.property_id = g_quark_from_static_string (X_("recenable"));
71  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for recenable = %1\n", Properties::recenable.property_id));
72  Properties::select.property_id = g_quark_from_static_string (X_("select"));
73  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for select = %1\n", Properties::select.property_id));
74  Properties::route_active.property_id = g_quark_from_static_string (X_("route-active"));
75  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for route-active = %1\n", Properties::route_active.property_id));
76  Properties::color.property_id = g_quark_from_static_string (X_("color"));
77  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for color = %1\n", Properties::color.property_id));
78  Properties::monitoring.property_id = g_quark_from_static_string (X_("monitoring"));
79  DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for monitoring = %1\n", Properties::monitoring.property_id));
80 }
81 
82 #define ROUTE_GROUP_DEFAULT_PROPERTIES _relative (Properties::relative, true) \
83  , _active (Properties::active, false) \
84  , _hidden (Properties::hidden, false) \
85  , _gain (Properties::gain, false) \
86  , _mute (Properties::mute, false) \
87  , _solo (Properties::solo, false) \
88  , _recenable (Properties::recenable, false) \
89  , _select (Properties::select, false) \
90  , _route_active (Properties::route_active, false) \
91  , _color (Properties::color, false) \
92  , _monitoring (Properties::monitoring, false)
93 
94 RouteGroup::RouteGroup (Session& s, const string &n)
95  : SessionObject (s, n)
96  , routes (new RouteList)
98 {
99  _xml_node_name = X_("RouteGroup");
100 
101  add_property (_relative);
102  add_property (_active);
103  add_property (_hidden);
104  add_property (_gain);
105  add_property (_mute);
106  add_property (_solo);
107  add_property (_recenable);
108  add_property (_select);
109  add_property (_route_active);
110  add_property (_color);
111  add_property (_monitoring);
112 }
113 
114 RouteGroup::~RouteGroup ()
115 {
116  for (RouteList::iterator i = routes->begin(); i != routes->end();) {
117  RouteList::iterator tmp = i;
118  ++tmp;
119 
120  (*i)->set_route_group (0);
121 
122  i = tmp;
123  }
124 }
125 
129 int
131 {
132  if (find (routes->begin(), routes->end(), r) != routes->end()) {
133  return 0;
134  }
135 
136  if (r->route_group()) {
137  r->route_group()->remove (r);
138  }
139 
140  routes->push_back (r);
141 
142  r->set_route_group (this);
143  r->DropReferences.connect_same_thread (*this, boost::bind (&RouteGroup::remove_when_going_away, this, boost::weak_ptr<Route> (r)));
144 
145  _session.set_dirty ();
146  RouteAdded (this, boost::weak_ptr<Route> (r)); /* EMIT SIGNAL */
147  return 0;
148 }
149 
150 void
152 {
153  boost::shared_ptr<Route> r (wr.lock());
154 
155  if (r) {
156  remove (r);
157  }
158 }
159 
160 int
162 {
163  RouteList::iterator i;
164 
165  if ((i = find (routes->begin(), routes->end(), r)) != routes->end()) {
166  r->set_route_group (0);
167  routes->erase (i);
168  _session.set_dirty ();
169  RouteRemoved (this, boost::weak_ptr<Route> (r)); /* EMIT SIGNAL */
170  return 0;
171  }
172 
173  return -1;
174 }
175 
176 
177 gain_t
179 {
180  for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
181  gain_t const g = (*i)->amp()->gain();
182 
183  if ((g + g * factor) >= 0.0f) {
184  continue;
185  }
186 
187  if (g <= 0.0000003f) {
188  return 0.0f;
189  }
190 
191  factor = 0.0000003f / g - 1.0f;
192  }
193 
194  return factor;
195 }
196 
197 gain_t
199 {
200  for (RouteList::iterator i = routes->begin(); i != routes->end(); i++) {
201  gain_t const g = (*i)->amp()->gain();
202 
203  // if the current factor woulnd't raise this route above maximum
204  if ((g + g * factor) <= 1.99526231f) {
205  continue;
206  }
207 
208  // if route gain is already at peak, return 0.0f factor
209  if (g >= 1.99526231f) {
210  return 0.0f;
211  }
212 
213  // factor is calculated so that it would raise current route to max
214  factor = 1.99526231f / g - 1.0f;
215  }
216 
217  return factor;
218 }
219 
220 XMLNode&
222 {
223  XMLNode *node = new XMLNode ("RouteGroup");
224 
225  char buf[64];
226  id().print (buf, sizeof (buf));
227  node->add_property ("id", buf);
228 
229  add_properties (*node);
230 
231  if (!routes->empty()) {
232  stringstream str;
233 
234  for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
235  str << (*i)->id () << ' ';
236  }
237 
238  node->add_property ("routes", str.str());
239  }
240 
241  return *node;
242 }
243 
244 int
245 RouteGroup::set_state (const XMLNode& node, int version)
246 {
247  if (version < 3000) {
248  return set_state_2X (node, version);
249  }
250 
251  const XMLProperty *prop;
252 
253  set_id (node);
254  set_values (node);
255 
256  if ((prop = node.property ("routes")) != 0) {
257  stringstream str (prop->value());
258  vector<string> ids;
259  split (str.str(), ids, ' ');
260 
261  for (vector<string>::iterator i = ids.begin(); i != ids.end(); ++i) {
262  PBD::ID id (*i);
264 
265  if (r) {
266  add (r);
267  }
268  }
269  }
270 
271  return 0;
272 }
273 
274 int
275 RouteGroup::set_state_2X (const XMLNode& node, int /*version*/)
276 {
277  set_values (node);
278 
279  if (node.name() == "MixGroup") {
280  _gain = true;
281  _mute = true;
282  _solo = true;
283  _recenable = true;
284  _route_active = true;
285  _color = false;
286  } else if (node.name() == "EditGroup") {
287  _gain = false;
288  _mute = false;
289  _solo = false;
290  _recenable = false;
291  _route_active = false;
292  _color = false;
293  }
294 
295  return 0;
296 }
297 
298 void
300 {
301  if (is_gain() == yn) {
302  return;
303  }
304  _gain = yn;
306 }
307 
308 void
310 {
311  if (is_mute() == yn) {
312  return;
313  }
314  _mute = yn;
316 }
317 
318 void
320 {
321  if (is_solo() == yn) {
322  return;
323  }
324  _solo = yn;
326 }
327 
328 void
330 {
331  if (is_recenable() == yn) {
332  return;
333  }
334  _recenable = yn;
336 }
337 
338 void
340 {
341  if (is_select() == yn) {
342  return;
343  }
344  _select = yn;
346 }
347 
348 void
350 {
351  if (is_route_active() == yn) {
352  return;
353  }
354  _route_active = yn;
356 }
357 
358 void
360 {
361  if (is_color() == yn) {
362  return;
363  }
364  _color = yn;
365 
367 
368  /* This is a bit of a hack, but this might change
369  our route's effective color, so emit gui_changed
370  for our routes.
371  */
372 
373  for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
374  (*i)->gui_changed (X_("color"), this);
375  }
376 }
377 
378 void
380 {
381  if (is_monitoring() == yn) {
382  return;
383  }
384 
385  _monitoring = yn;
387 
388  _session.set_dirty ();
389 }
390 
391 void
392 RouteGroup::set_active (bool yn, void* /*src*/)
393 {
394  if (is_active() == yn) {
395  return;
396  }
397 
398  _active = yn;
400  _session.set_dirty ();
401 }
402 
403 void
404 RouteGroup::set_relative (bool yn, void* /*src*/)
405 {
406  if (is_relative() == yn) {
407  return;
408  }
409  _relative = yn;
411  _session.set_dirty ();
412 }
413 
414 void
415 RouteGroup::set_hidden (bool yn, void* /*src*/)
416 {
417  if (is_hidden() == yn) {
418  return;
419  }
420 
421  if (yn) {
422  _hidden = true;
423  if (Config->get_hiding_groups_deactivates_groups()) {
424  _active = false;
425  }
426  } else {
427  _hidden = false;
428  if (Config->get_hiding_groups_deactivates_groups()) {
429  _active = true;
430  }
431  }
432 
434 
435  _session.set_dirty ();
436 }
437 
438 void
440 {
441  for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
443  if (at) {
444  ats.insert (at);
445  }
446  }
447 }
448 
449 void
451 {
452  RouteList rl;
453  uint32_t nin = 0;
454 
455  /* since we don't do MIDI Busses yet, check quickly ... */
456 
457  for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
458  if ((*i)->output()->n_ports().n_midi() != 0) {
459  PBD::info << _("You cannot subgroup MIDI tracks at this time") << endmsg;
460  return;
461  }
462  }
463 
464  for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
465  nin = max (nin, (*i)->output()->n_ports().n_audio());
466  }
467 
468  try {
469  /* use master bus etc. to determine default nouts */
470  rl = _session.new_audio_route (nin, 2, 0, 1);
471  } catch (...) {
472  return;
473  }
474 
475  subgroup_bus = rl.front();
477 
478  if (aux) {
479 
481 
482  } else {
483 
484  boost::shared_ptr<Bundle> bundle = subgroup_bus->input()->bundle ();
485 
486  for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
487  (*i)->output()->disconnect (this);
488  (*i)->output()->connect_ports_to_bundle (bundle, false, this);
489  }
490  }
491 }
492 
493 void
495 {
496  if (!subgroup_bus) {
497  return;
498  }
499 
500  for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
501  (*i)->output()->disconnect (this);
502  /* XXX find a new bundle to connect to */
503  }
504 
506  subgroup_bus.reset ();
507 }
508 
509 bool
511 {
512  return subgroup_bus != 0;
513 }
514 
515 bool
517 {
518  OwnedPropertyList::iterator i = _properties->find (prop);
519  if (i == _properties->end()) {
520  return false;
521  }
522 
523  return dynamic_cast<const PropertyTemplate<bool>* > (i->second)->val ();
524 }
gain_t get_max_factor(gain_t factor)
Definition: route_group.cc:198
ARDOUR::Session & _session
PBD::Property< bool > _solo
Definition: route_group.h:146
virtual void send_change(const PropertyChange &)
Definition: stateful.cc:278
PBD::Signal0< void > DropReferences
Definition: destructible.h:34
void set_gain(bool yn)
Definition: route_group.cc:299
bool is_mute() const
Definition: route_group.h:70
void add_internal_sends(boost::shared_ptr< Route > dest, Placement p, boost::shared_ptr< RouteList > senders)
Definition: session.cc:2840
const std::string & value() const
Definition: xml++.h:159
boost::shared_ptr< Route > route_by_id(PBD::ID)
Definition: session.cc:3338
void set_recenable(bool yn)
Definition: route_group.cc:329
bool is_gain() const
Definition: route_group.h:69
void set_mute(bool yn)
Definition: route_group.cc:309
int set_state(const XMLNode &, int version)
Definition: route_group.cc:245
void audio_track_group(std::set< boost::shared_ptr< AudioTrack > > &at_set)
Definition: route_group.cc:439
LIBARDOUR_API PBD::PropertyDescriptor< bool > hidden
Definition: route_group.h:50
bool is_select() const
Definition: route_group.h:73
LIBPBD_API void split(std::string, std::vector< std::string > &, char)
void set_monitoring(bool yn)
Definition: route_group.cc:379
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
const std::string & name() const
Definition: xml++.h:104
bool has_subgroup() const
Definition: route_group.cc:510
tuple f
Definition: signals.py:35
Definition: Beats.hpp:239
LIBARDOUR_API PBD::PropertyDescriptor< bool > gain
Definition: route_group.cc:44
void set_route_active(bool yn)
Definition: route_group.cc:349
bool set_name(const std::string &str)
Definition: route.cc:3870
PBD::Signal2< void, RouteGroup *, boost::weak_ptr< ARDOUR::Route > > RouteRemoved
Definition: route_group.h:131
void add_properties(XMLNode &)
Definition: stateful.cc:264
float gain_t
Definition: types.h:58
bool is_hidden() const
Definition: route_group.h:68
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
PropertyChange set_values(XMLNode const &)
Definition: stateful.cc:209
void remove_route(boost::shared_ptr< Route >)
Definition: session.cc:2870
OwnedPropertyList * _properties
Definition: stateful.h:117
Definition: id.h:32
PBD::Property< bool > _recenable
Definition: route_group.h:147
void set_select(bool yn)
Definition: route_group.cc:339
PBD::Property< bool > _active
Definition: route_group.h:142
#define _(Text)
Definition: i18n.h:11
GQuark PropertyID
void set_relative(bool yn, void *src)
Definition: route_group.cc:404
PBD::Property< bool > _route_active
Definition: route_group.h:149
PBD::Property< bool > _hidden
Definition: route_group.h:143
void make_subgroup(bool, Placement)
Definition: route_group.cc:450
#define X_(Text)
Definition: i18n.h:13
boost::shared_ptr< RouteList > routes
Definition: route_group.h:138
XMLProperty * property(const char *)
Definition: xml++.cc:413
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
LIBARDOUR_API PBD::PropertyDescriptor< bool > recenable
Definition: route_group.cc:47
#define ROUTE_GROUP_DEFAULT_PROPERTIES
Definition: route_group.cc:82
LIBARDOUR_API PBD::PropertyDescriptor< bool > route_active
Definition: route_group.cc:49
int remove(boost::shared_ptr< Route >)
Definition: route_group.cc:161
Definition: amp.h:29
const PBD::ID & id() const
Definition: stateful.h:68
bool is_active() const
Definition: route_group.h:66
void print(char *buf, uint32_t bufsize) const
Definition: id.cc:73
bool set_id(const XMLNode &)
Definition: stateful.cc:381
bool enabled_property(PBD::PropertyID)
Definition: route_group.cc:516
bool is_route_active() const
Definition: route_group.h:74
PBD::Property< bool > _relative
Definition: route_group.h:141
bool is_recenable() const
Definition: route_group.h:72
void remove_when_going_away(boost::weak_ptr< Route >)
Definition: route_group.cc:151
PBD::Property< bool > _color
Definition: route_group.h:150
boost::shared_ptr< Route > subgroup_bus
Definition: route_group.h:139
static void make_property_quarks()
Definition: route_group.cc:56
LIBARDOUR_API PBD::PropertyDescriptor< bool > mute
Definition: route_group.cc:45
void set_hidden(bool yn, void *src)
Definition: route_group.cc:415
#define DEBUG_TRACE(bits, str)
Definition: debug.h:55
RouteGroup::RouteGroup(Session &s, const string &n) add_property(_relative)
Definition: route_group.cc:101
RouteList new_audio_route(int input_channels, int output_channels, RouteGroup *route_group, uint32_t how_many, std::string name_template="")
Definition: session.cc:2454
PBD::Property< std::string > _name
PBD::Property< bool > _select
Definition: route_group.h:148
LIBPBD_API Transmitter info
LIBARDOUR_API PBD::PropertyDescriptor< bool > active
Definition: route_group.cc:43
LIBPBD_API uint64_t Properties
Definition: debug.cc:47
void set_solo(bool yn)
Definition: route_group.cc:319
XMLProperty * add_property(const char *name, const std::string &value)
RouteGroup(Session &s, const std::string &n)
int set_state_2X(const XMLNode &, int)
Definition: route_group.cc:275
bool is_monitoring() const
Definition: route_group.h:76
bool is_solo() const
Definition: route_group.h:71
PBD::Property< bool > _gain
Definition: route_group.h:144
LIBARDOUR_API PBD::PropertyDescriptor< bool > solo
Definition: route_group.cc:46
LIBARDOUR_API PBD::PropertyDescriptor< bool > relative
Definition: route_group.cc:42
Definition: xml++.h:95
RouteGroup * route_group() const
bool is_color() const
Definition: route_group.h:75
bool is_relative() const
Definition: route_group.h:67
PBD::Signal2< void, RouteGroup *, boost::weak_ptr< ARDOUR::Route > > RouteAdded
Definition: route_group.h:129
LIBARDOUR_API PBD::PropertyDescriptor< bool > select
Definition: route_group.cc:48
Definition: debug.h:30
int add(boost::shared_ptr< Route >)
Definition: route_group.cc:130
boost::shared_ptr< IO > input() const
Definition: route.h:89
void set_color(bool yn)
Definition: route_group.cc:359
PBD::Property< bool > _mute
Definition: route_group.h:145
gain_t get_min_factor(gain_t factor)
Definition: route_group.cc:178
std::list< boost::shared_ptr< Route > > RouteList
Definition: types.h:532
void set_active(bool yn, void *src)
Definition: route_group.cc:392
Placement
Definition: types.h:375
XMLNode & get_state()
Definition: route_group.cc:221
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
PBD::Property< bool > _monitoring
Definition: route_group.h:151
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50
LIBARDOUR_API PBD::PropertyDescriptor< bool > monitoring
Definition: route_group.cc:51