97b779c50a0496d514101bfc664e0722174e11a1
[ardour.git] / gtk2_ardour / monitor_section.cc
1 #include <gdkmm/pixbuf.h>
2
3 #include "pbd/compose.h"
4 #include "pbd/error.h"
5
6 #include "gtkmm2ext/bindable_button.h"
7 #include "gtkmm2ext/tearoff.h"
8 #include "gtkmm2ext/actions.h"
9 #include "gtkmm2ext/motionfeedback.h"
10
11 #include "ardour/dB.h"
12 #include "ardour/monitor_processor.h"
13 #include "ardour/route.h"
14 #include "ardour/utils.h"
15
16 #include "ardour_ui.h"
17 #include "gui_thread.h"
18 #include "monitor_section.h"
19 #include "public_editor.h"
20 #include "volume_controller.h"
21 #include "utils.h"
22
23 #include "i18n.h"
24
25 using namespace ARDOUR;
26 using namespace Gtk;
27 using namespace Gtkmm2ext;
28 using namespace PBD;
29 using namespace std;
30
31 Glib::RefPtr<ActionGroup> MonitorSection::monitor_actions;
32 Glib::RefPtr<Gdk::Pixbuf> MonitorSection::big_knob_pixbuf;
33 Glib::RefPtr<Gdk::Pixbuf> MonitorSection::little_knob_pixbuf;
34
35 MonitorSection::MonitorSection (Session* s)
36         : AxisView (s)
37         , RouteUI (s)
38         , main_table (2, 3)
39         , _tearoff (0)
40         , gain_control (0)
41         , dim_control (0)
42         , solo_boost_control (0)
43         , solo_cut_control (0)
44         , solo_in_place_button (solo_model_group, _("SiP"))
45         , afl_button (solo_model_group, _("AFL"))
46         , pfl_button (solo_model_group, _("PFL"))
47         , cut_all_button (ArdourButton::led_default_elements)
48         , dim_all_button (ArdourButton::led_default_elements)
49         , mono_button (ArdourButton::led_default_elements)
50         , exclusive_solo_button (ArdourButton::led_default_elements)
51         , solo_mute_override_button (ArdourButton::led_default_elements)
52 {
53         Glib::RefPtr<Action> act;
54
55         if (!monitor_actions) {
56
57                 /* do some static stuff */
58
59                 register_actions ();
60
61         }
62
63         set_session (s);
64
65         VBox* spin_packer;
66         Label* spin_label;
67
68         /* Dim */
69
70         dim_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.01, 0.1, true, 30, 30, true);
71
72         HBox* dim_packer = manage (new HBox);
73         dim_packer->show ();
74
75         spin_label = manage (new Label (_("Dim")));
76         spin_packer = manage (new VBox);
77         spin_packer->show ();
78         spin_packer->set_spacing (6);
79         spin_packer->pack_start (*dim_control, false, false);
80         spin_packer->pack_start (*spin_label, false, false);
81
82         dim_packer->set_spacing (12);
83         dim_packer->pack_start (*spin_packer, true, false);
84
85         /* Rude Solo */
86
87         rude_solo_button.set_text (_("soloing"));
88         rude_solo_button.set_name ("rude solo");
89         rude_solo_button.show ();
90
91         rude_iso_button.set_text (_("isolated"));
92         rude_iso_button.set_name ("rude isolate");
93         rude_iso_button.show ();
94
95         rude_audition_button.set_text (_("auditioning"));
96         rude_audition_button.set_name ("rude audition");
97         rude_audition_button.show ();
98
99         ARDOUR_UI::Blink.connect (sigc::mem_fun (*this, &MonitorSection::do_blink));
100
101         rude_solo_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_solo));
102         UI::instance()->set_tip (rude_solo_button, _("When active, something is soloed.\nClick to de-solo everything"));
103
104         rude_iso_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_isolate));
105         UI::instance()->set_tip (rude_iso_button, _("When active, something is solo-isolated.\nClick to de-isolate everything"));
106
107         rude_audition_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_audition));
108         UI::instance()->set_tip (rude_audition_button, _("When active, auditioning is active.\nClick to stop the audition"));
109
110         solo_model_box.set_spacing (6);
111         solo_model_box.pack_start (solo_in_place_button, false, false);
112         solo_model_box.pack_start (afl_button, false, false);
113         solo_model_box.pack_start (pfl_button, false, false);
114
115         solo_in_place_button.show ();
116         afl_button.show ();
117         pfl_button.show ();
118         solo_model_box.show ();
119
120         act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
121         if (act) {
122                 act->connect_proxy (solo_in_place_button);
123         }
124
125         act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
126         if (act) {
127                 act->connect_proxy (afl_button);
128         }
129
130         act = ActionManager::get_action (X_("Solo"), X_("solo-use-pfl"));
131         if (act) {
132                 act->connect_proxy (pfl_button);
133         }
134
135         /* Solo Boost */
136
137         solo_boost_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.01, 0.1, true, 30, 30, true);
138
139         HBox* solo_packer = manage (new HBox);
140         solo_packer->set_spacing (12);
141         solo_packer->show ();
142
143         spin_label = manage (new Label (_("Solo Boost")));
144         spin_packer = manage (new VBox);
145         spin_packer->show ();
146         spin_packer->set_spacing (6);
147         spin_packer->pack_start (*solo_boost_control, false, false);
148         spin_packer->pack_start (*spin_label, false, false);
149
150         solo_packer->pack_start (*spin_packer, false, true);
151
152         /* Solo (SiP) cut */
153
154         solo_cut_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.1, 0.5, true, 30, 30, true);
155
156         spin_label = manage (new Label (_("SiP Cut")));
157         spin_packer = manage (new VBox);
158         spin_packer->show ();
159         spin_packer->set_spacing (6);
160         spin_packer->pack_start (*solo_cut_control, false, false);
161         spin_packer->pack_start (*spin_label, false, false);
162
163         solo_packer->pack_start (*spin_packer, false, true);
164
165         exclusive_solo_button.set_text (_("Exclusive"));
166         exclusive_solo_button.set_name (X_("monitor solo exclusive"));
167         ARDOUR_UI::instance()->set_tip (&exclusive_solo_button, _("Exclusive solo means that only 1 solo is active at a time"));
168
169         act = ActionManager::get_action (X_("Monitor"), X_("toggle-exclusive-solo"));
170         if (act) {
171                 exclusive_solo_button.set_related_action (act);
172         }
173
174         solo_mute_override_button.set_text (_("Solo/Mute"));
175         solo_mute_override_button.set_name (X_("monitor solo override"));
176         ARDOUR_UI::instance()->set_tip (&solo_mute_override_button, _("If enabled, solo will override mute\n(a soloed & muted track or bus will be audible)"));
177
178         act = ActionManager::get_action (X_("Monitor"), X_("toggle-mute-overrides-solo"));
179         if (act) {
180                 solo_mute_override_button.set_related_action (act);
181         }
182
183         HBox* solo_opt_box = manage (new HBox);
184         solo_opt_box->set_spacing (12);
185         solo_opt_box->set_homogeneous (true);
186         solo_opt_box->pack_start (exclusive_solo_button);
187         solo_opt_box->pack_start (solo_mute_override_button);
188         solo_opt_box->show ();
189
190         upper_packer.set_spacing (12);
191
192         Gtk::HBox* rude_box = manage (new HBox);
193         rude_box->pack_start (rude_solo_button, true, true);
194         rude_box->pack_start (rude_iso_button, true, true);
195
196         upper_packer.pack_start (*rude_box, false, false);
197         upper_packer.pack_start (rude_audition_button, false, false);
198         upper_packer.pack_start (solo_model_box, false, false);
199         upper_packer.pack_start (*solo_opt_box, false, false);
200         upper_packer.pack_start (*solo_packer, false, false);
201
202         cut_all_button.set_text (_("MUTE"));
203         cut_all_button.set_name ("monitor section cut");
204         cut_all_button.set_name (X_("monitor section cut"));
205         cut_all_button.set_size_request (50,50);
206         cut_all_button.show ();
207
208         act = ActionManager::get_action (X_("Monitor"), X_("monitor-cut-all"));
209         if (act) {
210                 cut_all_button.set_related_action (act);
211         }
212
213         dim_all_button.set_text (_("dim"));
214         dim_all_button.set_name ("monitor section dim");
215         // dim_all_button.set_size_request (50,50);
216         act = ActionManager::get_action (X_("Monitor"), X_("monitor-dim-all"));
217         if (act) {
218                 dim_all_button.set_related_action (act);
219         }
220
221         mono_button.set_text (_("mono"));
222         mono_button.set_name ("monitor section mono");
223         // mono_button.set_size_request (50,50);
224         act = ActionManager::get_action (X_("Monitor"), X_("monitor-mono"));
225         if (act) {
226                 mono_button.set_related_action (act);
227         }
228
229         HBox* bbox = manage (new HBox);
230
231         bbox->set_spacing (12);
232         bbox->pack_start (mono_button, true, true);
233         bbox->pack_start (dim_all_button, true, true);
234
235         lower_packer.set_spacing (12);
236         lower_packer.pack_start (*bbox, false, false);
237         lower_packer.pack_start (cut_all_button, false, false);
238
239         /* Gain */
240
241         gain_control = new VolumeController (big_knob_pixbuf, boost::shared_ptr<Controllable>(), 1.0, 0.01, 0.1, true, 80, 80, false);
242
243         spin_label = manage (new Label (_("Monitor")));
244         spin_packer = manage (new VBox);
245         spin_packer->show ();
246         spin_packer->set_spacing (6);
247         spin_packer->pack_start (*gain_control, false, false);
248         spin_packer->pack_start (*spin_label, false, false);
249
250         lower_packer.pack_start (*spin_packer, true, true);
251
252         main_table_scroller.add (main_table);
253         main_table_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
254         main_table_scroller.set_size_request (-1, 150);
255         main_table_scroller.set_shadow_type (Gtk::SHADOW_NONE);
256         main_table_scroller.show ();
257
258         vpacker.set_border_width (12);
259         vpacker.set_spacing (12);
260         vpacker.pack_start (upper_packer, false, false);
261         vpacker.pack_start (*dim_packer, false, false);
262         vpacker.pack_start (main_table_scroller, false, false);
263         vpacker.pack_start (lower_packer, false, false);
264
265         hpacker.set_border_width (12);
266         hpacker.set_spacing (12);
267         hpacker.pack_start (vpacker, true, true);
268
269         gain_control->show_all ();
270         dim_control->show_all ();
271         solo_boost_control->show_all ();
272
273         main_table.show ();
274         hpacker.show ();
275         upper_packer.show ();
276         lower_packer.show ();
277         vpacker.show ();
278
279         populate_buttons ();
280         map_state ();
281         assign_controllables ();
282
283         _tearoff = new TearOff (hpacker);
284
285         /* if torn off, make this a normal window */
286         _tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
287         _tearoff->tearoff_window().set_title (X_("Monitor"));
288         _tearoff->tearoff_window().signal_key_press_event().connect (sigc::ptr_fun (forward_key_press), false);
289
290         /* catch changes that affect us */
291
292         Config->ParameterChanged.connect (config_connection, invalidator (*this), ui_bind (&MonitorSection::parameter_changed, this, _1), gui_context());
293 }
294
295 MonitorSection::~MonitorSection ()
296 {
297         for (ChannelButtons::iterator i = _channel_buttons.begin(); i != _channel_buttons.end(); ++i) {
298                 delete *i;
299         }
300
301         _channel_buttons.clear ();
302
303         delete gain_control;
304         delete dim_control;
305         delete solo_boost_control;
306         delete _tearoff;
307 }
308
309 void
310 MonitorSection::set_session (Session* s)
311 {
312         AxisView::set_session (s);
313
314         if (_session) {
315
316                 _route = _session->monitor_out ();
317
318                 if (_route) {
319                         /* session with monitor section */
320                         _monitor = _route->monitor_control ();
321                         assign_controllables ();
322                 } else {
323                         /* session with no monitor section */
324                         _monitor.reset ();
325                         _route.reset ();
326                 }
327
328         } else {
329                 /* no session */
330
331                 _monitor.reset ();
332                 _route.reset ();
333                 control_connections.drop_connections ();
334                 rude_iso_button.unset_active_state ();
335                 rude_solo_button.unset_active_state ();
336
337                 assign_controllables ();
338         }
339 }
340
341 MonitorSection::ChannelButtonSet::ChannelButtonSet ()
342         : cut (ArdourButton::just_led_default_elements)
343         , dim (ArdourButton::just_led_default_elements)
344         , solo (ArdourButton::just_led_default_elements)
345         , invert (ArdourButton::just_led_default_elements)
346 {
347         cut.set_diameter (3);
348         dim.set_diameter (3);
349         solo.set_diameter (3);
350         invert.set_diameter (3);
351
352         cut.set_name (X_("monitor section cut"));
353         dim.set_name (X_("monitor section dim"));
354         solo.set_name (X_("monitor section solo"));
355         invert.set_name (X_("monitor section invert"));
356
357         cut.unset_flags (Gtk::CAN_FOCUS);
358         dim.unset_flags (Gtk::CAN_FOCUS);
359         solo.unset_flags (Gtk::CAN_FOCUS);
360         invert.unset_flags (Gtk::CAN_FOCUS);
361 }
362
363 void
364 MonitorSection::populate_buttons ()
365 {
366         if (!_monitor) {
367                 return;
368         }
369
370         Glib::RefPtr<Action> act;
371         uint32_t nchans = _monitor->output_streams().n_audio();
372
373         main_table.resize (nchans+1, 5);
374         main_table.set_col_spacings (6);
375         main_table.set_row_spacings (6);
376         main_table.set_homogeneous (true);
377
378         Label* l1 = manage (new Label (X_("out")));
379         main_table.attach (*l1, 0, 1, 0, 1, SHRINK|FILL, SHRINK|FILL);
380         l1 = manage (new Label (X_("cut")));
381         main_table.attach (*l1, 1, 2, 0, 1, SHRINK|FILL, SHRINK|FILL);
382         l1 = manage (new Label (X_("dim")));
383         main_table.attach (*l1, 2, 3, 0, 1, SHRINK|FILL, SHRINK|FILL);
384         l1 = manage (new Label (X_("solo")));
385         main_table.attach (*l1, 3, 4, 0, 1, SHRINK|FILL, SHRINK|FILL);
386         l1 = manage (new Label (X_("inv")));
387         main_table.attach (*l1, 4, 5, 0, 1, SHRINK|FILL, SHRINK|FILL);
388
389         const uint32_t row_offset = 1;
390
391         for (uint32_t i = 0; i < nchans; ++i) {
392
393                 string l;
394                 char buf[64];
395
396                 if (nchans == 2) {
397                         if (i == 0) {
398                                 l = "L";
399                         } else {
400                                 l = "R";
401                         }
402                 } else {
403                         char buf[32];
404                         snprintf (buf, sizeof (buf), "%d", i+1);
405                         l = buf;
406                 }
407
408                 Label* label = manage (new Label (l));
409                 main_table.attach (*label, 0, 1, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
410
411                 ChannelButtonSet* cbs = new ChannelButtonSet;
412
413                 _channel_buttons.push_back (cbs);
414
415                 main_table.attach (cbs->cut, 1, 2, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
416                 main_table.attach (cbs->dim, 2, 3, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
417                 main_table.attach (cbs->solo, 3, 4, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
418                 main_table.attach (cbs->invert, 4, 5, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
419
420                 snprintf (buf, sizeof (buf), "monitor-cut-%u", i+1);
421                 act = ActionManager::get_action (X_("Monitor"), buf);
422                 if (act) {
423                         cbs->cut.set_related_action (act);
424                 }
425
426                 snprintf (buf, sizeof (buf), "monitor-dim-%u", i+1);
427                 act = ActionManager::get_action (X_("Monitor"), buf);
428                 if (act) {
429                         cbs->dim.set_related_action (act);
430                 }
431
432                 snprintf (buf, sizeof (buf), "monitor-solo-%u", i+1);
433                 act = ActionManager::get_action (X_("Monitor"), buf);
434                 if (act) {
435                         cbs->solo.set_related_action (act);
436                 }
437
438                 snprintf (buf, sizeof (buf), "monitor-invert-%u", i+1);
439                 act = ActionManager::get_action (X_("Monitor"), buf);
440                 if (act) {
441                         cbs->invert.set_related_action (act);
442                 }
443         }
444
445         main_table.show_all ();
446 }
447
448 void
449 MonitorSection::set_button_names ()
450 {
451         rec_enable_button_label.set_text ("rec");
452         mute_button_label.set_text ("rec");
453         solo_button_label.set_text ("rec");
454 }
455
456 void
457 MonitorSection::toggle_exclusive_solo ()
458 {
459         if (!_monitor) {
460                 return;
461         }
462
463         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "toggle-exclusive-solo");
464         if (act) {
465                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
466                 Config->set_exclusive_solo (tact->get_active());
467         }
468
469 }
470
471
472 void
473 MonitorSection::toggle_mute_overrides_solo ()
474 {
475         if (!_monitor) {
476                 return;
477         }
478
479         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "toggle-mute-overrides-solo");
480         if (act) {
481                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
482                 Config->set_solo_mute_override (tact->get_active());
483         }
484 }
485
486 void
487 MonitorSection::dim_all ()
488 {
489         if (!_monitor) {
490                 return;
491         }
492
493         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
494         if (act) {
495                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
496                 _monitor->set_dim_all (tact->get_active());
497         }
498
499 }
500
501 void
502 MonitorSection::cut_all ()
503 {
504         if (!_monitor) {
505                 return;
506         }
507
508         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
509         if (act) {
510                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
511                 _monitor->set_cut_all (tact->get_active());
512         }
513 }
514
515 void
516 MonitorSection::mono ()
517 {
518         if (!_monitor) {
519                 return;
520         }
521
522         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
523         if (act) {
524                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
525                 _monitor->set_mono (tact->get_active());
526         }
527 }
528
529 void
530 MonitorSection::cut_channel (uint32_t chn)
531 {
532         if (!_monitor) {
533                 return;
534         }
535
536         char buf[64];
537         snprintf (buf, sizeof (buf), "monitor-cut-%u", chn);
538
539         --chn; // 0-based in backend
540
541         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
542         if (act) {
543                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
544                 _monitor->set_cut (chn, tact->get_active());
545         }
546 }
547
548 void
549 MonitorSection::dim_channel (uint32_t chn)
550 {
551         if (!_monitor) {
552                 return;
553         }
554
555         char buf[64];
556         snprintf (buf, sizeof (buf), "monitor-dim-%u", chn);
557
558         --chn; // 0-based in backend
559
560         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
561         if (act) {
562                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
563                 _monitor->set_dim (chn, tact->get_active());
564         }
565
566 }
567
568 void
569 MonitorSection::solo_channel (uint32_t chn)
570 {
571         if (!_monitor) {
572                 return;
573         }
574
575         char buf[64];
576         snprintf (buf, sizeof (buf), "monitor-solo-%u", chn);
577
578         --chn; // 0-based in backend
579
580         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
581         if (act) {
582                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
583                 _monitor->set_solo (chn, tact->get_active());
584         }
585
586 }
587
588 void
589 MonitorSection::invert_channel (uint32_t chn)
590 {
591         if (!_monitor) {
592                 return;
593         }
594
595         char buf[64];
596         snprintf (buf, sizeof (buf), "monitor-invert-%u", chn);
597
598         --chn; // 0-based in backend
599
600         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
601         if (act) {
602                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
603                 _monitor->set_polarity (chn, tact->get_active());
604         }
605 }
606
607 void
608 MonitorSection::register_actions ()
609 {
610         string action_name;
611         string action_descr;
612         Glib::RefPtr<Action> act;
613
614         monitor_actions = ActionGroup::create (X_("Monitor"));
615         ActionManager::add_action_group (monitor_actions);
616
617         ActionManager::register_toggle_action (monitor_actions, "monitor-mono", "", "Switch monitor to mono",
618                                                sigc::mem_fun (*this, &MonitorSection::mono));
619
620         ActionManager::register_toggle_action (monitor_actions, "monitor-cut-all", "", "Cut monitor",
621                                                sigc::mem_fun (*this, &MonitorSection::cut_all));
622
623         ActionManager::register_toggle_action (monitor_actions, "monitor-dim-all", "", "Dim monitor",
624                                                sigc::mem_fun (*this, &MonitorSection::dim_all));
625
626         act = ActionManager::register_toggle_action (monitor_actions, "toggle-exclusive-solo", "", "Toggle exclusive solo mode",
627                                                sigc::mem_fun (*this, &MonitorSection::toggle_exclusive_solo));
628
629         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
630         tact->set_active (Config->get_exclusive_solo());
631
632         act = ActionManager::register_toggle_action (monitor_actions, "toggle-mute-overrides-solo", "", "Toggle mute overrides solo mode",
633                                                      sigc::mem_fun (*this, &MonitorSection::toggle_mute_overrides_solo));
634
635         tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
636         tact->set_active (Config->get_solo_mute_override());
637
638
639         /* note the 1-based counting (for naming - backend uses 0-based) */
640
641         for (uint32_t chn = 1; chn <= 16; ++chn) {
642
643                 action_name = string_compose (X_("monitor-cut-%1"), chn);
644                 action_descr = string_compose (_("Cut monitor channel %1"), chn);
645                 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
646                                                        sigc::bind (sigc::mem_fun (*this, &MonitorSection::cut_channel), chn));
647
648                 action_name = string_compose (X_("monitor-dim-%1"), chn);
649                 action_descr = string_compose (_("Dim monitor channel %1"), chn+1);
650                 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
651                                                        sigc::bind (sigc::mem_fun (*this, &MonitorSection::dim_channel), chn));
652
653                 action_name = string_compose (X_("monitor-solo-%1"), chn);
654                 action_descr = string_compose (_("Solo monitor channel %1"), chn+1);
655                 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
656                                                        sigc::bind (sigc::mem_fun (*this, &MonitorSection::solo_channel), chn));
657
658                 action_name = string_compose (X_("monitor-invert-%1"), chn);
659                 action_descr = string_compose (_("Invert monitor channel %1"), chn+1);
660                 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
661                                                        sigc::bind (sigc::mem_fun (*this, &MonitorSection::invert_channel), chn));
662
663         }
664
665
666         Glib::RefPtr<ActionGroup> solo_actions = ActionGroup::create (X_("Solo"));
667         RadioAction::Group solo_group;
668
669         ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-in-place", "", "In-place solo",
670                                               sigc::mem_fun (*this, &MonitorSection::solo_use_in_place));
671         ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-afl", "", "After Fade Listen (AFL) solo",
672                                               sigc::mem_fun (*this, &MonitorSection::solo_use_afl));
673         ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-pfl", "", "Pre Fade Listen (PFL) solo",
674                                               sigc::mem_fun (*this, &MonitorSection::solo_use_pfl));
675
676         ActionManager::add_action_group (solo_actions);
677 }
678
679 void
680 MonitorSection::solo_use_in_place ()
681 {
682         /* this is driven by a toggle on a radio group, and so is invoked twice,
683            once for the item that became inactive and once for the one that became
684            active.
685         */
686
687         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
688
689         if (act) {
690                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
691                 if (ract) {
692                         Config->set_solo_control_is_listen_control (!ract->get_active());
693                 }
694         }
695 }
696
697 void
698 MonitorSection::solo_use_afl ()
699 {
700         /* this is driven by a toggle on a radio group, and so is invoked twice,
701            once for the item that became inactive and once for the one that became
702            active.
703         */
704
705         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
706         if (act) {
707                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
708                 if (ract) {
709                         if (ract->get_active()) {
710                                 Config->set_listen_position (AfterFaderListen);
711                                 Config->set_solo_control_is_listen_control (true);
712                         }
713                 }
714         }
715 }
716
717 void
718 MonitorSection::solo_use_pfl ()
719 {
720         /* this is driven by a toggle on a radio group, and so is invoked twice,
721            once for the item that became inactive and once for the one that became
722            active.
723         */
724
725         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
726         if (act) {
727                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
728                 if (ract) {
729                         if (ract->get_active()) {
730                                 Config->set_listen_position (PreFaderListen);
731                                 Config->set_solo_control_is_listen_control (true);
732                         }
733                 }
734         }
735 }
736
737 void
738 MonitorSection::setup_knob_images ()
739 {
740         
741         try {
742                 uint32_t c = ARDOUR_UI::config()->color_by_name ("monitor knob");
743                 char buf[16];
744                 snprintf (buf, 16, "#%x", (c >> 8));
745                 cerr << "Motion feedback using " << buf << endl;
746                 MotionFeedback::set_lamp_color (buf);
747                 big_knob_pixbuf = MotionFeedback::render_pixbuf (80);
748
749         }  catch (...) {
750
751                 error << "No usable large knob image" << endmsg;
752                 throw failed_constructor ();
753         }
754
755         if (!big_knob_pixbuf) {
756                 error << "No usable large knob image" << endmsg;
757                 throw failed_constructor ();
758         }
759
760         try {
761
762                 little_knob_pixbuf = MotionFeedback::render_pixbuf (30);
763
764         }  catch (...) {
765
766                 error << "No usable small knob image" << endmsg;
767                 throw failed_constructor ();
768         }
769
770         if (!little_knob_pixbuf) {
771                 error << "No usable small knob image" << endmsg;
772                 throw failed_constructor ();
773         }
774
775 }
776
777 void
778 MonitorSection::update_solo_model ()
779 {
780         const char* action_name = 0;
781         Glib::RefPtr<Action> act;
782
783         if (Config->get_solo_control_is_listen_control()) {
784                 switch (Config->get_listen_position()) {
785                 case AfterFaderListen:
786                         action_name = X_("solo-use-afl");
787                         break;
788                 case PreFaderListen:
789                         action_name = X_("solo-use-pfl");
790                         break;
791                 }
792         } else {
793                 action_name = X_("solo-use-in-place");
794         }
795
796         act = ActionManager::get_action (X_("Solo"), action_name);
797         if (act) {
798                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
799                 if (ract) {
800                         ract->set_active (true);
801                 }
802         }
803 }
804
805 void
806 MonitorSection::map_state ()
807 {
808         if (!_route || !_monitor) {
809                 return;
810         }
811
812         Glib::RefPtr<Action> act;
813
814         update_solo_model ();
815
816         act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
817         if (act) {
818                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
819                 if (tact) {
820                         tact->set_active (_monitor->cut_all());
821                 }
822         }
823
824         act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
825         if (act) {
826                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
827                 if (tact) {
828                         tact->set_active (_monitor->dim_all());
829                 }
830         }
831
832         act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
833         if (act) {
834                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
835                 if (tact) {
836                         tact->set_active (_monitor->mono());
837                 }
838         }
839
840         uint32_t nchans = _monitor->output_streams().n_audio();
841
842         assert (nchans == _channel_buttons.size ());
843
844         for (uint32_t n = 0; n < nchans; ++n) {
845
846                 char action_name[32];
847
848                 snprintf (action_name, sizeof (action_name), "monitor-cut-%u", n+1);
849                 act = ActionManager::get_action (X_("Monitor"), action_name);
850                 if (act) {
851                         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
852                         if (tact) {
853                                 tact->set_active (_monitor->cut (n));
854                         }
855                 }
856
857                 snprintf (action_name, sizeof (action_name), "monitor-dim-%u", n+1);
858                 act = ActionManager::get_action (X_("Monitor"), action_name);
859                 if (act) {
860                         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
861                         if (tact) {
862                                 tact->set_active (_monitor->dimmed (n));
863                         }
864                 }
865
866                 snprintf (action_name, sizeof (action_name), "monitor-solo-%u", n+1);
867                 act = ActionManager::get_action (X_("Monitor"), action_name);
868                 if (act) {
869                         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
870                         if (tact) {
871                                 tact->set_active (_monitor->soloed (n));
872                         }
873                 }
874
875                 snprintf (action_name, sizeof (action_name), "monitor-invert-%u", n+1);
876                 act = ActionManager::get_action (X_("Monitor"), action_name);
877                 if (act) {
878                         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
879                         if (tact) {
880                                 tact->set_active (_monitor->inverted (n));
881                         }
882                 }
883         }
884 }
885
886 void
887 MonitorSection::do_blink (bool onoff)
888 {
889         solo_blink (onoff);
890         audition_blink (onoff);
891 }
892
893 void
894 MonitorSection::audition_blink (bool onoff)
895 {
896         if (_session == 0) {
897                 return;
898         }
899
900         if (_session->is_auditioning()) {
901                 if (onoff) {
902                         rude_audition_button.set_active_state (CairoWidget::Active);
903                 } else {
904                         rude_audition_button.unset_active_state ();
905                 }
906         } else {
907                 rude_audition_button.unset_active_state ();
908         }
909 }
910
911 void
912 MonitorSection::solo_blink (bool onoff)
913 {
914         if (_session == 0) {
915                 return;
916         }
917
918         if (_session->soloing() || _session->listening()) {
919                 if (onoff) {
920                         rude_solo_button.set_active_state (CairoWidget::Active);
921                 } else {
922                         rude_solo_button.unset_active_state ();
923                 }
924
925                 if (_session->soloing()) {
926                         if (_session->solo_isolated()) {
927                                 rude_iso_button.set_active_state (CairoWidget::Active);
928                         }
929                 }
930
931         } else {
932                 // rude_solo_button.set_active (false);
933                 rude_solo_button.unset_active_state ();
934                 rude_iso_button.unset_active_state ();
935         }
936 }
937
938 bool
939 MonitorSection::cancel_solo (GdkEventButton*)
940 {
941         if (_session) {
942                 if (_session->soloing()) {
943                         _session->set_solo (_session->get_routes(), false);
944                 } else if (_session->listening()) {
945                         _session->set_listen (_session->get_routes(), false);
946                 }
947         }
948
949         return true;
950 }
951
952 bool
953 MonitorSection::cancel_isolate (GdkEventButton*)
954 {
955         if (_session) {
956                 boost::shared_ptr<RouteList> rl (_session->get_routes ());
957                 _session->set_solo_isolated (rl, false, Session::rt_cleanup, true);
958         }
959
960         return true;
961 }
962
963 bool
964 MonitorSection::cancel_audition (GdkEventButton*)
965 {
966         if (_session) {
967                 _session->cancel_audition();
968         }
969         return true;
970 }
971
972 void
973 MonitorSection::parameter_changed (std::string name)
974 {
975         if (name == "solo-control-is-listen-control" ||
976             name == "listen-position") {
977                 update_solo_model ();
978         }
979 }
980
981 void
982 MonitorSection::assign_controllables ()
983 {
984         boost::shared_ptr<Controllable> none;
985
986         if (!gain_control) {
987                 /* too early - GUI controls not set up yet */
988                 return;
989         }
990
991         if (_session) {
992                 solo_cut_control->set_controllable (_session->solo_cut_control());
993         } else {
994                 solo_cut_control->set_controllable (none);
995         }
996
997         if (_route) {
998                 gain_control->set_controllable (_route->gain_control());
999         } else {
1000                 gain_control->set_controllable (none);
1001         }
1002
1003         if (_monitor) {
1004
1005                 cut_all_button.set_controllable (_monitor->cut_control());
1006                 cut_all_button.watch ();
1007                 dim_all_button.set_controllable (_monitor->dim_control());
1008                 dim_all_button.watch ();
1009                 mono_button.set_controllable (_monitor->mono_control());
1010                 mono_button.watch ();
1011
1012                 dim_control->set_controllable (_monitor->dim_level_control ());
1013                 solo_boost_control->set_controllable (_monitor->solo_boost_control ());
1014
1015         } else {
1016
1017                 cut_all_button.set_controllable (none);
1018                 dim_all_button.set_controllable (none);
1019                 mono_button.set_controllable (none);
1020
1021                 dim_control->set_controllable (none);
1022                 solo_boost_control->set_controllable (none);
1023         }
1024 }
1025
1026 string
1027 MonitorSection::state_id() const
1028 {
1029         return "monitor-section";
1030 }