ardour
group_tabs.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 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 <gtkmm/stock.h>
21 #include "ardour/session.h"
22 #include "ardour/route_group.h"
23 #include "ardour/route.h"
24 
25 #include "gui_thread.h"
26 #include "route_group_dialog.h"
27 #include "global_signals.h"
28 #include "group_tabs.h"
29 #include "keyboard.h"
30 #include "i18n.h"
31 #include "ardour_ui.h"
32 #include "rgb_macros.h"
33 #include "utils.h"
34 
35 using namespace std;
36 using namespace Gtk;
37 using namespace ARDOUR;
38 using namespace ARDOUR_UI_UTILS;
40 
41 list<Gdk::Color> GroupTabs::_used_colors;
42 
44  : _menu (0)
45  , _dragging (0)
46  , _dragging_new_tab (0)
47 {
48  add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
49  ColorsChanged.connect (sigc::mem_fun (*this, &GroupTabs::queue_draw));
50 }
51 
53 {
54  delete _menu;
55 }
56 
57 void
59 {
60  SessionHandlePtr::set_session (s);
61 
62  if (_session) {
65  );
68  );
71  );
72 
74  }
75 }
76 
77 
81 void
82 GroupTabs::on_size_request (Gtk::Requisition *req)
83 {
84  /* Use a dummy, small width and the actual height that we want */
85  req->width = 16;
86  req->height = 16;
87 }
88 
89 bool
91 {
92  using namespace Menu_Helpers;
93 
94  double const p = primary_coordinate (ev->x, ev->y);
95 
96  list<Tab>::iterator prev;
97  list<Tab>::iterator next;
98  Tab* t = click_to_tab (p, &prev, &next);
99 
100  _drag_min = prev != _tabs.end() ? prev->to : 0;
101  _drag_max = next != _tabs.end() ? next->from : extent ();
102 
103  if (ev->button == 1) {
104 
105  if (t == 0) {
106  Tab n;
107  n.from = n.to = p;
108  _dragging_new_tab = true;
109 
110  if (next == _tabs.end()) {
111  _tabs.push_back (n);
112  t = &_tabs.back ();
113  } else {
114  list<Tab>::iterator j = _tabs.insert (next, n);
115  t = &(*j);
116  }
117 
118  } else {
119  _dragging_new_tab = false;
121  }
122 
123  _dragging = t;
124  _drag_moved = false;
125  _drag_first = p;
126 
127  double const h = (t->from + t->to) / 2;
128  if (p < h) {
129  _drag_moving = t->from;
130  _drag_fixed = t->to;
131  _drag_offset = p - t->from;
132  } else {
133  _drag_moving = t->to;
134  _drag_fixed = t->from;
135  _drag_offset = p - t->to;
136  }
137 
138  } else if (ev->button == 3) {
139 
140  RouteGroup* g = t ? t->group : 0;
141 
142  if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier) && g) {
143  /* edit */
144  RouteGroupDialog d (g, false);
145  d.do_run ();
146  } else {
147  Menu* m = get_menu (g);
148  if (m) {
149  m->popup (ev->button, ev->time);
150  }
151  }
152  }
153 
154  return true;
155 }
156 
157 
158 bool
160 {
161  if (_dragging == 0) {
162  return false;
163  }
164 
165  double const p = primary_coordinate (ev->x, ev->y);
166 
167  if (p != _drag_first) {
168  _drag_moved = true;
169  }
170 
172 
175 
177  _dragging->to = min (_dragging->to, _drag_max);
178 
179  set_dirty ();
180  queue_draw ();
181 
182  gdk_event_request_motions(ev);
183 
184  return true;
185 }
186 
187 
188 bool
190 {
191  if (_dragging == 0) {
192  return false;
193  }
194 
195  if (!_drag_moved) {
196 
197  if (_dragging->group) {
198  /* toggle active state */
200  }
201 
202  } else {
203  /* finish drag */
205 
206  if (!routes.empty()) {
207  if (_dragging_new_tab) {
209  if (g) {
210  for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
211  g->add (*i);
212  }
213  }
214  } else {
216  for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
217 
218  bool const was_in_tab = find (
220  ) != _initial_dragging_routes.end ();
221 
222  bool const now_in_tab = find (routes.begin(), routes.end(), *i) != routes.end();
223 
224  if (was_in_tab && !now_in_tab) {
225  _dragging->group->remove (*i);
226  } else if (!was_in_tab && now_in_tab) {
227  _dragging->group->add (*i);
228  }
229  }
230  }
231  }
232 
233  set_dirty ();
234  queue_draw ();
235  }
236 
237  _dragging = 0;
238  _initial_dragging_routes.clear ();
239 
240  return true;
241 }
242 
243 void
244 GroupTabs::render (cairo_t* cr, cairo_rectangle_t*)
245 {
246  if (_dragging == 0) {
247  _tabs = compute_tabs ();
248  }
249 
250  /* background */
251 
252  Gdk::Color c = get_style()->get_base (Gtk::STATE_NORMAL);
253 
254  cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p());
255  cairo_rectangle (cr, 0, 0, get_width(), get_height());
256  cairo_fill (cr);
257 
258  /* tabs */
259 
260  for (list<Tab>::const_iterator i = _tabs.begin(); i != _tabs.end(); ++i) {
261  draw_tab (cr, *i);
262  }
263 }
264 
265 
274 GroupTabs::click_to_tab (double c, list<Tab>::iterator* prev, list<Tab>::iterator* next)
275 {
276  *prev = *next = _tabs.end ();
277  Tab* under = 0;
278 
279  list<Tab>::iterator i = _tabs.begin ();
280  while (i != _tabs.end()) {
281 
282  if (i->from > c) {
283  *next = i;
284  break;
285  }
286 
287  if (i->to < c) {
288  *prev = i;
289  ++i;
290  continue;
291  }
292 
293  if (i->from <= c && c < i->to) {
294  under = &(*i);
295  }
296 
297  ++i;
298  }
299 
300  return under;
301 }
302 
303 Gtk::Menu*
305 {
306  using namespace Menu_Helpers;
307 
308  delete _menu;
309 
310  Menu* new_from = new Menu;
311  MenuList& f = new_from->items ();
312  f.push_back (MenuElem (_("Selection..."), sigc::mem_fun (*this, &GroupTabs::new_from_selection)));
313  f.push_back (MenuElem (_("Record Enabled..."), sigc::mem_fun (*this, &GroupTabs::new_from_rec_enabled)));
314  f.push_back (MenuElem (_("Soloed..."), sigc::mem_fun (*this, &GroupTabs::new_from_soloed)));
315 
316  _menu = new Menu;
317  _menu->set_name ("ArdourContextMenu");
318  MenuList& items = _menu->items();
319 
320  items.push_back (MenuElem (_("Create New Group ..."), hide_return (sigc::mem_fun(*this, &GroupTabs::create_and_add_group))));
321  items.push_back (MenuElem (_("Create New Group From"), *new_from));
322 
323  if (g) {
324  items.push_back (MenuElem (_("Edit Group..."), sigc::bind (sigc::mem_fun (*this, &GroupTabs::edit_group), g)));
325  items.push_back (MenuElem (_("Collect Group"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::collect), g)));
326  items.push_back (MenuElem (_("Remove Group"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::remove_group), g)));
327  items.push_back (SeparatorElem());
328  if (g->has_subgroup()) {
329  items.push_back (MenuElem (_("Remove Subgroup Bus"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::un_subgroup), g)));
330  } else {
331  items.push_back (MenuElem (_("Add New Subgroup Bus"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::subgroup), g, false, PreFader)));
332  }
333  items.push_back (MenuElem (_("Add New Aux Bus (pre-fader)"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::subgroup), g, true, PreFader)));
334  items.push_back (MenuElem (_("Add New Aux Bus (post-fader)"), sigc::bind (sigc::mem_fun (*this, &GroupTabs::subgroup), g, true, PostFader)));
335  }
336 
337  add_menu_items (_menu, g);
338 
339  items.push_back (SeparatorElem());
340  items.push_back (MenuElem (_("Enable All Groups"), sigc::mem_fun(*this, &GroupTabs::activate_all)));
341  items.push_back (MenuElem (_("Disable All Groups"), sigc::mem_fun(*this, &GroupTabs::disable_all)));
342 
343  return _menu;
344 
345 }
346 
347 void
349 {
350  RouteList rl = selected_routes ();
351  if (rl.empty()) {
352  return;
353  }
354 
356 }
357 
358 void
360 {
362 
363  RouteList rec_enabled;
364 
365  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
366  if ((*i)->record_enabled()) {
367  rec_enabled.push_back (*i);
368  }
369  }
370 
371  if (rec_enabled.empty()) {
372  return;
373  }
374 
375  run_new_group_dialog (rec_enabled);
376 }
377 
378 void
380 {
382 
383  RouteList soloed;
384 
385  for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
386  if (!(*i)->is_master() && (*i)->soloed()) {
387  soloed.push_back (*i);
388  }
389  }
390 
391  if (soloed.empty()) {
392  return;
393  }
394 
395  run_new_group_dialog (soloed);
396 }
397 
400 {
401  PBD::PropertyList plist;
402 
403  plist.add (Properties::route_active, true);
404  plist.add (Properties::active, true);
405  plist.add (Properties::gain, true);
406  plist.add (Properties::relative, true);
407  plist.add (Properties::color, true);
408  plist.add (Properties::monitoring, true);
409  plist.add (Properties::select, true);
410  plist.add (Properties::mute, true);
411  plist.add (Properties::solo, true);
412  plist.add (Properties::gain, true);
413  plist.add (Properties::recenable, true);
414 
415  return plist;
416 }
417 
418 void
420 {
421  RouteGroup* g = new RouteGroup (*_session, "");
423 
424  RouteGroupDialog d (g, true);
425 
426  if (d.do_run ()) {
427  delete g;
428  } else {
430  for (RouteList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
431  g->add (*i);
432  }
433  }
434 }
435 
436 RouteGroup *
438 {
439  RouteGroup* g = new RouteGroup (*_session, "");
440 
442 
443  RouteGroupDialog d (g, true);
444 
445  if (d.do_run ()) {
446  delete g;
447  return 0;
448  }
449 
451  return g;
452 }
453 
454 void
456 {
457  RouteGroupDialog d (g, false);
458  d.do_run ();
459 }
460 
461 void
462 GroupTabs::subgroup (RouteGroup* g, bool aux, Placement placement)
463 {
464  g->make_subgroup (aux, placement);
465 }
466 
467 void
469 {
470  g->destroy_subgroup ();
471 }
472 
475  return a->order_key () < b->order_key ();
476  }
477 };
478 
479 struct OrderSorter {
481  return a->order_key () < b->order_key ();
482  }
483 };
484 
488 void
490 {
491  boost::shared_ptr<RouteList> group_routes = g->route_list ();
492  group_routes->sort (CollectSorter ());
493  int const N = group_routes->size ();
494 
495  RouteList::iterator i = group_routes->begin ();
497  routes->sort (OrderSorter ());
498  RouteList::const_iterator j = routes->begin ();
499 
500  int diff = 0;
501  int coll = -1;
502  while (i != group_routes->end() && j != routes->end()) {
503 
504  int const k = (*j)->order_key ();
505 
506  if (*i == *j) {
507 
508  if (coll == -1) {
509  coll = k;
510  diff = N - 1;
511  } else {
512  --diff;
513  }
514 
515  (*j)->set_order_key (coll);
516 
517  ++coll;
518  ++i;
519 
520  } else {
521 
522  (*j)->set_order_key (k + diff);
523 
524  }
525 
526  ++j;
527  }
528 
529  sync_order_keys ();
530 }
531 
532 void
534 {
536  sigc::bind (sigc::mem_fun (*this, &GroupTabs::set_activation), true)
537  );
538 }
539 
540 void
542 {
544  sigc::bind (sigc::mem_fun (*this, &GroupTabs::set_activation), false)
545  );
546 }
547 
548 void
550 {
551  g->set_active (a, this);
552 }
553 
554 void
556 {
558 }
559 
561 void
563 {
564  assert (group);
565  uint32_t r, g, b, a;
566 
567  UINT_TO_RGBA (color, &r, &g, &b, &a);
568 
569  /* Hack to disallow black route groups; force a dark grey instead */
570 
571  if (r == 0 && g == 0 && b == 0) {
572  r = 25;
573  g = 25;
574  b = 25;
575  }
576 
578 
579  char buf[64];
580 
581  /* for historical reasons the colors must be stored as 16 bit color
582  * values. Ugh.
583  */
584 
585  snprintf (buf, sizeof (buf), "%d:%d:%d", (r<<8), (g<<8), (b<<8));
586  gui_state.set_property (group_gui_id (group), "color", buf);
587 
588  /* the group color change notification */
589 
590  PBD::PropertyChange change;
591  change.add (Properties::color);
592  group->PropertyChanged (change);
593 
594  /* This is a bit of a hack, but this might change
595  our route's effective color, so emit gui_changed
596  for our routes.
597  */
598 
600 }
601 
603 string
605 {
606  assert (group);
607 
608  char buf[64];
609  snprintf (buf, sizeof (buf), "route_group %s", group->id().to_s().c_str ());
610 
611  return buf;
612 }
613 
615 uint32_t
617 {
618  assert (group);
619 
621  string const gui_id = group_gui_id (group);
622  bool empty;
623  string const color = gui_state.get_string (gui_id, "color", &empty);
624 
625  if (empty) {
626  /* no color has yet been set, so use a random one */
628  set_group_color (group, c);
629  return c;
630  }
631 
632  int r, g, b;
633 
634  /* for historical reasons, colors are stored as 16 bit values.
635  */
636 
637  sscanf (color.c_str(), "%d:%d:%d", &r, &g, &b);
638 
639  r /= 256;
640  g /= 256;
641  b /= 256;
642 
643  return RGBA_TO_UINT (r, g, b, 255);
644 }
645 
646 void
648 {
649  /* This is a bit of a hack, but this might change
650  our route's effective color, so emit gui_changed
651  for our routes.
652  */
653 
655 
656  set_dirty ();
657 }
658 
659 void
661 {
662  /* Similarly-spirited hack as in route_group_property_changed */
663 
664  boost::shared_ptr<Route> r = w.lock ();
665  if (!r) {
666  return;
667  }
668 
669  r->gui_changed (X_("color"), 0);
670 
671  set_dirty ();
672 }
673 
674 void
676 {
677  /* Similarly-spirited hack as in route_group_property_changed */
678 
679  boost::shared_ptr<Route> r = w.lock ();
680  if (!r) {
681  return;
682  }
683 
684  r->gui_changed (X_("color"), 0);
685 
686  set_dirty ();
687 }
688 
689 void
691 {
692  for (RouteList::iterator i = rg->route_list()->begin(); i != rg->route_list()->end(); ++i) {
693  (*i)->gui_changed (X_("color"), 0);
694  }
695 }
Gdk::Color unique_random_color(std::list< Gdk::Color > &)
Definition: utils.cc:873
bool _drag_moved
true if there has been movement during any current drag
Definition: group_tabs.h:129
std::string get_string(const std::string &id, const std::string &prop_name, bool *empty=0)
Definition: gui_object.cc:92
void add_route_group(RouteGroup *)
std::list< Tab > _tabs
current list of tabs
Definition: group_tabs.h:124
PBD::Signal1< void, const PropertyChange & > PropertyChanged
Definition: stateful.h:87
void new_from_rec_enabled()
Definition: group_tabs.cc:359
double _drag_moving
the position of the moving end of the tab being dragged
Definition: group_tabs.h:131
double _drag_offset
offset from the mouse to the end of the tab being dragged
Definition: group_tabs.h:132
PBD::Signal1< void, RouteGroup * > RouteGroupPropertyChanged
Definition: session.h:321
Tab * _dragging
tab being dragged, or 0
Definition: group_tabs.h:125
bool _dragging_new_tab
true if we're dragging a new tab
Definition: group_tabs.h:128
Definition: ardour_ui.h:130
static ARDOUR_UI * instance()
Definition: ardour_ui.h:187
void route_removed_from_route_group(ARDOUR::RouteGroup *, boost::weak_ptr< ARDOUR::Route >)
Definition: group_tabs.cc:675
static void set_group_color(ARDOUR::RouteGroup *, uint32_t)
Definition: group_tabs.cc:562
void route_added_to_route_group(ARDOUR::RouteGroup *, boost::weak_ptr< ARDOUR::Route >)
Definition: group_tabs.cc:660
void remove_group(ARDOUR::RouteGroup *)
Definition: group_tabs.cc:555
bool has_subgroup() const
Definition: route_group.cc:510
void remove_route_group(RouteGroup &)
static int N
Definition: signals_test.cc:27
tuple f
Definition: signals.py:35
void disable_all()
Definition: group_tabs.cc:541
Definition: Beats.hpp:239
virtual ARDOUR::RouteList selected_routes() const =0
LIBARDOUR_API PBD::PropertyDescriptor< bool > gain
Definition: route_group.cc:44
PBD::Signal2< void, RouteGroup *, boost::weak_ptr< Route > > RouteAddedToRouteGroup
Definition: session.h:325
double _drag_max
maximum position for drag
Definition: group_tabs.h:134
void subgroup(ARDOUR::RouteGroup *, bool, ARDOUR::Placement)
Definition: group_tabs.cc:462
void collect(ARDOUR::RouteGroup *)
Definition: group_tabs.cc:489
#define UINT_TO_RGBA(u, r, g, b, a)
Definition: fastmeter.cc:35
void new_from_soloed()
Definition: group_tabs.cc:379
virtual void add_menu_items(Gtk::Menu *, ARDOUR::RouteGroup *)
Definition: group_tabs.h:93
void route_group_property_changed(ARDOUR::RouteGroup *)
Definition: group_tabs.cc:647
#define invalidator(x)
Definition: gui_thread.h:40
GUIObjectState * gui_object_state
Definition: ardour_ui.h:227
void set_session(ARDOUR::Session *)
Definition: group_tabs.cc:58
Gtk::Menu * get_menu(ARDOUR::RouteGroup *g)
Definition: group_tabs.cc:304
double _drag_fixed
the position of the fixed end of the tab being dragged
Definition: group_tabs.h:130
#define _(Text)
Definition: i18n.h:11
LIBGTKMM2EXT_API uint64_t Keyboard
Definition: debug.cc:23
virtual bool apply_changes(PropertyBase const &)
Definition: stateful.cc:337
void make_subgroup(bool, Placement)
Definition: route_group.cc:450
void new_from_selection()
Definition: group_tabs.cc:348
uint32_t gdk_color_to_rgba(Gdk::Color const &)
Definition: utils.cc:285
bool on_button_release_event(GdkEventButton *)
Definition: group_tabs.cc:189
void foreach_route_group(boost::function< void(RouteGroup *)> f)
Definition: session.h:510
#define X_(Text)
Definition: i18n.h:13
PBD::Signal2< void, std::string, void * > gui_changed
Definition: route.h:324
static void emit_gui_changed_for_members(ARDOUR::RouteGroup *)
Definition: group_tabs.cc:690
uint32_t order_key() const
Definition: route.cc:306
virtual ~GroupTabs()
Definition: group_tabs.cc:52
Tab * click_to_tab(double, std::list< Tab >::iterator *, std::list< Tab >::iterator *)
Definition: group_tabs.cc:274
double _drag_min
minimum position for drag
Definition: group_tabs.h:133
LIBARDOUR_API PBD::PropertyDescriptor< bool > recenable
Definition: route_group.cc:47
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
std::string to_s() const
Definition: id.cc:78
#define gui_context()
Definition: gui_thread.h:36
ARDOUR::RouteGroup * create_and_add_group() const
Definition: group_tabs.cc:437
virtual void draw_tab(cairo_t *cr, Tab const &t) const =0
virtual PBD::PropertyList default_properties() const
Definition: group_tabs.cc:399
virtual void sync_order_keys()=0
void set_dirty()
LIBARDOUR_API PBD::PropertyDescriptor< bool > mute
Definition: route_group.cc:45
boost::shared_ptr< RouteList > get_routes() const
Definition: session.h:229
void un_subgroup(ARDOUR::RouteGroup *)
Definition: group_tabs.cc:468
virtual double extent() const =0
PBD::ScopedConnectionList _session_connections
LIBARDOUR_API PBD::PropertyDescriptor< bool > active
Definition: route_group.cc:43
void set_activation(ARDOUR::RouteGroup *, bool)
Definition: group_tabs.cc:549
virtual ARDOUR::RouteList routes_for_tab(Tab const *t) const =0
void render(cairo_t *, cairo_rectangle_t *)
Definition: group_tabs.cc:244
bool on_button_press_event(GdkEventButton *)
Definition: group_tabs.cc:90
static uint32_t group_color(ARDOUR::RouteGroup *)
Definition: group_tabs.cc:616
Gtk::Menu * _menu
Definition: group_tabs.h:123
void on_size_request(Gtk::Requisition *)
Definition: group_tabs.cc:82
double _drag_first
first mouse pointer position during drag
Definition: group_tabs.h:135
LIBARDOUR_API PBD::PropertyDescriptor< bool > solo
Definition: route_group.cc:46
virtual std::list< Tab > compute_tabs() const =0
LIBARDOUR_API PBD::PropertyDescriptor< bool > relative
Definition: route_group.cc:42
ARDOUR::RouteGroup * group
route group
Definition: group_tabs.h:65
boost::shared_ptr< RouteList > route_list()
Definition: route_group.h:126
sigc::signal< void > ColorsChanged
LIBARDOUR_API PBD::PropertyDescriptor< bool > select
Definition: route_group.cc:48
bool on_motion_notify_event(GdkEventMotion *)
Definition: group_tabs.cc:159
int add(boost::shared_ptr< Route >)
Definition: route_group.cc:130
void edit_group(ARDOUR::RouteGroup *)
Definition: group_tabs.cc:455
static std::string group_gui_id(ARDOUR::RouteGroup *)
Definition: group_tabs.cc:604
void set_property(const std::string &id, const std::string &prop_name, const T &val)
Definition: gui_object.h:44
PBD::Signal2< void, RouteGroup *, boost::weak_ptr< Route > > RouteRemovedFromRouteGroup
Definition: session.h:329
#define RGBA_TO_UINT(r, g, b, a)
Definition: rgb_macros.h:34
static std::list< Gdk::Color > _used_colors
Definition: group_tabs.h:138
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
void activate_all()
Definition: group_tabs.cc:533
virtual double primary_coordinate(double, double) const =0
bool add(PropertyBase *prop)
void run_new_group_dialog(ARDOUR::RouteList const &)
Definition: group_tabs.cc:419
ARDOUR::Session * _session
void add(PropertyID id)
PBD::Signal0< void > route_group_removed
Definition: session.h:507
ARDOUR::RouteList _initial_dragging_routes
Definition: group_tabs.h:127
LIBARDOUR_API PBD::PropertyDescriptor< bool > color
Definition: route_group.cc:50
LIBARDOUR_API PBD::PropertyDescriptor< bool > monitoring
Definition: route_group.cc:51