Merge branch 'master' into cairocanvas
[ardour.git] / gtk2_ardour / route_ui.cc
1 /*
2     Copyright (C) 2002-2006 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 <gtkmm2ext/gtk_ui.h>
21 #include <gtkmm2ext/choice.h>
22 #include <gtkmm2ext/doi.h>
23 #include <gtkmm2ext/bindable_button.h>
24 #include <gtkmm2ext/barcontroller.h>
25 #include <gtkmm2ext/gtk_ui.h>
26
27 #include "ardour/route_group.h"
28 #include "ardour/dB.h"
29 #include "pbd/memento_command.h"
30 #include "pbd/stacktrace.h"
31 #include "pbd/controllable.h"
32 #include "pbd/enumwriter.h"
33
34 #include "ardour_ui.h"
35 #include "editor.h"
36 #include "route_ui.h"
37 #include "ardour_button.h"
38 #include "keyboard.h"
39 #include "utils.h"
40 #include "prompter.h"
41 #include "gui_thread.h"
42 #include "ardour_dialog.h"
43 #include "latency_gui.h"
44 #include "mixer_strip.h"
45 #include "automation_time_axis.h"
46 #include "route_time_axis.h"
47 #include "group_tabs.h"
48
49 #include "ardour/audio_track.h"
50 #include "ardour/audioengine.h"
51 #include "ardour/filename_extensions.h"
52 #include "ardour/midi_track.h"
53 #include "ardour/route.h"
54 #include "ardour/session.h"
55 #include "ardour/template_utils.h"
56
57 #include "i18n.h"
58 using namespace Gtk;
59 using namespace Gtkmm2ext;
60 using namespace ARDOUR;
61 using namespace PBD;
62
63 uint32_t RouteUI::_max_invert_buttons = 3;
64 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
65 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
66
67 RouteUI::RouteUI (ARDOUR::Session* sess)
68         : AxisView(sess)
69         , mute_menu(0)
70         , solo_menu(0)
71         , sends_menu(0)
72         , record_menu(0)
73         , _invert_menu(0)
74 {
75         if (sess) init ();
76 }
77
78 RouteUI::~RouteUI()
79 {
80         _route.reset (); /* drop reference to route, so that it can be cleaned up */
81         route_connections.drop_connections ();
82
83         delete solo_menu;
84         delete mute_menu;
85         delete sends_menu;
86         delete record_menu;
87         delete _invert_menu;
88 }
89
90 void
91 RouteUI::init ()
92 {
93         self_destruct = true;
94         mute_menu = 0;
95         solo_menu = 0;
96         sends_menu = 0;
97         record_menu = 0;
98         _invert_menu = 0;
99         pre_fader_mute_check = 0;
100         post_fader_mute_check = 0;
101         listen_mute_check = 0;
102         main_mute_check = 0;
103         solo_safe_check = 0;
104         solo_isolated_check = 0;
105         solo_isolated_led = 0;
106         solo_safe_led = 0;
107         _solo_release = 0;
108         _mute_release = 0;
109         denormal_menu_item = 0;
110         step_edit_item = 0;
111         multiple_mute_change = false;
112         multiple_solo_change = false;
113         _i_am_the_modifier = 0;
114
115         setup_invert_buttons ();
116
117         mute_button = manage (new ArdourButton);
118         mute_button->set_name ("mute button");
119         UI::instance()->set_tip (mute_button, _("Mute this track"), "");
120
121         solo_button = manage (new ArdourButton);
122         solo_button->set_name ("solo button");
123         UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
124         solo_button->set_no_show_all (true);
125
126         rec_enable_button = manage (new ArdourButton);
127         rec_enable_button->set_name ("record enable button");
128         rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor);
129         UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
130
131         show_sends_button = manage (new ArdourButton);
132         show_sends_button->set_name ("send alert button");
133         UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
134
135         monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
136         monitor_input_button->set_name ("monitor button");
137         monitor_input_button->set_text (_("In"));
138         UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
139         monitor_input_button->set_no_show_all (true);
140         
141         monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
142         monitor_disk_button->set_name ("monitor button");
143         monitor_disk_button->set_text (_("Disk"));
144         UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
145         monitor_disk_button->set_no_show_all (true);
146
147         _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
148         _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
149         _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
150
151         _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
152         Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
153
154         rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
155         rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
156
157         show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
158         show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
159
160         solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
161         solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
162         mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
163         mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
164         
165         monitor_input_button->set_distinct_led_click (false);
166         monitor_disk_button->set_distinct_led_click (false);
167
168         monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
169         monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
170
171         monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
172         monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
173
174         BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
175 }
176
177 void
178 RouteUI::reset ()
179 {
180         route_connections.drop_connections ();
181
182         delete solo_menu;
183         solo_menu = 0;
184
185         delete mute_menu;
186         mute_menu = 0;
187
188         denormal_menu_item = 0;
189 }
190
191 void
192 RouteUI::self_delete ()
193 {
194         delete this;
195 }
196
197 void
198 RouteUI::set_route (boost::shared_ptr<Route> rp)
199 {
200         reset ();
201
202         _route = rp;
203
204         if (set_color_from_route()) {
205                 set_color (unique_random_color());
206         }
207
208         if (self_destruct) {
209                 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
210         }
211
212         mute_button->set_controllable (_route->mute_control());
213         solo_button->set_controllable (_route->solo_control());
214
215         _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
216         _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
217
218         _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
219         _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
220         _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
221         _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
222
223         _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
224         _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
225
226         _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
227         _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
228
229         if (_session->writable() && is_track()) {
230                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
231
232                 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
233                 
234                 rec_enable_button->show();
235                 rec_enable_button->set_controllable (t->rec_enable_control());
236
237                 if (is_midi_track()) {
238                         midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
239                                                                     boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
240                 }
241
242         } 
243
244         /* this will work for busses and tracks, and needs to be called to
245            set up the name entry/name label display.
246         */
247
248         update_rec_display ();
249
250         if (is_track()) {
251                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
252                 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
253
254                 update_monitoring_display ();
255         }
256
257         mute_button->unset_flags (Gtk::CAN_FOCUS);
258         solo_button->unset_flags (Gtk::CAN_FOCUS);
259
260         mute_button->show();
261
262         if (_route->is_monitor() || _route->is_master()) {
263                 solo_button->hide ();
264         } else {
265                 solo_button->show();
266         }
267
268         map_frozen ();
269
270         setup_invert_buttons ();
271         set_invert_button_state ();
272
273         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
274         bus_send_display_changed (s);
275
276         update_mute_display ();
277         update_solo_display ();
278 }
279
280 void
281 RouteUI::polarity_changed ()
282 {
283         if (!_route) {
284                 return;
285         }
286
287         set_invert_button_state ();
288 }
289
290 bool
291 RouteUI::mute_press (GdkEventButton* ev)
292 {
293         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
294                 return true;
295         }
296
297         multiple_mute_change = false;
298
299         if (!_i_am_the_modifier) {
300
301                 if (Keyboard::is_context_menu_event (ev)) {
302
303                         if (mute_menu == 0){
304                                 build_mute_menu();
305                         }
306
307                         mute_menu->popup(0,ev->time);
308
309                 } else {
310
311                         if (Keyboard::is_button2_event (ev)) {
312                                 // Primary-button2 click is the midi binding click
313                                 // button2-click is "momentary"
314
315
316                                 if (mute_button->on_button_press_event (ev)) {
317                                         return true;
318                                 }
319
320                                 _mute_release = new SoloMuteRelease (_route->muted ());
321                         }
322
323                         if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
324
325                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
326
327                                         /* toggle mute on everything (but
328                                          * exclude the master and monitor)
329                                          *
330                                          * because we are going to erase
331                                          * elements of the list we need to work
332                                          * on a copy.
333                                          */
334                                         
335                                         boost::shared_ptr<RouteList> copy (new RouteList);
336
337                                         *copy = *_session->get_routes ();
338
339                                         for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
340                                                 if ((*i)->is_master() || (*i)->is_monitor()) {
341                                                         i = copy->erase (i);
342                                                 } else {
343                                                         ++i;
344                                                 }
345                                         }
346
347                                         if (_mute_release) {
348                                                 _mute_release->routes = copy;
349                                         }
350
351                                         _session->set_mute (copy, !_route->muted());
352
353                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
354
355                                         /* Primary-button1 applies change to the mix group even if it is not active
356                                            NOTE: Primary-button2 is MIDI learn.
357                                         */
358
359                                         boost::shared_ptr<RouteList> rl;
360
361                                         if (ev->button == 1) { 
362
363                                                 if (_route->route_group()) {
364                                                         
365                                                         rl = _route->route_group()->route_list();
366                                                         
367                                                         if (_mute_release) {
368                                                                 _mute_release->routes = rl;
369                                                         }
370                                                 } else {
371                                                         rl.reset (new RouteList);
372                                                         rl->push_back (_route);
373                                                 }
374
375                                                 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
376                                         }
377
378                                 } else {
379
380                                         /* plain click applies change to this route */
381
382                                         boost::shared_ptr<RouteList> rl (new RouteList);
383                                         rl->push_back (_route);
384                                         
385                                         if (_mute_release) {
386                                                 _mute_release->routes = rl;
387                                         }
388
389                                         _session->set_mute (rl, !_route->muted());
390
391                                 }
392                         }
393                 }
394
395         }
396
397         return true;
398 }
399
400 bool
401 RouteUI::mute_release (GdkEventButton*)
402 {
403         if (!_i_am_the_modifier) {
404                 if (_mute_release){
405                         _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
406                         delete _mute_release;
407                         _mute_release = 0;
408                 }
409         }
410
411         return true;
412 }
413
414 bool
415 RouteUI::solo_press(GdkEventButton* ev)
416 {
417         /* ignore double/triple clicks */
418
419         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
420                 return true;
421         }
422
423         multiple_solo_change = false;
424
425         if (!_i_am_the_modifier) {
426
427                 if (Keyboard::is_context_menu_event (ev)) {
428
429                         if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
430                             ! (solo_safe_led && solo_safe_led->is_visible())) {
431
432                                 if (solo_menu == 0) {
433                                         build_solo_menu ();
434                                 }
435
436                                 solo_menu->popup (1, ev->time);
437                         }
438
439                 } else {
440
441                         if (Keyboard::is_button2_event (ev)) {
442
443                                 // Primary-button2 click is the midi binding click
444                                 // button2-click is "momentary"
445
446                                 if (solo_button->on_button_press_event (ev)) {
447                                         return true;
448                                 }
449
450                                 _solo_release = new SoloMuteRelease (_route->self_soloed());
451                         }
452
453                         if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
454
455                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
456
457                                         /* Primary-Tertiary-click applies change to all routes */
458
459                                         if (_solo_release) {
460                                                 _solo_release->routes = _session->get_routes ();
461                                         }
462
463                                         if (Config->get_solo_control_is_listen_control()) {
464                                                 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(),  Session::rt_cleanup, true);
465                                         } else {
466                                                 _session->set_solo (_session->get_routes(), !_route->self_soloed(),  Session::rt_cleanup, true);
467                                         }
468
469                                 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
470
471                                         // Primary-Secondary-click: exclusively solo this track
472
473                                         if (_solo_release) {
474                                                 _solo_release->exclusive = true;
475
476                                                 boost::shared_ptr<RouteList> routes = _session->get_routes();
477
478                                                 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
479                                                         if ((*i)->soloed ()) {
480                                                                 _solo_release->routes_on->push_back (*i);
481                                                         } else {
482                                                                 _solo_release->routes_off->push_back (*i);
483                                                         }
484                                                 }
485                                         }
486
487                                         if (Config->get_solo_control_is_listen_control()) {
488                                                 /* ??? we need a just_one_listen() method */
489                                         } else {
490                                                 _session->set_just_one_solo (_route, true);
491                                         }
492
493                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
494
495                                         // shift-click: toggle solo isolated status
496
497                                         _route->set_solo_isolated (!_route->solo_isolated(), this);
498                                         delete _solo_release;
499                                         _solo_release = 0;
500
501                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
502
503                                         /* Primary-button1: solo mix group.
504                                            NOTE: Primary-button2 is MIDI learn.
505                                         */
506
507                                         /* Primary-button1 applies change to the mix group even if it is not active
508                                            NOTE: Primary-button2 is MIDI learn.
509                                         */
510
511                                         boost::shared_ptr<RouteList> rl;
512
513                                         if (ev->button == 1) { 
514
515                                                 if (_route->route_group()) {
516                                                         
517                                                         rl = _route->route_group()->route_list();
518                                                         
519                                                         if (_solo_release) {
520                                                                 _solo_release->routes = rl;
521                                                         }
522                                                 } else {
523                                                         rl.reset (new RouteList);
524                                                         rl->push_back (_route);
525                                                 }
526
527                                                 if (Config->get_solo_control_is_listen_control()) {
528                                                         _session->set_listen (rl, !_route->listening_via_monitor(),  Session::rt_cleanup, true);
529                                                 } else {
530                                                         _session->set_solo (rl, !_route->self_soloed(),  Session::rt_cleanup, true);
531                                                 }
532                                         }
533
534                                 } else {
535
536                                         /* click: solo this route */
537
538                                         boost::shared_ptr<RouteList> rl (new RouteList);
539                                         rl->push_back (route());
540
541                                         if (_solo_release) {
542                                                 _solo_release->routes = rl;
543                                         }
544
545                                         if (Config->get_solo_control_is_listen_control()) {
546                                                 _session->set_listen (rl, !_route->listening_via_monitor());
547                                         } else {
548                                                 _session->set_solo (rl, !_route->self_soloed());
549                                         }
550                                 }
551                         }
552                 }
553         }
554
555         return true;
556 }
557
558 bool
559 RouteUI::solo_release (GdkEventButton*)
560 {
561         if (!_i_am_the_modifier) {
562
563                 if (_solo_release) {
564
565                         if (_solo_release->exclusive) {
566
567                         } else {
568                                 if (Config->get_solo_control_is_listen_control()) {
569                                         _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
570                                 } else {
571                                         _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
572                                 }
573                         }
574
575                         delete _solo_release;
576                         _solo_release = 0;
577                 }
578         }
579
580         return true;
581 }
582
583 bool
584 RouteUI::rec_enable_press(GdkEventButton* ev)
585 {
586         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
587                 return true;
588         }
589
590         if (!_session->engine().connected()) {
591                 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
592                 msg.run ();
593                 return true;
594         }
595
596         if (is_midi_track()) {
597
598                 /* rec-enable button exits from step editing */
599
600                 if (midi_track()->step_editing()) {
601                         midi_track()->set_step_editing (false);
602                         return true;
603                 }
604         }
605
606         if (!_i_am_the_modifier && is_track() && rec_enable_button) {
607
608                 if (Keyboard::is_button2_event (ev)) {
609
610                         // do nothing on midi sigc::bind event
611                         return rec_enable_button->on_button_press_event (ev);
612
613                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
614
615                         _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
616
617                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
618
619                         /* Primary-button1 applies change to the route group (even if it is not active)
620                            NOTE: Primary-button2 is MIDI learn.
621                         */
622
623                         if (ev->button == 1) {
624
625                                 boost::shared_ptr<RouteList> rl;
626                                 
627                                 if (_route->route_group()) {
628                                         
629                                         rl = _route->route_group()->route_list();
630                                         
631                                 } else {
632                                         rl.reset (new RouteList);
633                                         rl->push_back (_route);
634                                 }
635                                 
636                                 _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
637                         }
638
639                 } else if (Keyboard::is_context_menu_event (ev)) {
640
641                         /* do this on release */
642
643                 } else {
644
645                         boost::shared_ptr<RouteList> rl (new RouteList);
646                         rl->push_back (route());
647                         _session->set_record_enabled (rl, !rec_enable_button->active_state());
648                 }
649         }
650
651         return true;
652 }
653
654 void
655 RouteUI::monitoring_changed ()
656 {
657         update_monitoring_display ();
658 }
659
660 void
661 RouteUI::update_monitoring_display ()
662 {
663         if (!_route) {
664                 return;
665         }
666
667         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
668
669         if (!t) {
670                 return;
671         }
672
673         MonitorState ms = t->monitoring_state();
674
675         if (t->monitoring_choice() & MonitorInput) {
676                 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
677         } else {
678                 if (ms & MonitoringInput) {
679                         monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
680                 } else {
681                         monitor_input_button->unset_active_state ();
682                 }
683         }
684
685         if (t->monitoring_choice() & MonitorDisk) {
686                 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
687         } else {
688                 if (ms & MonitoringDisk) {
689                         monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
690                 } else {
691                         monitor_disk_button->unset_active_state ();
692                 }
693         }
694 }
695
696 bool
697 RouteUI::monitor_input_press(GdkEventButton*)
698 {
699         return true;
700 }
701
702 bool
703 RouteUI::monitor_input_release(GdkEventButton* ev)
704 {
705         return monitor_release (ev, MonitorInput);
706 }
707
708 bool
709 RouteUI::monitor_disk_press (GdkEventButton*)
710 {
711         return true;
712 }
713
714 bool
715 RouteUI::monitor_disk_release (GdkEventButton* ev)
716 {
717         return monitor_release (ev, MonitorDisk);
718 }
719
720 bool
721 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
722 {       
723         if (ev->button != 1) {
724                 return false;
725         }
726
727         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
728
729         if (!t) {
730                 return true;
731         }
732
733         MonitorChoice mc;
734         boost::shared_ptr<RouteList> rl;
735         
736         /* XXX for now, monitoring choices are orthogonal. cue monitoring 
737            will follow in 3.X but requires mixing the input and playback (disk)
738            signal together, which requires yet more buffers.
739         */
740
741         if (t->monitoring_choice() & monitor_choice) {
742                 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
743         } else {
744                 /* this line will change when the options are non-orthogonal */
745                 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
746                 mc = monitor_choice;
747         }
748
749         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {       
750                 rl = _session->get_routes ();
751
752         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
753                 if (_route->route_group() && _route->route_group()->is_monitoring()) {
754                         rl = _route->route_group()->route_list();
755                 } else {
756                         rl.reset (new RouteList);
757                         rl->push_back (route());
758                 }
759         } else {
760                 rl.reset (new RouteList);
761                 rl->push_back (route());
762         }
763
764         _session->set_monitoring (rl, mc, Session::rt_cleanup, true);           
765
766         return true;
767 }
768
769 void
770 RouteUI::build_record_menu ()
771 {
772         if (record_menu) {
773                 return;
774         }
775
776         /* no rec-button context menu for non-MIDI tracks
777          */
778
779         if (is_midi_track()) {
780                 record_menu = new Menu;
781                 record_menu->set_name ("ArdourContextMenu");
782
783                 using namespace Menu_Helpers;
784                 MenuList& items = record_menu->items();
785
786                 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
787                 step_edit_item = dynamic_cast<CheckMenuItem*> (&items.back());
788
789                 if (_route->record_enabled()) {
790                         step_edit_item->set_sensitive (false);
791                 }
792
793                 step_edit_item->set_active (midi_track()->step_editing());
794         }
795 }
796
797 void
798 RouteUI::toggle_step_edit ()
799 {
800         if (!is_midi_track() || _route->record_enabled()) {
801                 return;
802         }
803
804         midi_track()->set_step_editing (step_edit_item->get_active());
805 }
806
807 void
808 RouteUI::step_edit_changed (bool yn)
809 {
810         if (yn) {
811                 if (rec_enable_button) {
812                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
813                 }
814
815                 start_step_editing ();
816
817                 if (step_edit_item) {
818                         step_edit_item->set_active (true);
819                 }
820
821         } else {
822
823                 if (rec_enable_button) {
824                         rec_enable_button->unset_active_state ();
825                 }
826
827                 stop_step_editing ();
828
829                 if (step_edit_item) {
830                         step_edit_item->set_active (false);
831                 }
832         }
833 }
834
835 bool
836 RouteUI::rec_enable_release (GdkEventButton* ev)
837 {
838         if (Keyboard::is_context_menu_event (ev)) {
839                 build_record_menu ();
840                 if (record_menu) {
841                         record_menu->popup (1, ev->time);
842                 }
843                 return true;
844         }
845
846         return true;
847 }
848
849 void
850 RouteUI::build_sends_menu ()
851 {
852         using namespace Menu_Helpers;
853
854         sends_menu = new Menu;
855         sends_menu->set_name ("ArdourContextMenu");
856         MenuList& items = sends_menu->items();
857
858         items.push_back (
859                 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
860                 );
861
862         items.push_back (
863                 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
864                 );
865
866         items.push_back (
867                 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
868                 );
869
870         items.push_back (
871                 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
872                 );
873
874         items.push_back (
875                 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
876                 );
877
878         items.push_back (
879                 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
880
881         items.push_back (
882                 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
883                 );
884
885         items.push_back (
886                 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
887                 );
888
889         items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
890         items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
891         items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
892
893 }
894
895 void
896 RouteUI::create_sends (Placement p, bool include_buses)
897 {
898         _session->globally_add_internal_sends (_route, p, include_buses);
899 }
900
901 void
902 RouteUI::create_selected_sends (Placement p, bool include_buses)
903 {
904         boost::shared_ptr<RouteList> rlist (new RouteList);
905         TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
906
907         for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
908                 RouteTimeAxisView* rtv;
909                 RouteUI* rui;
910                 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
911                         if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
912                                 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
913                                         rlist->push_back (rui->route());
914                                 }
915                         }
916                 }
917         }
918
919         _session->add_internal_sends (_route, p, rlist);
920 }
921
922 void
923 RouteUI::set_sends_gain_from_track ()
924 {
925         _session->globally_set_send_gains_from_track (_route);
926 }
927
928 void
929 RouteUI::set_sends_gain_to_zero ()
930 {
931         _session->globally_set_send_gains_to_zero (_route);
932 }
933
934 void
935 RouteUI::set_sends_gain_to_unity ()
936 {
937         _session->globally_set_send_gains_to_unity (_route);
938 }
939
940 bool
941 RouteUI::show_sends_press(GdkEventButton* ev)
942 {
943         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
944                 return true;
945         }
946
947         if (!_i_am_the_modifier && !is_track() && show_sends_button) {
948
949                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
950
951                         // do nothing on midi sigc::bind event
952                         return false;
953
954                 } else if (Keyboard::is_context_menu_event (ev)) {
955
956                         if (sends_menu == 0) {
957                                 build_sends_menu ();
958                         }
959
960                         sends_menu->popup (0, ev->time);
961
962                 } else {
963
964                         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
965
966                         if (s == _route) {
967                                 set_showing_sends_to (boost::shared_ptr<Route> ());
968                         } else {
969                                 set_showing_sends_to (_route);
970                         }
971                 }
972         }
973
974         return true;
975 }
976
977 bool
978 RouteUI::show_sends_release (GdkEventButton*)
979 {
980         return true;
981 }
982
983 void
984 RouteUI::send_blink (bool onoff)
985 {
986         if (!show_sends_button) {
987                 return;
988         }
989
990         if (onoff) {
991                 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
992         } else {
993                 show_sends_button->unset_active_state ();
994         }
995 }
996
997 Gtkmm2ext::ActiveState
998 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
999 {
1000         if (r->is_master() || r->is_monitor()) {
1001                 return Gtkmm2ext::Off;
1002         }
1003
1004         if (Config->get_solo_control_is_listen_control()) {
1005
1006                 if (r->listening_via_monitor()) {
1007                         return Gtkmm2ext::ExplicitActive;
1008                 } else {
1009                         return Gtkmm2ext::Off;
1010                 }
1011
1012         }
1013
1014         if (r->soloed()) {
1015                 if (!r->self_soloed()) {
1016                         return Gtkmm2ext::ImplicitActive;
1017                 } else {
1018                         return Gtkmm2ext::ExplicitActive;
1019                 }
1020         } else {
1021                 return Gtkmm2ext::Off;
1022         }
1023 }
1024
1025 Gtkmm2ext::ActiveState
1026 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1027 {
1028         if (r->is_master() || r->is_monitor()) {
1029                 return Gtkmm2ext::Off;
1030         }
1031
1032         if (r->solo_isolated()) {
1033                 return Gtkmm2ext::ExplicitActive;
1034         } else {
1035                 return Gtkmm2ext::Off;
1036         }
1037 }
1038
1039 Gtkmm2ext::ActiveState
1040 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1041 {
1042         if (r->is_master() || r->is_monitor()) {
1043                 return Gtkmm2ext::Off;
1044         }
1045
1046         if (r->solo_safe()) {
1047                 return Gtkmm2ext::ExplicitActive;
1048         } else {
1049                 return Gtkmm2ext::Off;
1050         }
1051 }
1052
1053 void
1054 RouteUI::update_solo_display ()
1055 {
1056         bool yn = _route->solo_safe ();
1057
1058         if (solo_safe_check && solo_safe_check->get_active() != yn) {
1059                 solo_safe_check->set_active (yn);
1060         }
1061
1062         yn = _route->solo_isolated ();
1063
1064         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1065                 solo_isolated_check->set_active (yn);
1066         }
1067
1068         set_button_names ();
1069
1070         if (solo_isolated_led) {
1071                 if (_route->solo_isolated()) {
1072                         solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1073                 } else {
1074                         solo_isolated_led->unset_active_state ();
1075                 }
1076         }
1077
1078         if (solo_safe_led) {
1079                 if (_route->solo_safe()) {
1080                         solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1081                 } else {
1082                         solo_safe_led->unset_active_state ();
1083                 }
1084         }
1085
1086         solo_button->set_active_state (solo_active_state (_route));
1087
1088         /* some changes to solo status can affect mute display, so catch up
1089          */
1090
1091         update_mute_display ();
1092 }
1093
1094 void
1095 RouteUI::solo_changed_so_update_mute ()
1096 {
1097         update_mute_display ();
1098 }
1099
1100 void
1101 RouteUI::mute_changed(void* /*src*/)
1102 {
1103         update_mute_display ();
1104 }
1105
1106 ActiveState
1107 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1108 {
1109         if (r->is_monitor()) {
1110                 return ActiveState(0);
1111         }
1112
1113
1114         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1115
1116                 if (r->muted ()) {
1117                         /* full mute */
1118                         return Gtkmm2ext::ExplicitActive;
1119                 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1120                         /* master is NEVER muted by others */
1121                         return Gtkmm2ext::ImplicitActive;
1122                 } else {
1123                         /* no mute at all */
1124                         return Gtkmm2ext::Off;
1125                 }
1126
1127         } else {
1128
1129                 if (r->muted()) {
1130                         /* full mute */
1131                         return Gtkmm2ext::ExplicitActive;
1132                 } else {
1133                         /* no mute at all */
1134                         return Gtkmm2ext::Off;
1135                 }
1136         }
1137
1138         return ActiveState(0);
1139 }
1140
1141 void
1142 RouteUI::update_mute_display ()
1143 {
1144         if (!_route) {
1145                 return;
1146         }
1147
1148         mute_button->set_active_state (mute_active_state (_session, _route));
1149 }
1150
1151 void
1152 RouteUI::route_rec_enable_changed ()
1153 {
1154         update_rec_display ();
1155         update_monitoring_display ();
1156 }
1157
1158 void
1159 RouteUI::session_rec_enable_changed ()
1160 {
1161         update_rec_display ();
1162         update_monitoring_display ();
1163 }
1164
1165 void
1166 RouteUI::update_rec_display ()
1167 {
1168         if (!rec_enable_button || !_route) {
1169                 return;
1170         }
1171
1172         if (_route->record_enabled()) {
1173                 switch (_session->record_status ()) {
1174                 case Session::Recording:
1175                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1176                         break;
1177
1178                 case Session::Disabled:
1179                 case Session::Enabled:
1180                         rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive);
1181                         break;
1182
1183                 }
1184
1185                 if (step_edit_item) {
1186                         step_edit_item->set_sensitive (false);
1187                 }
1188
1189         } else {
1190                 rec_enable_button->unset_active_state ();
1191
1192                 if (step_edit_item) {
1193                         step_edit_item->set_sensitive (true);
1194                 }
1195         }
1196
1197
1198         check_rec_enable_sensitivity ();
1199 }
1200
1201 void
1202 RouteUI::build_solo_menu (void)
1203 {
1204         using namespace Menu_Helpers;
1205
1206         solo_menu = new Menu;
1207         solo_menu->set_name ("ArdourContextMenu");
1208         MenuList& items = solo_menu->items();
1209         CheckMenuItem* check;
1210
1211         check = new CheckMenuItem(_("Solo Isolate"));
1212         check->set_active (_route->solo_isolated());
1213         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1214         items.push_back (CheckMenuElem(*check));
1215         solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
1216         check->show_all();
1217
1218         check = new CheckMenuItem(_("Solo Safe"));
1219         check->set_active (_route->solo_safe());
1220         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1221         items.push_back (CheckMenuElem(*check));
1222         solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
1223         check->show_all();
1224
1225         //items.push_back (SeparatorElem());
1226         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1227
1228 }
1229
1230 void
1231 RouteUI::build_mute_menu(void)
1232 {
1233         using namespace Menu_Helpers;
1234
1235         mute_menu = new Menu;
1236         mute_menu->set_name ("ArdourContextMenu");
1237
1238         MenuList& items = mute_menu->items();
1239
1240         pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
1241         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1242         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1243         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1244         pre_fader_mute_check->show_all();
1245
1246         post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
1247         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1248         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1249         items.push_back (CheckMenuElem(*post_fader_mute_check));
1250         post_fader_mute_check->show_all();
1251
1252         listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1253         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1254         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1255         items.push_back (CheckMenuElem(*listen_mute_check));
1256         listen_mute_check->show_all();
1257
1258         main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1259         init_mute_menu(MuteMaster::Main, main_mute_check);
1260         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1261         items.push_back (CheckMenuElem(*main_mute_check));
1262         main_mute_check->show_all();
1263
1264         //items.push_back (SeparatorElem());
1265         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1266
1267         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1268 }
1269
1270 void
1271 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1272 {
1273         check->set_active (_route->mute_points() & mp);
1274 }
1275
1276 void
1277 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1278 {
1279         if (check->get_active()) {
1280                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1281         } else {
1282                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1283         }
1284 }
1285
1286 void
1287 RouteUI::muting_change ()
1288 {
1289         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1290
1291         bool yn;
1292         MuteMaster::MutePoint current = _route->mute_points ();
1293
1294         yn = (current & MuteMaster::PreFader);
1295
1296         if (pre_fader_mute_check->get_active() != yn) {
1297                 pre_fader_mute_check->set_active (yn);
1298         }
1299
1300         yn = (current & MuteMaster::PostFader);
1301
1302         if (post_fader_mute_check->get_active() != yn) {
1303                 post_fader_mute_check->set_active (yn);
1304         }
1305
1306         yn = (current & MuteMaster::Listen);
1307
1308         if (listen_mute_check->get_active() != yn) {
1309                 listen_mute_check->set_active (yn);
1310         }
1311
1312         yn = (current & MuteMaster::Main);
1313
1314         if (main_mute_check->get_active() != yn) {
1315                 main_mute_check->set_active (yn);
1316         }
1317 }
1318
1319 bool
1320 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1321 {
1322         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1323                 return true;
1324         }
1325
1326         bool view = solo_isolated_led->active_state();
1327         bool model = _route->solo_isolated();
1328
1329         /* called BEFORE the view has changed */
1330
1331         if (ev->button == 1) {
1332                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1333
1334                         if (model) {
1335                                 /* disable isolate for all routes */
1336                                 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1337                         }
1338
1339                 } else {
1340                         if (model == view) {
1341
1342                                 /* flip just this route */
1343
1344                                 boost::shared_ptr<RouteList> rl (new RouteList);
1345                                 rl->push_back (_route);
1346                                 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1347                         }
1348                 }
1349         }
1350
1351         return true;
1352 }
1353
1354 bool
1355 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1356 {
1357         if (ev->button == 1) {
1358                 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1359                 return true;
1360         }
1361         return false;
1362 }
1363
1364 void
1365 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1366 {
1367         bool view = check->get_active();
1368         bool model = _route->solo_isolated();
1369
1370         /* called AFTER the view has changed */
1371
1372         if (model != view) {
1373                 _route->set_solo_isolated (view, this);
1374         }
1375 }
1376
1377 void
1378 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1379 {
1380         _route->set_solo_safe (check->get_active(), this);
1381 }
1382
1383 /** Ask the user to choose a colour, and then set all selected tracks
1384  *  to that colour.
1385  */
1386 void
1387 RouteUI::choose_color ()
1388 {
1389         bool picked;
1390         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1391
1392         if (picked) {
1393                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1394                         boost::bind (&RouteUI::set_color, _1, color)
1395                         );
1396         }
1397 }
1398
1399 /** Set the route's own color.  This may not be used for display if
1400  *  the route is in a group which shares its color with its routes.
1401  */
1402 void
1403 RouteUI::set_color (const Gdk::Color & c)
1404 {
1405         /* leave _color alone in the group case so that tracks can retain their
1406          * own pre-group colors.
1407          */
1408
1409         char buf[64];
1410         _color = c;
1411         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1412         
1413         /* note: we use the route state ID here so that color is the same for both
1414            the time axis view and the mixer strip
1415         */
1416         
1417         gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1418         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1419 }
1420
1421 /** @return GUI state ID for things that are common to the route in all its representations */
1422 string
1423 RouteUI::route_state_id () const
1424 {
1425         return string_compose (X_("route %1"), _route->id().to_s());
1426 }
1427
1428 int
1429 RouteUI::set_color_from_route ()
1430 {
1431         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1432
1433         if (str.empty()) {
1434                 return 1;
1435         }
1436
1437         int r, g, b;
1438
1439         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1440
1441         _color.set_red (r);
1442         _color.set_green (g);
1443         _color.set_blue (b);
1444
1445         return 0;
1446 }
1447
1448 void
1449 RouteUI::remove_this_route (bool apply_to_selection)
1450 {
1451         if (apply_to_selection) {
1452                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1453         } else {
1454                 if ((route()->is_master() || route()->is_monitor()) &&
1455                     !Config->get_allow_special_bus_removal()) {
1456                         MessageDialog msg (_("That would be bad news ...."),
1457                                            false,
1458                                            Gtk::MESSAGE_INFO,
1459                                    Gtk::BUTTONS_OK);
1460                         msg.set_secondary_text (string_compose (_(
1461 "Removing the master or monitor bus is such a bad idea\n\
1462 that %1 is not going to allow it.\n\
1463 \n\
1464 If you really want to do this sort of thing\n\
1465 edit your ardour.rc file to set the\n\
1466 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1467
1468                         msg.present ();
1469                         msg.run ();
1470                         return;
1471                 }
1472
1473                 vector<string> choices;
1474                 string prompt;
1475
1476                 if (is_track()) {
1477                         prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
1478                 } else {
1479                         prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
1480                 }
1481
1482                 choices.push_back (_("No, do nothing."));
1483                 choices.push_back (_("Yes, remove it."));
1484
1485                 string title;
1486                 if (is_track()) {
1487                         title = _("Remove track");
1488                 } else {
1489                         title = _("Remove bus");
1490                 }
1491
1492                 Choice prompter (title, prompt, choices);
1493
1494                 if (prompter.run () == 1) {
1495                         Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1496                 }
1497         }
1498 }
1499
1500 gint
1501 RouteUI::idle_remove_this_route (RouteUI *rui)
1502 {
1503         rui->_session->remove_route (rui->route());
1504         return false;
1505 }
1506
1507 /** @return true if this name should be used for the route, otherwise false */
1508 bool
1509 RouteUI::verify_new_route_name (const std::string& name)
1510 {
1511         if (name.find (':') == string::npos) {
1512                 return true;
1513         }
1514         
1515         MessageDialog colon_msg (
1516                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1517                 false, MESSAGE_QUESTION, BUTTONS_NONE
1518                 );
1519         
1520         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1521         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1522
1523         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1524 }
1525
1526 void
1527 RouteUI::route_rename ()
1528 {
1529         ArdourPrompter name_prompter (true);
1530         string result;
1531         bool done = false;
1532
1533         if (is_track()) {
1534                 name_prompter.set_title (_("Rename Track"));
1535         } else {
1536                 name_prompter.set_title (_("Rename Bus"));
1537         }
1538         name_prompter.set_prompt (_("New name:"));
1539         name_prompter.set_initial_text (_route->name());
1540         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1541         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1542         name_prompter.show_all ();
1543
1544         while (!done) {
1545                 switch (name_prompter.run ()) {
1546                 case Gtk::RESPONSE_ACCEPT:
1547                         name_prompter.get_result (result);
1548                         name_prompter.hide ();
1549                         if (result.length()) {
1550                                 if (verify_new_route_name (result)) {
1551                                         _route->set_name (result);
1552                                         done = true;
1553                                 } else {
1554                                         /* back to name prompter */
1555                                 }
1556
1557                         } else {
1558                                 /* nothing entered, just get out of here */
1559                                 done = true;
1560                         }
1561                         break;
1562                 default:
1563                         done = true;
1564                         break;
1565                 }
1566         }
1567
1568         return;
1569
1570 }
1571
1572 void
1573 RouteUI::property_changed (const PropertyChange& what_changed)
1574 {
1575         if (what_changed.contains (ARDOUR::Properties::name)) {
1576                 name_label.set_text (_route->name());
1577         }
1578 }
1579
1580 void
1581 RouteUI::set_route_active (bool a, bool apply_to_selection)
1582 {
1583         if (apply_to_selection) {
1584                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1585         } else {
1586                 _route->set_active (a, this);
1587         }
1588 }
1589
1590 void
1591 RouteUI::toggle_denormal_protection ()
1592 {
1593         if (denormal_menu_item) {
1594
1595                 bool x;
1596
1597                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1598
1599                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1600                         _route->set_denormal_protection (x);
1601                 }
1602         }
1603 }
1604
1605 void
1606 RouteUI::denormal_protection_changed ()
1607 {
1608         if (denormal_menu_item) {
1609                 denormal_menu_item->set_active (_route->denormal_protection());
1610         }
1611 }
1612
1613 void
1614 RouteUI::disconnect_input ()
1615 {
1616         _route->input()->disconnect (this);
1617 }
1618
1619 void
1620 RouteUI::disconnect_output ()
1621 {
1622         _route->output()->disconnect (this);
1623 }
1624
1625 bool
1626 RouteUI::is_track () const
1627 {
1628         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1629 }
1630
1631 boost::shared_ptr<Track>
1632 RouteUI::track() const
1633 {
1634         return boost::dynamic_pointer_cast<Track>(_route);
1635 }
1636
1637 bool
1638 RouteUI::is_audio_track () const
1639 {
1640         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1641 }
1642
1643 boost::shared_ptr<AudioTrack>
1644 RouteUI::audio_track() const
1645 {
1646         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1647 }
1648
1649 bool
1650 RouteUI::is_midi_track () const
1651 {
1652         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1653 }
1654
1655 boost::shared_ptr<MidiTrack>
1656 RouteUI::midi_track() const
1657 {
1658         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1659 }
1660
1661 bool
1662 RouteUI::has_audio_outputs () const
1663 {
1664         return (_route->n_outputs().n_audio() > 0);
1665 }
1666
1667 string
1668 RouteUI::name() const
1669 {
1670         return _route->name();
1671 }
1672
1673 void
1674 RouteUI::map_frozen ()
1675 {
1676         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1677
1678         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1679
1680         if (at) {
1681                 switch (at->freeze_state()) {
1682                 case AudioTrack::Frozen:
1683                         rec_enable_button->set_sensitive (false);
1684                         break;
1685                 default:
1686                         rec_enable_button->set_sensitive (true);
1687                         break;
1688                 }
1689         }
1690 }
1691
1692 void
1693 RouteUI::adjust_latency ()
1694 {
1695         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1696 }
1697
1698 void
1699 RouteUI::save_as_template ()
1700 {
1701         std::string path;
1702         std::string safe_name;
1703         string name;
1704
1705         path = ARDOUR::user_route_template_directory ();
1706
1707         if (g_mkdir_with_parents (path.c_str(), 0755)) {
1708                 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1709                 return;
1710         }
1711
1712         Prompter p (true); // modal
1713
1714         p.set_title (_("Save As Template"));
1715         p.set_prompt (_("Template name:"));
1716         p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1717         switch (p.run()) {
1718         case RESPONSE_ACCEPT:
1719                 break;
1720         default:
1721                 return;
1722         }
1723
1724         p.hide ();
1725         p.get_result (name, true);
1726
1727         safe_name = legalize_for_path (name);
1728         safe_name += template_suffix;
1729
1730         path = Glib::build_filename (path, safe_name);
1731
1732         _route->save_as_template (path, name);
1733 }
1734
1735 void
1736 RouteUI::check_rec_enable_sensitivity ()
1737 {
1738         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1739                 rec_enable_button->set_sensitive (false);
1740         } else {
1741                 rec_enable_button->set_sensitive (true);
1742         }
1743
1744         update_monitoring_display ();
1745 }
1746
1747 void
1748 RouteUI::parameter_changed (string const & p)
1749 {
1750         /* this handles RC and per-session parameter changes */
1751
1752         if (p == "disable-disarm-during-roll") {
1753                 check_rec_enable_sensitivity ();
1754         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1755                 set_button_names ();
1756         } else if (p == "auto-input") {
1757                 update_monitoring_display ();
1758         }
1759 }
1760
1761 void
1762 RouteUI::step_gain_up ()
1763 {
1764         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1765 }
1766
1767 void
1768 RouteUI::page_gain_up ()
1769 {
1770         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1771 }
1772
1773 void
1774 RouteUI::step_gain_down ()
1775 {
1776         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1777 }
1778
1779 void
1780 RouteUI::page_gain_down ()
1781 {
1782         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1783 }
1784
1785 void
1786 RouteUI::open_remote_control_id_dialog ()
1787 {
1788         ArdourDialog dialog (_("Remote Control ID"));
1789         SpinButton* spin = 0;
1790
1791         dialog.get_vbox()->set_border_width (18);
1792
1793         if (Config->get_remote_model() == UserOrdered) {
1794                 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1795                 
1796                 HBox* hbox = manage (new HBox);
1797                 hbox->set_spacing (6);
1798                 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1799                 spin = manage (new SpinButton);
1800                 spin->set_digits (0);
1801                 spin->set_increments (1, 10);
1802                 spin->set_range (0, limit);
1803                 spin->set_value (_route->remote_control_id());
1804                 hbox->pack_start (*spin);
1805                 dialog.get_vbox()->pack_start (*hbox);
1806                 
1807                 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1808                 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1809         } else {
1810                 Label* l = manage (new Label());
1811                 if (_route->is_master() || _route->is_monitor()) {
1812                         l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1813                                                          "The remote control ID of %3 cannot be changed."),
1814                                                        Glib::Markup::escape_text (_route->name()),
1815                                                        _route->remote_control_id(),
1816                                                        (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1817                 } else {
1818                         l->set_markup (string_compose (_("The remote control ID of %6 is: %3\n\n\n"
1819                                                          "Remote Control IDs are currently determined by track/bus ordering in %1\n\n"
1820                                                          "%4Use the User Interaction tab of the Preferences window if you want to change this%5"),
1821                                                        (Config->get_remote_model() == MixerOrdered ? _("the mixer") : _("the editor")),
1822                                                        (is_track() ? _("track") : _("bus")),
1823                                                        _route->remote_control_id(),
1824                                                        "<span size=\"small\" style=\"italic\">",
1825                                                        "</span>",
1826                                                        Glib::Markup::escape_text (_route->name())));
1827                 }
1828                 dialog.get_vbox()->pack_start (*l);
1829                 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1830         }
1831
1832         dialog.show_all ();
1833         int const r = dialog.run ();
1834
1835         if (r == RESPONSE_ACCEPT && spin) {
1836                 _route->set_remote_control_id (spin->get_value_as_int ());
1837         }
1838 }
1839
1840 void
1841 RouteUI::setup_invert_buttons ()
1842 {
1843         /* remove old invert buttons */
1844         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1845                 _invert_button_box.remove (**i);
1846         }
1847
1848         _invert_buttons.clear ();
1849
1850         if (!_route || !_route->input()) {
1851                 return;
1852         }
1853
1854         uint32_t const N = _route->input()->n_ports().n_audio ();
1855
1856         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1857
1858         for (uint32_t i = 0; i < to_add; ++i) {
1859                 ArdourButton* b = manage (new ArdourButton);
1860                 b->set_size_request(20,20);
1861                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1862                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1863
1864                 b->set_name (X_("invert button"));
1865                 if (to_add == 1) {
1866                         if (N > 1) {
1867                                 b->set_text (string_compose (X_("Ø (%1)"), N));
1868                         } else {
1869                                 b->set_text (X_("Ø"));
1870                         }
1871                 } else {
1872                         b->set_text (string_compose (X_("Ø%1"), i + 1));
1873                 }
1874
1875                 if (N <= _max_invert_buttons) {
1876                         UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) channel %1 of this track.  Right-click to show menu."), i + 1));
1877                 } else {
1878                         UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1879                 }
1880
1881                 _invert_buttons.push_back (b);
1882                 _invert_button_box.pack_start (*b);
1883         }
1884
1885         _invert_button_box.set_spacing (1);
1886         _invert_button_box.show_all ();
1887 }
1888
1889 void
1890 RouteUI::set_invert_button_state ()
1891 {
1892         ++_i_am_the_modifier;
1893
1894         uint32_t const N = _route->input()->n_ports().n_audio();
1895         if (N > _max_invert_buttons) {
1896
1897                 /* One button for many channels; explicit active if all channels are inverted,
1898                    implicit active if some are, off if none are.
1899                 */
1900
1901                 ArdourButton* b = _invert_buttons.front ();
1902                 
1903                 if (_route->phase_invert().count() == _route->phase_invert().size()) {
1904                         b->set_active_state (Gtkmm2ext::ExplicitActive);
1905                 } else if (_route->phase_invert().any()) {
1906                         b->set_active_state (Gtkmm2ext::ImplicitActive);
1907                 } else {
1908                         b->set_active_state (Gtkmm2ext::Off);
1909                 }
1910
1911         } else {
1912
1913                 /* One button per channel; just set active */
1914
1915                 int j = 0;
1916                 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1917                         (*i)->set_active (_route->phase_invert (j));
1918                 }
1919                 
1920         }
1921
1922         --_i_am_the_modifier;
1923 }
1924
1925 bool
1926 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1927 {
1928         if (ev->button == 1 && i < _invert_buttons.size()) {
1929                 uint32_t const N = _route->input()->n_ports().n_audio ();
1930                 if (N <= _max_invert_buttons) {
1931                         /* left-click inverts phase so long as we have a button per channel */
1932                         _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1933                         return true;
1934                 }
1935         }
1936         return false;
1937 }
1938
1939
1940 bool
1941 RouteUI::invert_press (GdkEventButton* ev)
1942 {
1943         using namespace Menu_Helpers;
1944
1945         uint32_t const N = _route->input()->n_ports().n_audio();
1946         if (N <= _max_invert_buttons && ev->button != 3) {
1947                 /* If we have an invert button per channel, we only pop
1948                    up a menu on right-click; left click is handled
1949                    on release.
1950                 */
1951                 return true;
1952         }
1953         
1954         delete _invert_menu;
1955         _invert_menu = new Menu;
1956         _invert_menu->set_name ("ArdourContextMenu");
1957         MenuList& items = _invert_menu->items ();
1958
1959         for (uint32_t i = 0; i < N; ++i) {
1960                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1961                 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1962                 ++_i_am_the_modifier;
1963                 e->set_active (_route->phase_invert (i));
1964                 --_i_am_the_modifier;
1965         }
1966
1967         _invert_menu->popup (0, ev->time);
1968
1969         return false;
1970 }
1971
1972 void
1973 RouteUI::invert_menu_toggled (uint32_t c)
1974 {
1975         if (_i_am_the_modifier) {
1976                 return;
1977         }
1978
1979         _route->set_phase_invert (c, !_route->phase_invert (c));
1980 }
1981
1982 void
1983 RouteUI::set_invert_sensitive (bool yn)
1984 {
1985         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1986                 (*b)->set_sensitive (yn);
1987         }
1988 }
1989
1990 void
1991 RouteUI::request_redraw ()
1992 {
1993         if (_route) {
1994                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1995         }
1996 }
1997
1998 /** The Route's gui_changed signal has been emitted */
1999 void
2000 RouteUI::route_gui_changed (string what_changed)
2001 {
2002         if (what_changed == "color") {
2003                 if (set_color_from_route () == 0) {
2004                         route_color_changed ();
2005                 }
2006         }
2007 }
2008
2009 /** @return the color that this route should use; it maybe its own,
2010     or it maybe that of its route group.
2011 */
2012 Gdk::Color
2013 RouteUI::color () const
2014 {
2015         RouteGroup* g = _route->route_group ();
2016         
2017         if (g && g->is_color()) {
2018                 return GroupTabs::group_color (g);
2019         }
2020
2021         return _color;
2022 }
2023
2024 void
2025 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2026 {
2027         _showing_sends_to = send_to;
2028         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2029 }
2030
2031 void
2032 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2033 {
2034         if (_route == send_to) {
2035                 show_sends_button->set_active (true);
2036                 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2037         } else {
2038                 show_sends_button->set_active (false);
2039                 send_blink_connection.disconnect ();
2040         }
2041 }
2042
2043 RouteGroup*
2044 RouteUI::route_group() const
2045 {
2046         return _route->route_group();
2047 }