1 #include <gdkmm/pixbuf.h>
3 #include "pbd/compose.h"
6 #include "gtkmm2ext/bindable_button.h"
7 #include "gtkmm2ext/tearoff.h"
8 #include "gtkmm2ext/actions.h"
9 #include "gtkmm2ext/motionfeedback.h"
11 #include "ardour/monitor_processor.h"
12 #include "ardour/route.h"
14 #include "ardour_ui.h"
15 #include "gui_thread.h"
16 #include "monitor_section.h"
17 #include "public_editor.h"
18 #include "volume_controller.h"
23 using namespace ARDOUR;
25 using namespace Gtkmm2ext;
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 MonitorSection::MonitorSection (Session* s)
37 , channel_table_viewport (*channel_table_scroller.get_hadjustment(),
38 *channel_table_scroller.get_vadjustment ())
41 , solo_boost_control (0)
42 , solo_cut_control (0)
43 , solo_in_place_button (_("SiP"), ArdourButton::led_default_elements)
44 , afl_button (_("AFL"), ArdourButton::led_default_elements)
45 , pfl_button (_("PFL"), ArdourButton::led_default_elements)
46 , exclusive_solo_button (ArdourButton::led_default_elements)
47 , solo_mute_override_button (ArdourButton::led_default_elements)
48 , _inhibit_solo_model_update (false)
50 Glib::RefPtr<Action> act;
52 if (!monitor_actions) {
54 /* do some static stuff */
67 rude_solo_button.set_text (_("soloing"));
68 rude_solo_button.set_name ("rude solo");
69 rude_solo_button.show ();
71 rude_iso_button.set_text (_("isolated"));
72 rude_iso_button.set_name ("rude isolate");
73 rude_iso_button.show ();
75 rude_audition_button.set_text (_("auditioning"));
76 rude_audition_button.set_name ("rude audition");
77 rude_audition_button.show ();
79 ARDOUR_UI::Blink.connect (sigc::mem_fun (*this, &MonitorSection::do_blink));
81 rude_solo_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_solo));
82 UI::instance()->set_tip (rude_solo_button, _("When active, something is soloed.\nClick to de-solo everything"));
84 rude_iso_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_isolate));
85 UI::instance()->set_tip (rude_iso_button, _("When active, something is solo-isolated.\nClick to de-isolate everything"));
87 rude_audition_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_audition));
88 UI::instance()->set_tip (rude_audition_button, _("When active, auditioning is active.\nClick to stop the audition"));
90 solo_in_place_button.set_name ("monitor section solo model");
91 afl_button.set_name ("monitor section solo model");
92 pfl_button.set_name ("monitor section solo model");
94 solo_model_box.set_spacing (6);
95 solo_model_box.pack_start (solo_in_place_button, true, false);
96 solo_model_box.pack_start (afl_button, true, false);
97 solo_model_box.pack_start (pfl_button, true, false);
99 solo_in_place_button.show ();
102 solo_model_box.show ();
104 act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
105 ARDOUR_UI::instance()->tooltips().set_tip (solo_in_place_button, _("Solo controls affect solo-in-place"));
107 solo_in_place_button.set_related_action (act);
110 act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
111 ARDOUR_UI::instance()->tooltips().set_tip (afl_button, _("Solo controls toggle after-fader-listen"));
113 afl_button.set_related_action (act);
116 act = ActionManager::get_action (X_("Solo"), X_("solo-use-pfl"));
117 ARDOUR_UI::instance()->tooltips().set_tip (pfl_button, _("Solo controls toggle pre-fader-listen"));
119 pfl_button.set_related_action (act);
124 solo_boost_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.01, 0.1, true, 30, 30, true);
125 ARDOUR_UI::instance()->tooltips().set_tip (*solo_boost_control, _("Gain increase for soloed signals (0dB is normal)"));
127 HBox* solo_packer = manage (new HBox);
128 solo_packer->set_spacing (6);
129 solo_packer->show ();
131 spin_label = manage (new Label (_("Solo Boost")));
132 spin_packer = manage (new VBox);
133 spin_packer->show ();
134 spin_packer->set_spacing (6);
135 spin_packer->pack_start (*solo_boost_control, false, false);
136 spin_packer->pack_start (*spin_label, false, false);
138 solo_packer->pack_start (*spin_packer, true, false);
142 solo_cut_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.1, 0.5, true, 30, 30, true);
143 ARDOUR_UI::instance()->tooltips().set_tip (*solo_cut_control, _("Gain reduction non-soloed signals\nA value above -inf dB causes \"solo-in-front\""));
145 spin_label = manage (new Label (_("SiP Cut")));
146 spin_packer = manage (new VBox);
147 spin_packer->show ();
148 spin_packer->set_spacing (6);
149 spin_packer->pack_start (*solo_cut_control, false, false);
150 spin_packer->pack_start (*spin_label, false, false);
152 solo_packer->pack_start (*spin_packer, true, false);
156 dim_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.01, 0.1, true, 30, 30, true);
157 ARDOUR_UI::instance()->tooltips().set_tip (*dim_control, _("Gain reduction to use when dimming monitor outputs"));
159 HBox* dim_packer = manage (new HBox);
162 spin_label = manage (new Label (_("Dim")));
163 spin_packer = manage (new VBox);
164 spin_packer->show ();
165 spin_packer->set_spacing (6);
166 spin_packer->pack_start (*dim_control, false, false);
167 spin_packer->pack_start (*spin_label, false, false);
169 dim_packer->pack_start (*spin_packer, true, false);
171 exclusive_solo_button.set_text (_("excl. solo"));
172 exclusive_solo_button.set_name (X_("monitor solo exclusive"));
173 ARDOUR_UI::instance()->set_tip (&exclusive_solo_button, _("Exclusive solo means that only 1 solo is active at a time"));
175 act = ActionManager::get_action (X_("Monitor"), X_("toggle-exclusive-solo"));
177 exclusive_solo_button.set_related_action (act);
180 solo_mute_override_button.set_text (_("solo ยป mute"));
181 solo_mute_override_button.set_name (X_("monitor solo override"));
182 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)"));
184 act = ActionManager::get_action (X_("Monitor"), X_("toggle-mute-overrides-solo"));
186 solo_mute_override_button.set_related_action (act);
189 HBox* solo_opt_box = manage (new HBox);
190 solo_opt_box->set_spacing (12);
191 solo_opt_box->set_homogeneous (true);
192 solo_opt_box->pack_start (exclusive_solo_button);
193 solo_opt_box->pack_start (solo_mute_override_button);
194 solo_opt_box->show ();
196 upper_packer.set_spacing (6);
198 Gtk::HBox* rude_box = manage (new HBox);
199 rude_box->pack_start (rude_solo_button, true, true);
200 rude_box->pack_start (rude_iso_button, true, true);
202 upper_packer.pack_start (*rude_box, false, false);
203 upper_packer.pack_start (rude_audition_button, false, false);
204 upper_packer.pack_start (solo_model_box, false, false, 12);
205 upper_packer.pack_start (*solo_opt_box, false, false);
206 upper_packer.pack_start (*solo_packer, false, false, 12);
208 cut_all_button.set_text (_("mute"));
209 cut_all_button.set_name ("monitor section cut");
210 cut_all_button.set_name (X_("monitor section cut"));
211 cut_all_button.set_size_request (-1,50);
212 cut_all_button.show ();
214 act = ActionManager::get_action (X_("Monitor"), X_("monitor-cut-all"));
216 cut_all_button.set_related_action (act);
219 dim_all_button.set_text (_("dim"));
220 dim_all_button.set_name ("monitor section dim");
221 act = ActionManager::get_action (X_("Monitor"), X_("monitor-dim-all"));
223 dim_all_button.set_related_action (act);
226 mono_button.set_text (_("mono"));
227 mono_button.set_name ("monitor section mono");
228 act = ActionManager::get_action (X_("Monitor"), X_("monitor-mono"));
230 mono_button.set_related_action (act);
233 HBox* bbox = manage (new HBox);
235 bbox->set_spacing (12);
236 bbox->pack_start (mono_button, true, true);
237 bbox->pack_start (dim_all_button, true, true);
239 lower_packer.set_spacing (12);
240 lower_packer.pack_start (*bbox, false, false);
241 lower_packer.pack_start (cut_all_button, false, false);
245 gain_control = new VolumeController (big_knob_pixbuf, boost::shared_ptr<Controllable>(), 1.0, 0.01, 0.1, true, 80, 80, false);
247 spin_label = manage (new Label (_("Monitor")));
248 spin_packer = manage (new VBox);
249 spin_packer->show ();
250 spin_packer->set_spacing (6);
251 spin_packer->pack_start (*gain_control, false, false);
252 spin_packer->pack_start (*spin_label, false, false);
254 lower_packer.pack_start (*spin_packer, true, true);
256 channel_table_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
257 channel_table_scroller.set_size_request (-1, 150);
258 channel_table_scroller.set_shadow_type (Gtk::SHADOW_NONE);
259 channel_table_scroller.show ();
260 channel_table_scroller.add (channel_table_viewport);
262 channel_size_group = SizeGroup::create (SIZE_GROUP_HORIZONTAL);
263 channel_size_group->add_widget (channel_table_header);
264 channel_size_group->add_widget (channel_table);
266 channel_table_header.resize (1, 5);
267 Label* l1 = manage (new Label (X_("out")));
268 l1->set_name (X_("MonitorSectionLabel"));
269 channel_table_header.attach (*l1, 0, 1, 0, 1, EXPAND|FILL);
270 l1 = manage (new Label (X_("mute")));
271 l1->set_name (X_("MonitorSectionLabel"));
272 channel_table_header.attach (*l1, 1, 2, 0, 1, EXPAND|FILL);
273 l1 = manage (new Label (X_("dim")));
274 l1->set_name (X_("MonitorSectionLabel"));
275 channel_table_header.attach (*l1, 2, 3, 0, 1, EXPAND|FILL);
276 l1 = manage (new Label (X_("solo")));
277 l1->set_name (X_("MonitorSectionLabel"));
278 channel_table_header.attach (*l1, 3, 4, 0, 1, EXPAND|FILL);
279 l1 = manage (new Label (X_("inv")));
280 l1->set_name (X_("MonitorSectionLabel"));
281 channel_table_header.attach (*l1, 4, 5, 0, 1, EXPAND|FILL);
282 channel_table_header.show ();
284 table_hpacker.pack_start (channel_table, true, true);
286 /* note that we don't pack the table_hpacker till later
289 vpacker.set_border_width (6);
290 vpacker.set_spacing (12);
291 vpacker.pack_start (upper_packer, false, false);
292 vpacker.pack_start (*dim_packer, false, false);
293 vpacker.pack_start (channel_table_header, false, false);
294 vpacker.pack_start (channel_table_packer, false, false);
295 vpacker.pack_start (lower_packer, false, false);
297 hpacker.pack_start (vpacker, true, true);
299 gain_control->show_all ();
300 dim_control->show_all ();
301 solo_boost_control->show_all ();
303 channel_table.show ();
305 upper_packer.show ();
306 lower_packer.show ();
311 assign_controllables ();
313 _tearoff = new TearOff (hpacker);
315 /* if torn off, make this a normal window */
316 _tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
317 _tearoff->tearoff_window().set_title (X_("Monitor"));
318 _tearoff->tearoff_window().signal_key_press_event().connect (sigc::ptr_fun (forward_key_press), false);
320 /* catch changes that affect us */
322 Config->ParameterChanged.connect (config_connection, invalidator (*this), boost::bind (&MonitorSection::parameter_changed, this, _1), gui_context());
325 MonitorSection::~MonitorSection ()
327 for (ChannelButtons::iterator i = _channel_buttons.begin(); i != _channel_buttons.end(); ++i) {
331 _channel_buttons.clear ();
335 delete solo_boost_control;
340 MonitorSection::set_session (Session* s)
342 AxisView::set_session (s);
346 _route = _session->monitor_out ();
349 /* session with monitor section */
350 _monitor = _route->monitor_control ();
351 assign_controllables ();
353 /* session with no monitor section */
358 if (channel_table_scroller.get_parent()) {
359 /* scroller is packed, so remove it */
360 channel_table_packer.remove (channel_table_scroller);
363 if (table_hpacker.get_parent () == &channel_table_packer) {
364 /* this occurs when the table hpacker is directly
365 packed, so remove it.
367 channel_table_packer.remove (table_hpacker);
368 } else if (table_hpacker.get_parent()) {
369 channel_table_viewport.remove ();
372 if (_monitor->output_streams().n_audio() > 7) {
373 /* put the table into a scrolled window, and then put
374 * that into the channel vpacker, after the table header
376 channel_table_viewport.add (table_hpacker);
377 channel_table_packer.pack_start (channel_table_scroller, true, true);
378 channel_table_viewport.show ();
379 channel_table_scroller.show ();
382 /* just put the channel table itself into the channel
383 * vpacker, after the table header
386 channel_table_packer.pack_start (table_hpacker, true, true);
387 channel_table_scroller.hide ();
390 table_hpacker.show ();
391 channel_table.show ();
398 control_connections.drop_connections ();
399 rude_iso_button.unset_active_state ();
400 rude_solo_button.unset_active_state ();
402 assign_controllables ();
406 MonitorSection::ChannelButtonSet::ChannelButtonSet ()
408 cut.set_diameter (3);
409 dim.set_diameter (3);
410 solo.set_diameter (3);
411 invert.set_diameter (3);
413 cut.set_name (X_("monitor section cut"));
414 dim.set_name (X_("monitor section dim"));
415 solo.set_name (X_("monitor section solo"));
416 invert.set_name (X_("monitor section invert"));
418 cut.unset_flags (Gtk::CAN_FOCUS);
419 dim.unset_flags (Gtk::CAN_FOCUS);
420 solo.unset_flags (Gtk::CAN_FOCUS);
421 invert.unset_flags (Gtk::CAN_FOCUS);
425 MonitorSection::populate_buttons ()
431 Glib::RefPtr<Action> act;
432 uint32_t nchans = _monitor->output_streams().n_audio();
434 channel_table.resize (nchans, 5);
435 channel_table.set_col_spacings (6);
436 channel_table.set_row_spacings (6);
437 channel_table.set_homogeneous (true);
439 const uint32_t row_offset = 0;
441 for (uint32_t i = 0; i < nchans; ++i) {
454 snprintf (buf, sizeof (buf), "%d", i+1);
458 Label* label = manage (new Label (l));
459 channel_table.attach (*label, 0, 1, i+row_offset, i+row_offset+1, EXPAND|FILL);
461 ChannelButtonSet* cbs = new ChannelButtonSet;
463 _channel_buttons.push_back (cbs);
465 channel_table.attach (cbs->cut, 1, 2, i+row_offset, i+row_offset+1, EXPAND|FILL);
466 channel_table.attach (cbs->dim, 2, 3, i+row_offset, i+row_offset+1, EXPAND|FILL);
467 channel_table.attach (cbs->solo, 3, 4, i+row_offset, i+row_offset+1, EXPAND|FILL);
468 channel_table.attach (cbs->invert, 4, 5, i+row_offset, i+row_offset+1, EXPAND|FILL);
470 snprintf (buf, sizeof (buf), "monitor-cut-%u", i+1);
471 act = ActionManager::get_action (X_("Monitor"), buf);
473 cbs->cut.set_related_action (act);
476 snprintf (buf, sizeof (buf), "monitor-dim-%u", i+1);
477 act = ActionManager::get_action (X_("Monitor"), buf);
479 cbs->dim.set_related_action (act);
482 snprintf (buf, sizeof (buf), "monitor-solo-%u", i+1);
483 act = ActionManager::get_action (X_("Monitor"), buf);
485 cbs->solo.set_related_action (act);
488 snprintf (buf, sizeof (buf), "monitor-invert-%u", i+1);
489 act = ActionManager::get_action (X_("Monitor"), buf);
491 cbs->invert.set_related_action (act);
495 channel_table.show_all ();
499 MonitorSection::toggle_exclusive_solo ()
505 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "toggle-exclusive-solo");
507 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
508 Config->set_exclusive_solo (tact->get_active());
515 MonitorSection::toggle_mute_overrides_solo ()
521 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "toggle-mute-overrides-solo");
523 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
524 Config->set_solo_mute_override (tact->get_active());
529 MonitorSection::dim_all ()
535 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
537 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
538 _monitor->set_dim_all (tact->get_active());
544 MonitorSection::cut_all ()
550 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
552 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
553 _monitor->set_cut_all (tact->get_active());
558 MonitorSection::mono ()
564 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
566 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
567 _monitor->set_mono (tact->get_active());
572 MonitorSection::cut_channel (uint32_t chn)
579 snprintf (buf, sizeof (buf), "monitor-cut-%u", chn);
581 --chn; // 0-based in backend
583 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
585 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
586 _monitor->set_cut (chn, tact->get_active());
591 MonitorSection::dim_channel (uint32_t chn)
598 snprintf (buf, sizeof (buf), "monitor-dim-%u", chn);
600 --chn; // 0-based in backend
602 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
604 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
605 _monitor->set_dim (chn, tact->get_active());
611 MonitorSection::solo_channel (uint32_t chn)
618 snprintf (buf, sizeof (buf), "monitor-solo-%u", chn);
620 --chn; // 0-based in backend
622 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
624 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
625 _monitor->set_solo (chn, tact->get_active());
631 MonitorSection::invert_channel (uint32_t chn)
638 snprintf (buf, sizeof (buf), "monitor-invert-%u", chn);
640 --chn; // 0-based in backend
642 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
644 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
645 _monitor->set_polarity (chn, tact->get_active());
650 MonitorSection::register_actions ()
654 Glib::RefPtr<Action> act;
656 monitor_actions = ActionGroup::create (X_("Monitor"));
657 ActionManager::add_action_group (monitor_actions);
659 ActionManager::register_toggle_action (monitor_actions, "monitor-mono", "", "Switch monitor to mono",
660 sigc::mem_fun (*this, &MonitorSection::mono));
662 ActionManager::register_toggle_action (monitor_actions, "monitor-cut-all", "", "Cut monitor",
663 sigc::mem_fun (*this, &MonitorSection::cut_all));
665 ActionManager::register_toggle_action (monitor_actions, "monitor-dim-all", "", "Dim monitor",
666 sigc::mem_fun (*this, &MonitorSection::dim_all));
668 act = ActionManager::register_toggle_action (monitor_actions, "toggle-exclusive-solo", "", "Toggle exclusive solo mode",
669 sigc::mem_fun (*this, &MonitorSection::toggle_exclusive_solo));
671 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
672 tact->set_active (Config->get_exclusive_solo());
674 act = ActionManager::register_toggle_action (monitor_actions, "toggle-mute-overrides-solo", "", "Toggle mute overrides solo mode",
675 sigc::mem_fun (*this, &MonitorSection::toggle_mute_overrides_solo));
677 tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
678 tact->set_active (Config->get_solo_mute_override());
681 /* note the 1-based counting (for naming - backend uses 0-based) */
683 for (uint32_t chn = 1; chn <= 16; ++chn) {
685 action_name = string_compose (X_("monitor-cut-%1"), chn);
686 action_descr = string_compose (_("Cut monitor channel %1"), chn);
687 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
688 sigc::bind (sigc::mem_fun (*this, &MonitorSection::cut_channel), chn));
690 action_name = string_compose (X_("monitor-dim-%1"), chn);
691 action_descr = string_compose (_("Dim monitor channel %1"), chn+1);
692 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
693 sigc::bind (sigc::mem_fun (*this, &MonitorSection::dim_channel), chn));
695 action_name = string_compose (X_("monitor-solo-%1"), chn);
696 action_descr = string_compose (_("Solo monitor channel %1"), chn+1);
697 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
698 sigc::bind (sigc::mem_fun (*this, &MonitorSection::solo_channel), chn));
700 action_name = string_compose (X_("monitor-invert-%1"), chn);
701 action_descr = string_compose (_("Invert monitor channel %1"), chn+1);
702 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
703 sigc::bind (sigc::mem_fun (*this, &MonitorSection::invert_channel), chn));
708 Glib::RefPtr<ActionGroup> solo_actions = ActionGroup::create (X_("Solo"));
709 RadioAction::Group solo_group;
711 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-in-place", "", "In-place solo",
712 sigc::mem_fun (*this, &MonitorSection::solo_use_in_place));
713 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-afl", "", "After Fade Listen (AFL) solo",
714 sigc::mem_fun (*this, &MonitorSection::solo_use_afl));
715 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-pfl", "", "Pre Fade Listen (PFL) solo",
716 sigc::mem_fun (*this, &MonitorSection::solo_use_pfl));
718 ActionManager::add_action_group (solo_actions);
722 MonitorSection::solo_use_in_place ()
724 /* this is driven by a toggle on a radio group, and so is invoked twice,
725 once for the item that became inactive and once for the one that became
729 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
732 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
734 if (!ract->get_active ()) {
735 /* We are turning SiP off, which means that AFL or PFL will be turned on
736 shortly; don't update the solo model in the mean time, as if the currently
737 configured listen position is not the one that is about to be turned on,
738 things will go wrong.
740 _inhibit_solo_model_update = true;
742 Config->set_solo_control_is_listen_control (!ract->get_active());
743 _inhibit_solo_model_update = false;
749 MonitorSection::solo_use_afl ()
751 /* this is driven by a toggle on a radio group, and so is invoked twice,
752 once for the item that became inactive and once for the one that became
756 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
758 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
760 if (ract->get_active()) {
761 Config->set_solo_control_is_listen_control (true);
762 Config->set_listen_position (AfterFaderListen);
769 MonitorSection::solo_use_pfl ()
771 /* this is driven by a toggle on a radio group, and so is invoked twice,
772 once for the item that became inactive and once for the one that became
776 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-pfl"));
778 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
780 if (ract->get_active()) {
781 Config->set_solo_control_is_listen_control (true);
782 Config->set_listen_position (PreFaderListen);
789 MonitorSection::setup_knob_images ()
793 uint32_t c = ARDOUR_UI::config()->color_by_name ("monitor knob");
795 snprintf (buf, 16, "#%x", (c >> 8));
796 MotionFeedback::set_lamp_color (buf);
797 big_knob_pixbuf = MotionFeedback::render_pixbuf (80);
801 error << "No usable large knob image" << endmsg;
802 throw failed_constructor ();
805 if (!big_knob_pixbuf) {
806 error << "No usable large knob image" << endmsg;
807 throw failed_constructor ();
812 little_knob_pixbuf = MotionFeedback::render_pixbuf (30);
816 error << "No usable small knob image" << endmsg;
817 throw failed_constructor ();
820 if (!little_knob_pixbuf) {
821 error << "No usable small knob image" << endmsg;
822 throw failed_constructor ();
828 MonitorSection::update_solo_model ()
830 if (_inhibit_solo_model_update) {
834 const char* action_name = 0;
835 Glib::RefPtr<Action> act;
837 if (Config->get_solo_control_is_listen_control()) {
838 switch (Config->get_listen_position()) {
839 case AfterFaderListen:
840 action_name = X_("solo-use-afl");
843 action_name = X_("solo-use-pfl");
847 action_name = X_("solo-use-in-place");
850 act = ActionManager::get_action (X_("Solo"), action_name);
853 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
855 /* because these are radio buttons, one of them will be
856 active no matter what. to trigger a change in the
857 action so that the view picks it up, toggle it.
859 if (ract->get_active()) {
860 ract->set_active (false);
862 ract->set_active (true);
869 MonitorSection::map_state ()
871 if (!_route || !_monitor) {
875 Glib::RefPtr<Action> act;
877 update_solo_model ();
879 act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
881 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
883 tact->set_active (_monitor->cut_all());
887 act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
889 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
891 tact->set_active (_monitor->dim_all());
895 act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
897 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
899 tact->set_active (_monitor->mono());
903 uint32_t nchans = _monitor->output_streams().n_audio();
905 assert (nchans == _channel_buttons.size ());
907 for (uint32_t n = 0; n < nchans; ++n) {
909 char action_name[32];
911 snprintf (action_name, sizeof (action_name), "monitor-cut-%u", n+1);
912 act = ActionManager::get_action (X_("Monitor"), action_name);
914 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
916 tact->set_active (_monitor->cut (n));
920 snprintf (action_name, sizeof (action_name), "monitor-dim-%u", n+1);
921 act = ActionManager::get_action (X_("Monitor"), action_name);
923 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
925 tact->set_active (_monitor->dimmed (n));
929 snprintf (action_name, sizeof (action_name), "monitor-solo-%u", n+1);
930 act = ActionManager::get_action (X_("Monitor"), action_name);
932 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
934 tact->set_active (_monitor->soloed (n));
938 snprintf (action_name, sizeof (action_name), "monitor-invert-%u", n+1);
939 act = ActionManager::get_action (X_("Monitor"), action_name);
941 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
943 tact->set_active (_monitor->inverted (n));
950 MonitorSection::do_blink (bool onoff)
953 audition_blink (onoff);
957 MonitorSection::audition_blink (bool onoff)
963 if (_session->is_auditioning()) {
964 rude_audition_button.set_active (onoff);
966 rude_audition_button.set_active (false);
971 MonitorSection::solo_blink (bool onoff)
977 if (_session->soloing() || _session->listening()) {
978 rude_solo_button.set_active (onoff);
980 if (_session->soloing()) {
981 if (_session->solo_isolated()) {
982 rude_iso_button.set_active (false);
987 rude_solo_button.set_active (false);
988 rude_iso_button.set_active (false);
993 MonitorSection::cancel_solo (GdkEventButton*)
996 if (_session->soloing()) {
997 _session->set_solo (_session->get_routes(), false);
998 } else if (_session->listening()) {
999 _session->set_listen (_session->get_routes(), false);
1007 MonitorSection::cancel_isolate (GdkEventButton*)
1010 boost::shared_ptr<RouteList> rl (_session->get_routes ());
1011 _session->set_solo_isolated (rl, false, Session::rt_cleanup, true);
1018 MonitorSection::cancel_audition (GdkEventButton*)
1021 _session->cancel_audition();
1027 MonitorSection::parameter_changed (std::string name)
1029 if (name == "solo-control-is-listen-control") {
1030 update_solo_model ();
1031 } else if (name == "listen-position") {
1032 update_solo_model ();
1037 MonitorSection::assign_controllables ()
1039 boost::shared_ptr<Controllable> none;
1041 if (!gain_control) {
1042 /* too early - GUI controls not set up yet */
1047 solo_cut_control->set_controllable (_session->solo_cut_control());
1049 solo_cut_control->set_controllable (none);
1053 gain_control->set_controllable (_route->gain_control());
1055 gain_control->set_controllable (none);
1060 cut_all_button.set_controllable (_monitor->cut_control());
1061 cut_all_button.watch ();
1062 dim_all_button.set_controllable (_monitor->dim_control());
1063 dim_all_button.watch ();
1064 mono_button.set_controllable (_monitor->mono_control());
1065 mono_button.watch ();
1067 dim_control->set_controllable (_monitor->dim_level_control ());
1068 solo_boost_control->set_controllable (_monitor->solo_boost_control ());
1072 cut_all_button.set_controllable (none);
1073 dim_all_button.set_controllable (none);
1074 mono_button.set_controllable (none);
1076 dim_control->set_controllable (none);
1077 solo_boost_control->set_controllable (none);
1082 MonitorSection::state_id() const
1084 return "monitor-section";