lots of tricks & tweaks related to the monitor section and All That It Uses
[ardour2.git] / gtk2_ardour / monitor_section.cc
blob5f779c6422a6441478e522e56b4be49a277f6b2a
1 #include <gdkmm/pixbuf.h>
3 #include "pbd/compose.h"
4 #include "pbd/error.h"
6 #include "gtkmm2ext/bindable_button.h"
7 #include "gtkmm2ext/tearoff.h"
8 #include "gtkmm2ext/actions.h"
10 #include "ardour/dB.h"
11 #include "ardour/monitor_processor.h"
12 #include "ardour/route.h"
13 #include "ardour/utils.h"
15 #include "ardour_ui.h"
16 #include "monitor_section.h"
17 #include "public_editor.h"
18 #include "utils.h"
19 #include "volume_controller.h"
21 #include "i18n.h"
23 using namespace ARDOUR;
24 using namespace Gtk;
25 using namespace Gtkmm2ext;
26 using namespace PBD;
27 using namespace std;
29 Glib::RefPtr<ActionGroup> MonitorSection::monitor_actions;
30 Glib::RefPtr<Gdk::Pixbuf> MonitorSection::big_knob_pixbuf;
31 Glib::RefPtr<Gdk::Pixbuf> MonitorSection::little_knob_pixbuf;
33 static bool
34 fixup_prelight (GdkEventCrossing* /* ignored */, GtkWidget* widget)
36 GtkRcStyle* style = gtk_rc_style_copy (gtk_widget_get_modifier_style (widget));
37 int current = gtk_widget_get_state (widget);
39 style->fg[GTK_STATE_PRELIGHT] = style->fg[current];
40 style->bg[GTK_STATE_PRELIGHT] = style->bg[current];
42 gtk_widget_modify_style(widget, style);
43 g_object_unref(style);
45 return false;
48 static void
49 block_prelight (Gtk::Widget& w)
51 w.signal_enter_notify_event().connect (sigc::bind (sigc::ptr_fun (fixup_prelight), w.gobj()), false);
54 MonitorSection::MonitorSection (Session* s)
55 : AxisView (s)
56 , RouteUI (s)
57 , main_table (2, 3)
58 , _tearoff (0)
59 , gain_adjustment (1.0, 0.0, 1.0, 0.01, 0.1)
60 , gain_control (0)
61 , dim_adjustment (0.2, 0.0, 1.0, 0.01, 0.1)
62 , dim_control (0)
63 , solo_boost_adjustment (1.0, 1.0, 2.0, 0.01, 0.1)
64 , solo_boost_control (0)
65 , solo_cut_adjustment (0.0, 0.0, 1.0, 0.01, 0.1)
66 , solo_cut_control (0)
67 , solo_in_place_button (solo_model_group, _("SiP"))
68 , afl_button (solo_model_group, _("AFL"))
69 , pfl_button (solo_model_group, _("PFL"))
70 , cut_all_button (_("MUTE"))
71 , dim_all_button (_("dim"))
72 , mono_button (_("mono"))
73 , rude_solo_button (_("soloing"))
76 Glib::RefPtr<Action> act;
78 if (!monitor_actions) {
80 /* do some static stuff */
82 register_actions ();
86 set_session (s);
88 VBox* spin_packer;
89 Label* spin_label;
91 /* Dim */
93 dim_control = new VolumeController (little_knob_pixbuf, &dim_adjustment, false, 30, 30);
94 dim_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MonitorSection::dim_level_changed));
96 HBox* dim_packer = manage (new HBox);
97 dim_packer->show ();
99 spin_label = manage (new Label (_("Dim Cut")));
100 spin_packer = manage (new VBox);
101 spin_packer->show ();
102 spin_packer->set_spacing (6);
103 spin_packer->pack_start (*dim_control, false, false);
104 spin_packer->pack_start (*spin_label, false, false);
106 dim_packer->set_spacing (12);
107 dim_packer->pack_start (*spin_packer, true, true);
109 /* Rude Solo */
111 rude_solo_button.set_name ("TransportSoloAlert");
112 rude_solo_button.show ();
113 block_prelight (rude_solo_button);
115 ARDOUR_UI::Blink.connect (sigc::mem_fun (*this, &MonitorSection::solo_blink));
116 rude_solo_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_solo), false);
117 UI::instance()->set_tip (rude_solo_button, _("When active, something is soloed.\nClick to de-solo everything"));
120 solo_model_box.set_spacing (6);
121 solo_model_box.pack_start (solo_in_place_button, false, false);
122 solo_model_box.pack_start (afl_button, false, false);
123 solo_model_box.pack_start (pfl_button, false, false);
125 solo_in_place_button.show ();
126 afl_button.show ();
127 pfl_button.show ();
128 solo_model_box.show ();
130 act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
131 if (act) {
132 act->connect_proxy (solo_in_place_button);
135 act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
136 if (act) {
137 act->connect_proxy (afl_button);
140 act = ActionManager::get_action (X_("Solo"), X_("solo-use-pfl"));
141 if (act) {
142 act->connect_proxy (pfl_button);
146 /* Solo Boost */
148 solo_boost_control = new VolumeController (little_knob_pixbuf, &solo_boost_adjustment, false, 30, 30);
149 solo_boost_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MonitorSection::solo_boost_changed));
151 HBox* solo_packer = manage (new HBox);
152 solo_packer->set_spacing (12);
153 solo_packer->show ();
155 spin_label = manage (new Label (_("Solo Boost")));
156 spin_packer = manage (new VBox);
157 spin_packer->show ();
158 spin_packer->set_spacing (6);
159 spin_packer->pack_start (*solo_boost_control, false, false);
160 spin_packer->pack_start (*spin_label, false, false);
162 solo_packer->pack_start (*spin_packer, true, true);
164 /* Solo (SiP) cut */
166 solo_cut_control = new VolumeController (little_knob_pixbuf, &solo_cut_adjustment, false, 30, 30);
167 // solo_cut_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MonitorSection::solo_cut_changed));
169 spin_label = manage (new Label (_("SiP Cut")));
170 spin_packer = manage (new VBox);
171 spin_packer->show ();
172 spin_packer->set_spacing (6);
173 spin_packer->pack_start (*solo_cut_control, false, false);
174 spin_packer->pack_start (*spin_label, false, false);
176 solo_packer->pack_start (*spin_packer, true, true);
178 upper_packer.set_spacing (12);
179 upper_packer.pack_start (rude_solo_button, false, false);
180 upper_packer.pack_start (solo_model_box, false, false);
181 upper_packer.pack_start (*solo_packer, false, false);
183 act = ActionManager::get_action (X_("Monitor"), X_("monitor-cut-all"));
184 if (act) {
185 act->connect_proxy (cut_all_button);
188 act = ActionManager::get_action (X_("Monitor"), X_("monitor-dim-all"));
189 if (act) {
190 act->connect_proxy (dim_all_button);
193 act = ActionManager::get_action (X_("Monitor"), X_("monitor-mono"));
194 if (act) {
195 act->connect_proxy (mono_button);
198 cut_all_button.set_size_request (50,50);
199 cut_all_button.show ();
201 HBox* bbox = manage (new HBox);
203 bbox->set_spacing (12);
204 bbox->pack_start (mono_button, true, true);
205 bbox->pack_start (dim_all_button, true, true);
207 lower_packer.set_spacing (12);
208 lower_packer.pack_start (*bbox, false, false);
209 lower_packer.pack_start (cut_all_button, false, false);
211 /* Gain */
213 gain_control = new VolumeController (big_knob_pixbuf, &gain_adjustment, false, 80, 80);
214 gain_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MonitorSection::gain_value_changed));
216 spin_label = manage (new Label (_("Gain")));
217 spin_packer = manage (new VBox);
218 spin_packer->show ();
219 spin_packer->set_spacing (6);
220 spin_packer->pack_start (*gain_control, false, false);
221 spin_packer->pack_start (*spin_label, false, false);
223 lower_packer.pack_start (*spin_packer, true, true);
225 vpacker.set_border_width (12);
226 vpacker.set_spacing (12);
227 vpacker.pack_start (upper_packer, false, false);
228 vpacker.pack_start (*dim_packer, false, false);
229 vpacker.pack_start (main_table, false, false);
230 vpacker.pack_start (lower_packer, false, false);
232 hpacker.set_border_width (12);
233 hpacker.set_spacing (12);
234 hpacker.pack_start (vpacker, true, true);
236 gain_control->show_all ();
237 dim_control->show_all ();
238 solo_boost_control->show_all ();
240 main_table.show ();
241 hpacker.show ();
242 upper_packer.show ();
243 lower_packer.show ();
244 vpacker.show ();
246 populate_buttons ();
247 map_state ();
249 _tearoff = new TearOff (hpacker);
251 /* if torn off, make this a normal window */
252 _tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
253 _tearoff->tearoff_window().set_title (X_("Monitor"));
254 _tearoff->tearoff_window().signal_key_press_event().connect (sigc::ptr_fun (forward_key_press), false);
257 MonitorSection::~MonitorSection ()
259 for (ChannelButtons::iterator i = _channel_buttons.begin(); i != _channel_buttons.end(); ++i) {
260 delete *i;
263 _channel_buttons.clear ();
265 delete gain_control;
266 delete dim_control;
267 delete solo_boost_control;
268 delete _tearoff;
271 void
272 MonitorSection::set_session (Session* s)
274 AxisView::set_session (s);
276 if (_session) {
278 _route = _session->control_out ();
280 if (_route) {
281 /* session with control outs */
282 _monitor = _route->monitor_control ();
283 } else {
284 /* session with no control outs */
285 _monitor.reset ();
286 _route.reset ();
289 } else {
290 /* no session */
291 _monitor.reset ();
292 _route.reset ();
295 /* both might be null */
298 MonitorSection::ChannelButtonSet::ChannelButtonSet ()
299 : cut (X_(""))
300 , dim (X_(""))
301 , solo (X_(""))
302 , invert (X_(""))
304 cut.set_name (X_("MixerMuteButton"));
305 dim.set_name (X_("MixerMuteButton"));
306 solo.set_name (X_("MixerSoloButton"));
308 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (cut.gobj()), false);
309 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dim.gobj()), false);
310 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (invert.gobj()), false);
311 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (solo.gobj()), false);
313 block_prelight (cut);
314 block_prelight (dim);
315 block_prelight (solo);
316 block_prelight (invert);
319 void
320 MonitorSection::populate_buttons ()
322 if (!_monitor) {
323 return;
326 Glib::RefPtr<Action> act;
327 uint32_t nchans = _monitor->output_streams().n_audio();
329 main_table.resize (nchans+1, 5);
330 main_table.set_col_spacings (6);
331 main_table.set_row_spacings (6);
332 main_table.set_homogeneous (true);
334 Label* l1 = manage (new Label (X_("out")));
335 main_table.attach (*l1, 0, 1, 0, 1, SHRINK|FILL, SHRINK|FILL);
336 l1 = manage (new Label (X_("cut")));
337 main_table.attach (*l1, 1, 2, 0, 1, SHRINK|FILL, SHRINK|FILL);
338 l1 = manage (new Label (X_("dim")));
339 main_table.attach (*l1, 2, 3, 0, 1, SHRINK|FILL, SHRINK|FILL);
340 l1 = manage (new Label (X_("solo")));
341 main_table.attach (*l1, 3, 4, 0, 1, SHRINK|FILL, SHRINK|FILL);
342 l1 = manage (new Label (X_("inv")));
343 main_table.attach (*l1, 4, 5, 0, 1, SHRINK|FILL, SHRINK|FILL);
345 const uint32_t row_offset = 1;
347 for (uint32_t i = 0; i < nchans; ++i) {
349 string l;
350 char buf[64];
352 if (nchans == 2) {
353 if (i == 0) {
354 l = "L";
355 } else {
356 l = "R";
358 } else {
359 char buf[32];
360 snprintf (buf, sizeof (buf), "%d", i+1);
361 l = buf;
364 Label* label = manage (new Label (l));
365 main_table.attach (*label, 0, 1, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
367 ChannelButtonSet* cbs = new ChannelButtonSet;
369 _channel_buttons.push_back (cbs);
371 main_table.attach (cbs->cut, 1, 2, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
372 main_table.attach (cbs->dim, 2, 3, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
373 main_table.attach (cbs->solo, 3, 4, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
374 main_table.attach (cbs->invert, 4, 5, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
376 snprintf (buf, sizeof (buf), "monitor-cut-%u", i+1);
377 act = ActionManager::get_action (X_("Monitor"), buf);
378 if (act) {
379 act->connect_proxy (cbs->cut);
382 snprintf (buf, sizeof (buf), "monitor-dim-%u", i+1);
383 act = ActionManager::get_action (X_("Monitor"), buf);
384 if (act) {
385 act->connect_proxy (cbs->dim);
388 snprintf (buf, sizeof (buf), "monitor-solo-%u", i+1);
389 act = ActionManager::get_action (X_("Monitor"), buf);
390 if (act) {
391 act->connect_proxy (cbs->solo);
394 snprintf (buf, sizeof (buf), "monitor-invert-%u", i+1);
395 act = ActionManager::get_action (X_("Monitor"), buf);
396 if (act) {
397 act->connect_proxy (cbs->invert);
401 main_table.show_all ();
404 void
405 MonitorSection::set_button_names ()
407 rec_enable_button_label.set_text ("rec");
408 mute_button_label.set_text ("rec");
409 solo_button_label.set_text ("rec");
412 void
413 MonitorSection::dim_all ()
415 if (!_monitor) {
416 return;
419 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
420 if (act) {
421 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
422 _monitor->set_dim_all (tact->get_active());
427 void
428 MonitorSection::cut_all ()
430 if (!_monitor) {
431 return;
434 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
435 if (act) {
436 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
437 _monitor->set_cut_all (tact->get_active());
441 void
442 MonitorSection::mono ()
444 if (!_monitor) {
445 return;
448 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
449 if (act) {
450 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
451 _monitor->set_mono (tact->get_active());
455 void
456 MonitorSection::cut_channel (uint32_t chn)
458 if (!_monitor) {
459 return;
462 char buf[64];
463 snprintf (buf, sizeof (buf), "monitor-cut-%u", chn);
465 --chn; // 0-based in backend
467 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
468 if (act) {
469 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
470 _monitor->set_cut (chn, tact->get_active());
474 void
475 MonitorSection::dim_channel (uint32_t chn)
477 if (!_monitor) {
478 return;
481 char buf[64];
482 snprintf (buf, sizeof (buf), "monitor-dim-%u", chn);
484 --chn; // 0-based in backend
486 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
487 if (act) {
488 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
489 _monitor->set_dim (chn, tact->get_active());
494 void
495 MonitorSection::solo_channel (uint32_t chn)
497 if (!_monitor) {
498 return;
501 char buf[64];
502 snprintf (buf, sizeof (buf), "monitor-solo-%u", chn);
504 --chn; // 0-based in backend
506 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
507 if (act) {
508 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
509 _monitor->set_solo (chn, tact->get_active());
514 void
515 MonitorSection::invert_channel (uint32_t chn)
517 if (!_monitor) {
518 return;
521 char buf[64];
522 snprintf (buf, sizeof (buf), "monitor-invert-%u", chn);
524 --chn; // 0-based in backend
526 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
527 if (act) {
528 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
529 _monitor->set_polarity (chn, tact->get_active());
533 void
534 MonitorSection::register_actions ()
536 string action_name;
537 string action_descr;
539 monitor_actions = ActionGroup::create (X_("Monitor"));
540 ActionManager::add_action_group (monitor_actions);
542 ActionManager::register_toggle_action (monitor_actions, "monitor-mono", "",
543 sigc::mem_fun (*this, &MonitorSection::mono));
545 ActionManager::register_toggle_action (monitor_actions, "monitor-cut-all", "",
546 sigc::mem_fun (*this, &MonitorSection::cut_all));
548 ActionManager::register_toggle_action (monitor_actions, "monitor-dim-all", "",
549 sigc::mem_fun (*this, &MonitorSection::dim_all));
551 /* note the 1-based counting (for naming - backend uses 0-based) */
553 for (uint32_t chn = 1; chn <= 16; ++chn) {
555 /* for the time being, do not use the action description because it always
556 shows up in the buttons, which is undesirable.
559 action_name = string_compose (X_("monitor-cut-%1"), chn);
560 action_descr = string_compose (_("Cut Monitor Chn %1"), chn);
561 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "",
562 sigc::bind (sigc::mem_fun (*this, &MonitorSection::cut_channel), chn));
564 action_name = string_compose (X_("monitor-dim-%1"), chn);
565 action_descr = string_compose (_("Dim Monitor Chn %1"), chn+1);
566 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "",
567 sigc::bind (sigc::mem_fun (*this, &MonitorSection::dim_channel), chn));
569 action_name = string_compose (X_("monitor-solo-%1"), chn);
570 action_descr = string_compose (_("Solo Monitor Chn %1"), chn);
571 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "",
572 sigc::bind (sigc::mem_fun (*this, &MonitorSection::solo_channel), chn));
574 action_name = string_compose (X_("monitor-invert-%1"), chn);
575 action_descr = string_compose (_("Invert Monitor Chn %1"), chn);
576 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "",
577 sigc::bind (sigc::mem_fun (*this, &MonitorSection::invert_channel), chn));
582 Glib::RefPtr<ActionGroup> solo_actions = ActionGroup::create (X_("Solo"));
583 RadioAction::Group solo_group;
585 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-in-place", "",
586 sigc::mem_fun (*this, &MonitorSection::solo_use_in_place));
587 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-afl", "",
588 sigc::mem_fun (*this, &MonitorSection::solo_use_afl));
589 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-pfl", "",
590 sigc::mem_fun (*this, &MonitorSection::solo_use_pfl));
592 ActionManager::add_action_group (solo_actions);
595 void
596 MonitorSection::solo_use_in_place ()
598 /* this is driven by a toggle on a radio group, and so is invoked twice,
599 once for the item that became inactive and once for the one that became
600 active.
603 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
605 if (act) {
606 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
607 if (ract) {
608 Config->set_solo_control_is_listen_control (!ract->get_active());
613 void
614 MonitorSection::solo_use_afl ()
616 /* this is driven by a toggle on a radio group, and so is invoked twice,
617 once for the item that became inactive and once for the one that became
618 active.
621 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
622 if (act) {
623 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
624 if (ract) {
625 if (ract->get_active()) {
626 Config->set_listen_position (AfterFaderListen);
627 Config->set_solo_control_is_listen_control (true);
633 void
634 MonitorSection::solo_use_pfl ()
636 /* this is driven by a toggle on a radio group, and so is invoked twice,
637 once for the item that became inactive and once for the one that became
638 active.
641 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
642 if (act) {
643 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
644 if (ract) {
645 if (ract->get_active()) {
646 Config->set_listen_position (PreFaderListen);
647 Config->set_solo_control_is_listen_control (true);
653 void
654 MonitorSection::setup_knob_images ()
656 try {
658 big_knob_pixbuf = ::get_icon ("bigknob");
660 } catch (...) {
662 error << "No knob image found (or not loadable) at "
663 << " .... "
664 << endmsg;
665 throw failed_constructor ();
668 try {
670 little_knob_pixbuf = ::get_icon ("littleknob");
672 } catch (...) {
674 error << "No knob image found (or not loadable) at "
675 << " .... "
676 << endmsg;
677 throw failed_constructor ();
681 void
682 MonitorSection::gain_value_changed ()
684 if (_route) {
685 _route->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
689 void
690 MonitorSection::dim_level_changed ()
692 if (_monitor) {
693 _monitor->set_dim_level (dim_adjustment.get_value());
697 void
698 MonitorSection::solo_boost_changed ()
700 if (_monitor) {
701 _monitor->set_solo_boost_level (solo_boost_adjustment.get_value());
705 bool
706 MonitorSection::nonlinear_gain_printer (SpinButton* button)
708 double val = button->get_adjustment()->get_value();
709 char buf[16];
710 snprintf (buf, sizeof (buf), "%.1f", accurate_coefficient_to_dB (slider_position_to_gain (val)));
711 button->set_text (buf);
712 return true;
715 bool
716 MonitorSection::linear_gain_printer (SpinButton* button)
718 double val = button->get_adjustment()->get_value();
719 char buf[16];
720 snprintf (buf, sizeof (buf), "%.1f", accurate_coefficient_to_dB (val));
721 button->set_text (buf);
722 return true;
725 void
726 MonitorSection::map_state ()
728 if (!_route || !_monitor) {
729 return;
732 gain_control->get_adjustment()->set_value (gain_to_slider_position (_route->gain_control()->get_value()));
733 dim_control->get_adjustment()->set_value (_monitor->dim_level());
734 solo_boost_control->get_adjustment()->set_value (_monitor->solo_boost_level());
736 const char *action_name;
738 if (Config->get_solo_control_is_listen_control()) {
739 switch (Config->get_listen_position()) {
740 case AfterFaderListen:
741 action_name = X_("solo-use-afl");
742 break;
743 case PreFaderListen:
744 action_name = X_("solo-use-afl");
745 break;
747 } else {
748 action_name = X_("solo-use-in-place");
751 Glib::RefPtr<Action> act;
753 act = ActionManager::get_action (X_("Solo"), action_name);
754 if (act) {
755 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
756 if (ract) {
757 ract->set_active (true);
761 act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
762 if (act) {
763 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
764 if (tact) {
765 cerr << "Set monitor cut all action to " << _monitor->cut_all () << endl;
766 tact->set_active (_monitor->cut_all());
767 } else {
768 cerr << " no global cut action\n";
770 } else {
771 cerr << " no global cut action2\n";
774 act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
775 if (act) {
776 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
777 if (tact) {
778 tact->set_active (_monitor->dim_all());
782 act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
783 if (act) {
784 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
785 if (tact) {
786 tact->set_active (_monitor->mono());
790 uint32_t nchans = _monitor->output_streams().n_audio();
792 assert (nchans == _channel_buttons.size ());
794 for (uint32_t n = 0; n < nchans; ++n) {
796 char action_name[32];
798 snprintf (action_name, sizeof (action_name), "monitor-cut-%u", n+1);
799 act = ActionManager::get_action (X_("Monitor"), action_name);
800 if (act) {
801 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
802 if (tact) {
803 tact->set_active (_monitor->cut (n));
807 snprintf (action_name, sizeof (action_name), "monitor-dim-%u", n+1);
808 act = ActionManager::get_action (X_("Monitor"), action_name);
809 if (act) {
810 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
811 if (tact) {
812 tact->set_active (_monitor->dimmed (n));
816 snprintf (action_name, sizeof (action_name), "monitor-solo-%u", n+1);
817 act = ActionManager::get_action (X_("Monitor"), action_name);
818 if (act) {
819 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
820 if (tact) {
821 tact->set_active (_monitor->soloed (n));
825 snprintf (action_name, sizeof (action_name), "monitor-invert-%u", n+1);
826 act = ActionManager::get_action (X_("Monitor"), action_name);
827 if (act) {
828 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
829 if (tact) {
830 tact->set_active (_monitor->inverted (n));
836 void
837 MonitorSection::solo_blink (bool onoff)
839 if (_session == 0) {
840 return;
843 if (_session->soloing() || _session->listening()) {
844 if (onoff) {
845 rude_solo_button.set_state (STATE_ACTIVE);
846 } else {
847 rude_solo_button.set_state (STATE_NORMAL);
849 } else {
850 // rude_solo_button.set_active (false);
851 rude_solo_button.set_state (STATE_NORMAL);
855 bool
856 MonitorSection::cancel_solo (GdkEventButton* ev)
858 if (_session) {
859 if (_session->soloing()) {
860 _session->set_solo (_session->get_routes(), false);
861 } else if (_session->listening()) {
862 _session->set_listen (_session->get_routes(), false);
866 return true;