6eac473c7e68082988141d15ba169ab662968fb6
[ardour.git] / gtk2_ardour / editor_edit_groups.cc
1 /*
2     Copyright (C) 2000 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 <cstdlib>
21 #include <cmath>
22
23 #include <gtkmm2ext/stop_signal.h>
24 #include <gtkmm2ext/gtk_ui.h>
25 #include "ardour/route_group.h"
26
27 #include "editor.h"
28 #include "keyboard.h"
29 #include "marker.h"
30 #include "time_axis_view.h"
31 #include "prompter.h"
32 #include "gui_thread.h"
33 #include "editor_group_tabs.h"
34 #include "route_group_dialog.h"
35 #include "route_time_axis.h"
36
37 #include "ardour/route.h"
38
39 #include "i18n.h"
40
41 using namespace std;
42 using namespace sigc;
43 using namespace ARDOUR;
44 using namespace PBD;
45 using namespace Gtk;
46
47 void
48 Editor::build_route_group_menu (RouteGroup* g)
49 {
50         using namespace Gtk::Menu_Helpers;
51
52         delete route_group_menu;
53
54         Menu* new_from = new Menu;
55         MenuList& f = new_from->items ();
56         f.push_back (MenuElem (_("Selection..."), mem_fun (*this, &Editor::new_route_group_from_selection)));
57         f.push_back (MenuElem (_("Record Enabled..."), mem_fun (*this, &Editor::new_route_group_from_rec_enabled)));
58         f.push_back (MenuElem (_("Soloed..."), mem_fun (*this, &Editor::new_route_group_from_soloed)));
59
60         route_group_menu = new Menu;
61         route_group_menu->set_name ("ArdourContextMenu");
62         MenuList& items = route_group_menu->items();
63
64         items.push_back (MenuElem (_("New..."), mem_fun(*this, &Editor::new_route_group)));
65         items.push_back (MenuElem (_("New From"), *new_from));
66         if (g) {
67                 items.push_back (MenuElem (_("Edit..."), bind (mem_fun (*this, &Editor::edit_route_group), g)));
68                 items.push_back (MenuElem (_("Fit to Window"), bind (mem_fun (*this, &Editor::fit_route_group), g)));
69                 items.push_back (MenuElem (_("Subgroup"), bind (mem_fun (*this, &Editor::subgroup_route_group), g)));
70         }
71         items.push_back (SeparatorElem());
72         items.push_back (MenuElem (_("Activate All"), mem_fun(*this, &Editor::activate_all_route_groups)));
73         items.push_back (MenuElem (_("Disable All"), mem_fun(*this, &Editor::disable_all_route_groups)));
74 }
75
76 void
77 Editor::subgroup_route_group (RouteGroup* g)
78 {
79         g->make_subgroup ();
80 }
81
82 void
83 Editor::unsubgroup_route_group (RouteGroup* g)
84 {
85         g->destroy_subgroup ();
86 }
87
88 void
89 Editor::activate_all_route_groups ()
90 {
91         session->foreach_route_group (bind (mem_fun (*this, &Editor::set_route_group_activation), true));
92 }
93
94 void
95 Editor::disable_all_route_groups ()
96 {
97         session->foreach_route_group (bind (mem_fun (*this, &Editor::set_route_group_activation), false));
98 }
99
100 void
101 Editor::set_route_group_activation (RouteGroup* g, bool a)
102 {
103         g->set_active (a, this);
104 }
105
106 void
107 Editor::new_route_group ()
108 {
109         RouteGroup* g = new RouteGroup (*session, "", RouteGroup::Active, (RouteGroup::Property) (RouteGroup::Mute | RouteGroup::Solo | RouteGroup::Edit));
110
111         RouteGroupDialog d (g, Gtk::Stock::NEW);
112         int const r = d.do_run ();
113
114         if (r == Gtk::RESPONSE_OK) {
115                 session->add_route_group (g);
116         } else {
117                 delete g;
118         }
119 }
120
121 void
122 Editor::new_route_group_from_selection ()
123 {
124         RouteGroup* g = new RouteGroup (*session, "", RouteGroup::Active, (RouteGroup::Property) (RouteGroup::Mute | RouteGroup::Solo | RouteGroup::Edit | RouteGroup::Select));
125
126         RouteGroupDialog d (g, Gtk::Stock::NEW);
127         int const r = d.do_run ();
128
129         if (r == Gtk::RESPONSE_OK) {
130                 session->add_route_group (g);
131
132                 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
133                         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
134                         if (rtv) {
135                                 rtv->route()->set_route_group (g, this);
136                         }
137                 }
138                 
139         } else {
140                 delete g;
141         }
142 }
143
144 void
145 Editor::new_route_group_from_rec_enabled ()
146 {
147         RouteGroup* g = new RouteGroup (*session, "", RouteGroup::Active, (RouteGroup::Property) (RouteGroup::Mute | RouteGroup::Solo | RouteGroup::Edit | RouteGroup::RecEnable));
148
149         RouteGroupDialog d (g, Gtk::Stock::NEW);
150         int const r = d.do_run ();
151
152         if (r == Gtk::RESPONSE_OK) {
153                 session->add_route_group (g);
154
155                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
156                         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
157                         if (rtv && rtv->route()->record_enabled()) {
158                                 rtv->route()->set_route_group (g, this);
159                         }
160                 }
161                 
162         } else {
163                 delete g;
164         }
165 }
166
167 void
168 Editor::new_route_group_from_soloed ()
169 {
170         RouteGroup* g = new RouteGroup (*session, "", RouteGroup::Active, (RouteGroup::Property) (RouteGroup::Mute | RouteGroup::Solo | RouteGroup::Edit));
171
172         RouteGroupDialog d (g, Gtk::Stock::NEW);
173         int const r = d.do_run ();
174
175         if (r == Gtk::RESPONSE_OK) {
176                 session->add_route_group (g);
177
178                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
179                         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
180                         if (rtv && !rtv->route()->is_master() && rtv->route()->soloed()) {
181                                 rtv->route()->set_route_group (g, this);
182                         }
183                 }
184                 
185         } else {
186                 delete g;
187         }
188 }
189
190 void
191 Editor::edit_route_group (RouteGroup* g)
192 {
193         RouteGroupDialog d (g, Gtk::Stock::APPLY);
194         d.do_run ();
195 }
196
197 void
198 Editor::remove_selected_route_group ()
199 {
200         Glib::RefPtr<TreeSelection> selection = route_group_display.get_selection();
201         TreeView::Selection::ListHandle_Path rows = selection->get_selected_rows ();
202
203         if (rows.empty()) {
204                 return;
205         }
206
207         TreeView::Selection::ListHandle_Path::iterator i = rows.begin();
208         TreeIter iter;
209         
210         /* selection mode is single, so rows.begin() is it */
211
212         if ((iter = group_model->get_iter (*i))) {
213
214                 RouteGroup* rg = (*iter)[group_columns.routegroup];
215
216                 if (rg) {
217                         session->remove_route_group (*rg);
218                 }
219         }
220 }
221
222 void
223 Editor::route_group_list_button_clicked ()
224 {
225         new_route_group ();
226 }
227
228 gint
229 Editor::route_group_list_button_press_event (GdkEventButton* ev)
230 {
231         TreeModel::Path path;
232         TreeIter iter;
233         RouteGroup* group = 0;
234         TreeViewColumn* column;
235         int cellx;
236         int celly;
237
238         bool const p = route_group_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly);
239
240         if (p) {
241                 iter = group_model->get_iter (path);
242         }
243         
244         if (iter) {
245                 group = (*iter)[group_columns.routegroup];
246         }
247
248         if (Keyboard::is_context_menu_event (ev)) {
249                 build_route_group_menu (group);
250                 route_group_menu->popup (1, ev->time);
251                 return true;
252         }
253
254         if (!p) {
255                 return 1;
256         }
257
258         switch (GPOINTER_TO_UINT (column->get_data (X_("colnum")))) {
259         case 0:
260                 if (Keyboard::is_edit_event (ev)) {
261                         if ((iter = group_model->get_iter (path))) {
262                                 if ((group = (*iter)[group_columns.routegroup]) != 0) {
263                                         // edit_route_group (group);
264 #ifdef GTKOSX
265                                         route_group_display.queue_draw();
266 #endif
267                                         return true;
268                                 }
269                         }
270                         
271                 } 
272                 break;
273
274         case 1:
275                 if ((iter = group_model->get_iter (path))) {
276                         bool gain = (*iter)[group_columns.gain];
277                         (*iter)[group_columns.gain] = !gain;
278 #ifdef GTKOSX
279                         route_group_display.queue_draw();
280 #endif
281                         return true;
282                 }
283                 break;
284
285         case 2:
286                 if ((iter = group_model->get_iter (path))) {
287                         bool record = (*iter)[group_columns.record];
288                         (*iter)[group_columns.record] = !record;
289 #ifdef GTKOSX
290                         route_group_display.queue_draw();
291 #endif
292                         return true;
293                 }
294                 break;
295
296         case 3:
297                 if ((iter = group_model->get_iter (path))) {
298                         bool mute = (*iter)[group_columns.mute];
299                         (*iter)[group_columns.mute] = !mute;
300 #ifdef GTKOSX
301                         route_group_display.queue_draw();
302 #endif
303                         return true;
304                 }
305                 break;
306
307         case 4:
308                 if ((iter = group_model->get_iter (path))) {
309                         bool solo = (*iter)[group_columns.solo];
310                         (*iter)[group_columns.solo] = !solo;
311 #ifdef GTKOSX
312                         route_group_display.queue_draw();
313 #endif
314                         return true;
315                 }
316                 break;
317
318         case 5:
319                 if ((iter = group_model->get_iter (path))) {
320                         bool select = (*iter)[group_columns.select];
321                         (*iter)[group_columns.select] = !select;
322 #ifdef GTKOSX
323                         route_group_display.queue_draw();
324 #endif
325                         return true;
326                 }
327                 break;
328
329         case 6:
330                 if ((iter = group_model->get_iter (path))) {
331                         bool edits = (*iter)[group_columns.edits];
332                         (*iter)[group_columns.edits] = !edits;
333 #ifdef GTKOSX
334                         route_group_display.queue_draw();
335 #endif
336                         return true;
337                 }
338                 break;
339
340         case 7:
341                 if ((iter = group_model->get_iter (path))) {
342                         bool visible = (*iter)[group_columns.is_visible];
343                         (*iter)[group_columns.is_visible] = !visible;
344 #ifdef GTKOSX
345                         route_group_display.queue_draw();
346 #endif
347                         return true;
348                 }
349                 break;
350
351         default:
352                 break;
353         }
354         
355         return false;
356  }
357
358 void 
359 Editor::route_group_row_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter)
360 {
361         RouteGroup* group;
362
363         if (in_route_group_row_change) {
364                 return;
365         }
366
367         if ((group = (*iter)[group_columns.routegroup]) == 0) {
368                 return;
369         }
370
371         if ((*iter)[group_columns.is_visible]) {
372                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
373                         if ((*j)->route_group() == group) {
374                                 show_track_in_display (**j);
375                         }
376                 }
377         } else {
378                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
379                         if ((*j)->route_group() == group) {
380                                 hide_track_in_display (**j);
381                         }
382                 }
383         }
384
385         if ((*iter)[group_columns.gain]) {
386                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
387                         if ((*j)->route_group() == group) {
388                                 group->set_property (RouteGroup::Gain, true);
389                         }
390                 }
391         } else {
392                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
393                         if ((*j)->route_group() == group) {
394                                 group->set_property (RouteGroup::Gain, false);
395                         }
396                 }
397         }
398
399         if ((*iter)[group_columns.record]) {
400                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
401                         if ((*j)->route_group() == group) {
402                                 group->set_property (RouteGroup::RecEnable, true);
403                         }
404                 }
405         } else {
406                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
407                         if ((*j)->route_group() == group) {
408                                 group->set_property (RouteGroup::RecEnable, false);
409                         }
410                 }
411         }
412
413         if ((*iter)[group_columns.mute]) {
414                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
415                         if ((*j)->route_group() == group) {
416                                 group->set_property (RouteGroup::Mute, true);
417                         }
418                 }
419         } else {
420                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
421                         if ((*j)->route_group() == group) {
422                                 group->set_property (RouteGroup::Mute, false);
423                         }
424                 }
425         }
426
427         if ((*iter)[group_columns.solo]) {
428                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
429                         if ((*j)->route_group() == group) {
430                                 group->set_property (RouteGroup::Solo, true);
431                         }
432                 }
433         } else {
434                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
435                         if ((*j)->route_group() == group) {
436                                 group->set_property (RouteGroup::Solo, false);
437                         }
438                 }
439         }
440
441         if ((*iter)[group_columns.select]) {
442                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
443                         if ((*j)->route_group() == group) {
444                                 group->set_property (RouteGroup::Select, true);
445                         }
446                 }
447         } else {
448                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
449                         if ((*j)->route_group() == group) {
450                                 group->set_property (RouteGroup::Select, false);
451                         }
452                 }
453         }
454
455         if ((*iter)[group_columns.edits]) {
456                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
457                         if ((*j)->route_group() == group) {
458                                 group->set_property (RouteGroup::Edit, true);
459                         }
460                 }
461         } else {
462                 for (TrackViewList::iterator j = track_views.begin(); j != track_views.end(); ++j) {
463                         if ((*j)->route_group() == group) {
464                                 group->set_property (RouteGroup::Edit, false);
465                         }
466                 }
467         }
468
469         string name = (*iter)[group_columns.text];
470
471         if (name != group->name()) {
472                 group->set_name (name);
473         }
474 }
475
476 void
477 Editor::add_route_group (RouteGroup* group)
478 {
479         ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::add_route_group), group));
480         bool focus = false;
481
482         TreeModel::Row row = *(group_model->append());
483         
484         row[group_columns.is_visible] = !group->is_hidden();
485         row[group_columns.gain] = group->property(RouteGroup::Gain);
486         row[group_columns.record] = group->property(RouteGroup::RecEnable);
487         row[group_columns.mute] = group->property(RouteGroup::Mute);
488         row[group_columns.solo] = group->property(RouteGroup::Solo);
489         row[group_columns.select] = group->property(RouteGroup::Select);
490         row[group_columns.edits] = group->property(RouteGroup::Edit);
491
492         in_route_group_row_change = true;
493
494         row[group_columns.routegroup] = group;
495
496         if (!group->name().empty()) {
497                 row[group_columns.text] = group->name();
498         } else {
499                 row[group_columns.text] = _("unnamed");
500                 focus = true;
501         }
502
503         group->FlagsChanged.connect (bind (mem_fun(*this, &Editor::group_flags_changed), group));
504
505         if (focus) {  
506                 TreeViewColumn* col = route_group_display.get_column (0);
507                 CellRendererText* name_cell = dynamic_cast<CellRendererText*>(route_group_display.get_column_cell_renderer (0));
508                 route_group_display.set_cursor (group_model->get_path (row), *col, *name_cell, true);
509         }
510
511         in_route_group_row_change = false;
512
513         _group_tabs->set_dirty ();
514 }
515
516 void
517 Editor::route_groups_changed ()
518 {
519         ENSURE_GUI_THREAD (mem_fun (*this, &Editor::route_groups_changed));
520
521         /* just rebuild the while thing */
522
523         group_model->clear ();
524
525         {
526                 TreeModel::Row row;
527                 row = *(group_model->append());
528                 row[group_columns.is_visible] = true;
529                 row[group_columns.text] = (_("-all-"));
530                 row[group_columns.routegroup] = 0;
531         }
532
533         session->foreach_route_group (mem_fun (*this, &Editor::add_route_group));
534 }
535
536 void
537 Editor::group_flags_changed (void* src, RouteGroup* group)
538 {
539         ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::group_flags_changed), src, group));
540
541         in_route_group_row_change = true;
542
543         Gtk::TreeModel::Children children = group_model->children();
544
545         for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) {
546                 if (group == (*iter)[group_columns.routegroup]) {
547                         (*iter)[group_columns.is_visible] = !group->is_hidden();
548                         (*iter)[group_columns.text] = group->name();
549                         (*iter)[group_columns.gain] = group->property(RouteGroup::Gain);
550                         (*iter)[group_columns.record] = group->property(RouteGroup::RecEnable);
551                         (*iter)[group_columns.mute] = group->property(RouteGroup::Mute);
552                         (*iter)[group_columns.solo] = group->property(RouteGroup::Solo);
553                         (*iter)[group_columns.select] = group->property(RouteGroup::Select);
554                         (*iter)[group_columns.edits] = group->property(RouteGroup::Edit);
555                 }
556         }
557
558         in_route_group_row_change = false;
559
560         _group_tabs->set_dirty ();
561 }
562
563 void
564 Editor::route_group_name_edit (const Glib::ustring& path, const Glib::ustring& new_text)
565 {
566         RouteGroup* group;
567         TreeIter iter;
568         
569         if ((iter = group_model->get_iter (path))) {
570         
571                 if ((group = (*iter)[group_columns.routegroup]) == 0) {
572                         return;
573                 }
574                 
575                 if (new_text != group->name()) {
576                         group->set_name (new_text);
577                 }
578         }
579 }