2 Copyright (C) 2012 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <gdkmm/pixbuf.h>
22 #include "pbd/compose.h"
23 #include "pbd/error.h"
25 #include "gtkmm2ext/bindable_button.h"
26 #include "gtkmm2ext/tearoff.h"
27 #include "gtkmm2ext/actions.h"
28 #include "gtkmm2ext/motionfeedback.h"
30 #include "ardour/monitor_processor.h"
31 #include "ardour/route.h"
33 #include "ardour_ui.h"
34 #include "gui_thread.h"
35 #include "monitor_section.h"
36 #include "public_editor.h"
37 #include "volume_controller.h"
42 using namespace ARDOUR;
44 using namespace Gtkmm2ext;
48 Glib::RefPtr<ActionGroup> MonitorSection::monitor_actions;
49 Glib::RefPtr<Gdk::Pixbuf> MonitorSection::big_knob_pixbuf;
50 Glib::RefPtr<Gdk::Pixbuf> MonitorSection::little_knob_pixbuf;
52 MonitorSection::MonitorSection (Session* s)
56 , channel_table_viewport (*channel_table_scroller.get_hadjustment(),
57 *channel_table_scroller.get_vadjustment ())
60 , solo_boost_control (0)
61 , solo_cut_control (0)
62 , solo_in_place_button (_("SiP"), ArdourButton::led_default_elements)
63 , afl_button (_("AFL"), ArdourButton::led_default_elements)
64 , pfl_button (_("PFL"), ArdourButton::led_default_elements)
65 , exclusive_solo_button (ArdourButton::led_default_elements)
66 , solo_mute_override_button (ArdourButton::led_default_elements)
67 , _inhibit_solo_model_update (false)
69 Glib::RefPtr<Action> act;
71 if (!monitor_actions) {
73 /* do some static stuff */
86 rude_solo_button.set_text (_("soloing"));
87 rude_solo_button.set_name ("rude solo");
88 rude_solo_button.show ();
90 rude_iso_button.set_text (_("isolated"));
91 rude_iso_button.set_name ("rude isolate");
92 rude_iso_button.show ();
94 rude_audition_button.set_text (_("auditioning"));
95 rude_audition_button.set_name ("rude audition");
96 rude_audition_button.show ();
98 ARDOUR_UI::Blink.connect (sigc::mem_fun (*this, &MonitorSection::do_blink));
100 rude_solo_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_solo));
101 UI::instance()->set_tip (rude_solo_button, _("When active, something is soloed.\nClick to de-solo everything"));
103 rude_iso_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_isolate));
104 UI::instance()->set_tip (rude_iso_button, _("When active, something is solo-isolated.\nClick to de-isolate everything"));
106 rude_audition_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_audition));
107 UI::instance()->set_tip (rude_audition_button, _("When active, auditioning is active.\nClick to stop the audition"));
109 solo_in_place_button.set_name ("monitor section solo model");
110 afl_button.set_name ("monitor section solo model");
111 pfl_button.set_name ("monitor section solo model");
113 solo_model_box.set_spacing (6);
114 solo_model_box.pack_start (solo_in_place_button, true, false);
115 solo_model_box.pack_start (afl_button, true, false);
116 solo_model_box.pack_start (pfl_button, true, false);
118 solo_in_place_button.show ();
121 solo_model_box.show ();
123 act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
124 ARDOUR_UI::instance()->tooltips().set_tip (solo_in_place_button, _("Solo controls affect solo-in-place"));
126 solo_in_place_button.set_related_action (act);
129 act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
130 ARDOUR_UI::instance()->tooltips().set_tip (afl_button, _("Solo controls toggle after-fader-listen"));
132 afl_button.set_related_action (act);
135 act = ActionManager::get_action (X_("Solo"), X_("solo-use-pfl"));
136 ARDOUR_UI::instance()->tooltips().set_tip (pfl_button, _("Solo controls toggle pre-fader-listen"));
138 pfl_button.set_related_action (act);
143 solo_boost_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.01, 0.1, true, 30, 30, true);
144 ARDOUR_UI::instance()->tooltips().set_tip (*solo_boost_control, _("Gain increase for soloed signals (0dB is normal)"));
146 HBox* solo_packer = manage (new HBox);
147 solo_packer->set_spacing (6);
148 solo_packer->show ();
150 spin_label = manage (new Label (_("Solo Boost")));
151 spin_packer = manage (new VBox);
152 spin_packer->show ();
153 spin_packer->set_spacing (6);
154 spin_packer->pack_start (*solo_boost_control, false, false);
155 spin_packer->pack_start (*spin_label, false, false);
157 solo_packer->pack_start (*spin_packer, true, false);
161 solo_cut_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.1, 0.5, true, 30, 30, true);
162 ARDOUR_UI::instance()->tooltips().set_tip (*solo_cut_control, _("Gain reduction non-soloed signals\nA value above -inf dB causes \"solo-in-front\""));
164 spin_label = manage (new Label (_("SiP Cut")));
165 spin_packer = manage (new VBox);
166 spin_packer->show ();
167 spin_packer->set_spacing (6);
168 spin_packer->pack_start (*solo_cut_control, false, false);
169 spin_packer->pack_start (*spin_label, false, false);
171 solo_packer->pack_start (*spin_packer, true, false);
175 dim_control = new VolumeController (little_knob_pixbuf, boost::shared_ptr<Controllable>(), 0.0, 0.01, 0.1, true, 30, 30, true);
176 ARDOUR_UI::instance()->tooltips().set_tip (*dim_control, _("Gain reduction to use when dimming monitor outputs"));
178 HBox* dim_packer = manage (new HBox);
181 spin_label = manage (new Label (_("Dim")));
182 spin_packer = manage (new VBox);
183 spin_packer->show ();
184 spin_packer->set_spacing (6);
185 spin_packer->pack_start (*dim_control, false, false);
186 spin_packer->pack_start (*spin_label, false, false);
188 dim_packer->pack_start (*spin_packer, true, false);
190 exclusive_solo_button.set_text (_("excl. solo"));
191 exclusive_solo_button.set_name (X_("monitor solo exclusive"));
192 ARDOUR_UI::instance()->set_tip (&exclusive_solo_button, _("Exclusive solo means that only 1 solo is active at a time"));
194 act = ActionManager::get_action (X_("Monitor"), X_("toggle-exclusive-solo"));
196 exclusive_solo_button.set_related_action (act);
199 solo_mute_override_button.set_text (_("solo ยป mute"));
200 solo_mute_override_button.set_name (X_("monitor solo override"));
201 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)"));
203 act = ActionManager::get_action (X_("Monitor"), X_("toggle-mute-overrides-solo"));
205 solo_mute_override_button.set_related_action (act);
208 HBox* solo_opt_box = manage (new HBox);
209 solo_opt_box->set_spacing (12);
210 solo_opt_box->set_homogeneous (true);
211 solo_opt_box->pack_start (exclusive_solo_button);
212 solo_opt_box->pack_start (solo_mute_override_button);
213 solo_opt_box->show ();
215 upper_packer.set_spacing (6);
217 Gtk::HBox* rude_box = manage (new HBox);
218 rude_box->pack_start (rude_solo_button, true, true);
219 rude_box->pack_start (rude_iso_button, true, true);
221 upper_packer.pack_start (*rude_box, false, false);
222 upper_packer.pack_start (rude_audition_button, false, false);
223 upper_packer.pack_start (solo_model_box, false, false, 12);
224 upper_packer.pack_start (*solo_opt_box, false, false);
225 upper_packer.pack_start (*solo_packer, false, false, 12);
227 cut_all_button.set_text (_("mute"));
228 cut_all_button.set_name ("monitor section cut");
229 cut_all_button.set_name (X_("monitor section cut"));
230 cut_all_button.set_size_request (-1,50);
231 cut_all_button.show ();
233 act = ActionManager::get_action (X_("Monitor"), X_("monitor-cut-all"));
235 cut_all_button.set_related_action (act);
238 dim_all_button.set_text (_("dim"));
239 dim_all_button.set_name ("monitor section dim");
240 act = ActionManager::get_action (X_("Monitor"), X_("monitor-dim-all"));
242 dim_all_button.set_related_action (act);
245 mono_button.set_text (_("mono"));
246 mono_button.set_name ("monitor section mono");
247 act = ActionManager::get_action (X_("Monitor"), X_("monitor-mono"));
249 mono_button.set_related_action (act);
252 HBox* bbox = manage (new HBox);
254 bbox->set_spacing (12);
255 bbox->pack_start (mono_button, true, true);
256 bbox->pack_start (dim_all_button, true, true);
258 lower_packer.set_spacing (12);
259 lower_packer.pack_start (*bbox, false, false);
260 lower_packer.pack_start (cut_all_button, false, false);
264 gain_control = new VolumeController (big_knob_pixbuf, boost::shared_ptr<Controllable>(), 1.0, 0.01, 0.1, true, 80, 80, false);
266 spin_label = manage (new Label (_("Monitor")));
267 spin_packer = manage (new VBox);
268 spin_packer->show ();
269 spin_packer->set_spacing (6);
270 spin_packer->pack_start (*gain_control, false, false);
271 spin_packer->pack_start (*spin_label, false, false);
273 lower_packer.pack_start (*spin_packer, true, true);
275 channel_table_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
276 channel_table_scroller.set_size_request (-1, 150);
277 channel_table_scroller.set_shadow_type (Gtk::SHADOW_NONE);
278 channel_table_scroller.show ();
279 channel_table_scroller.add (channel_table_viewport);
281 channel_size_group = SizeGroup::create (SIZE_GROUP_HORIZONTAL);
282 channel_size_group->add_widget (channel_table_header);
283 channel_size_group->add_widget (channel_table);
285 channel_table_header.resize (1, 5);
286 Label* l1 = manage (new Label (X_("out")));
287 l1->set_name (X_("MonitorSectionLabel"));
288 channel_table_header.attach (*l1, 0, 1, 0, 1, EXPAND|FILL);
289 l1 = manage (new Label (X_("mute")));
290 l1->set_name (X_("MonitorSectionLabel"));
291 channel_table_header.attach (*l1, 1, 2, 0, 1, EXPAND|FILL);
292 l1 = manage (new Label (X_("dim")));
293 l1->set_name (X_("MonitorSectionLabel"));
294 channel_table_header.attach (*l1, 2, 3, 0, 1, EXPAND|FILL);
295 l1 = manage (new Label (X_("solo")));
296 l1->set_name (X_("MonitorSectionLabel"));
297 channel_table_header.attach (*l1, 3, 4, 0, 1, EXPAND|FILL);
298 l1 = manage (new Label (X_("inv")));
299 l1->set_name (X_("MonitorSectionLabel"));
300 channel_table_header.attach (*l1, 4, 5, 0, 1, EXPAND|FILL);
301 channel_table_header.show ();
303 table_hpacker.pack_start (channel_table, true, true);
305 /* note that we don't pack the table_hpacker till later
308 vpacker.set_border_width (6);
309 vpacker.set_spacing (12);
310 vpacker.pack_start (upper_packer, false, false);
311 vpacker.pack_start (*dim_packer, false, false);
312 vpacker.pack_start (channel_table_header, false, false);
313 vpacker.pack_start (channel_table_packer, false, false);
314 vpacker.pack_start (lower_packer, false, false);
316 hpacker.pack_start (vpacker, true, true);
318 gain_control->show_all ();
319 dim_control->show_all ();
320 solo_boost_control->show_all ();
322 channel_table.show ();
324 upper_packer.show ();
325 lower_packer.show ();
330 assign_controllables ();
332 _tearoff = new TearOff (hpacker);
334 /* if torn off, make this a normal window */
335 _tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
336 _tearoff->tearoff_window().set_title (X_("Monitor"));
337 _tearoff->tearoff_window().signal_key_press_event().connect (sigc::ptr_fun (forward_key_press), false);
339 /* catch changes that affect us */
341 Config->ParameterChanged.connect (config_connection, invalidator (*this), boost::bind (&MonitorSection::parameter_changed, this, _1), gui_context());
344 MonitorSection::~MonitorSection ()
346 for (ChannelButtons::iterator i = _channel_buttons.begin(); i != _channel_buttons.end(); ++i) {
350 _channel_buttons.clear ();
354 delete solo_boost_control;
359 MonitorSection::set_session (Session* s)
361 AxisView::set_session (s);
365 _route = _session->monitor_out ();
368 /* session with monitor section */
369 _monitor = _route->monitor_control ();
370 assign_controllables ();
372 /* session with no monitor section */
377 if (channel_table_scroller.get_parent()) {
378 /* scroller is packed, so remove it */
379 channel_table_packer.remove (channel_table_scroller);
382 if (table_hpacker.get_parent () == &channel_table_packer) {
383 /* this occurs when the table hpacker is directly
384 packed, so remove it.
386 channel_table_packer.remove (table_hpacker);
387 } else if (table_hpacker.get_parent()) {
388 channel_table_viewport.remove ();
391 if (_monitor->output_streams().n_audio() > 7) {
392 /* put the table into a scrolled window, and then put
393 * that into the channel vpacker, after the table header
395 channel_table_viewport.add (table_hpacker);
396 channel_table_packer.pack_start (channel_table_scroller, true, true);
397 channel_table_viewport.show ();
398 channel_table_scroller.show ();
401 /* just put the channel table itself into the channel
402 * vpacker, after the table header
405 channel_table_packer.pack_start (table_hpacker, true, true);
406 channel_table_scroller.hide ();
409 table_hpacker.show ();
410 channel_table.show ();
417 control_connections.drop_connections ();
418 rude_iso_button.unset_active_state ();
419 rude_solo_button.unset_active_state ();
421 assign_controllables ();
425 MonitorSection::ChannelButtonSet::ChannelButtonSet ()
427 cut.set_diameter (3);
428 dim.set_diameter (3);
429 solo.set_diameter (3);
430 invert.set_diameter (3);
432 cut.set_name (X_("monitor section cut"));
433 dim.set_name (X_("monitor section dim"));
434 solo.set_name (X_("monitor section solo"));
435 invert.set_name (X_("monitor section invert"));
437 cut.unset_flags (Gtk::CAN_FOCUS);
438 dim.unset_flags (Gtk::CAN_FOCUS);
439 solo.unset_flags (Gtk::CAN_FOCUS);
440 invert.unset_flags (Gtk::CAN_FOCUS);
444 MonitorSection::populate_buttons ()
450 Glib::RefPtr<Action> act;
451 uint32_t nchans = _monitor->output_streams().n_audio();
453 channel_table.resize (nchans, 5);
454 channel_table.set_col_spacings (6);
455 channel_table.set_row_spacings (6);
456 channel_table.set_homogeneous (true);
458 const uint32_t row_offset = 0;
460 for (uint32_t i = 0; i < nchans; ++i) {
473 snprintf (buf, sizeof (buf), "%d", i+1);
477 Label* label = manage (new Label (l));
478 channel_table.attach (*label, 0, 1, i+row_offset, i+row_offset+1, EXPAND|FILL);
480 ChannelButtonSet* cbs = new ChannelButtonSet;
482 _channel_buttons.push_back (cbs);
484 channel_table.attach (cbs->cut, 1, 2, i+row_offset, i+row_offset+1, EXPAND|FILL);
485 channel_table.attach (cbs->dim, 2, 3, i+row_offset, i+row_offset+1, EXPAND|FILL);
486 channel_table.attach (cbs->solo, 3, 4, i+row_offset, i+row_offset+1, EXPAND|FILL);
487 channel_table.attach (cbs->invert, 4, 5, i+row_offset, i+row_offset+1, EXPAND|FILL);
489 snprintf (buf, sizeof (buf), "monitor-cut-%u", i+1);
490 act = ActionManager::get_action (X_("Monitor"), buf);
492 cbs->cut.set_related_action (act);
495 snprintf (buf, sizeof (buf), "monitor-dim-%u", i+1);
496 act = ActionManager::get_action (X_("Monitor"), buf);
498 cbs->dim.set_related_action (act);
501 snprintf (buf, sizeof (buf), "monitor-solo-%u", i+1);
502 act = ActionManager::get_action (X_("Monitor"), buf);
504 cbs->solo.set_related_action (act);
507 snprintf (buf, sizeof (buf), "monitor-invert-%u", i+1);
508 act = ActionManager::get_action (X_("Monitor"), buf);
510 cbs->invert.set_related_action (act);
514 channel_table.show_all ();
518 MonitorSection::toggle_exclusive_solo ()
524 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "toggle-exclusive-solo");
526 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
527 Config->set_exclusive_solo (tact->get_active());
534 MonitorSection::toggle_mute_overrides_solo ()
540 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "toggle-mute-overrides-solo");
542 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
543 Config->set_solo_mute_override (tact->get_active());
548 MonitorSection::dim_all ()
554 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
556 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
557 _monitor->set_dim_all (tact->get_active());
563 MonitorSection::cut_all ()
569 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
571 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
572 _monitor->set_cut_all (tact->get_active());
577 MonitorSection::mono ()
583 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
585 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
586 _monitor->set_mono (tact->get_active());
591 MonitorSection::cut_channel (uint32_t chn)
598 snprintf (buf, sizeof (buf), "monitor-cut-%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_cut (chn, tact->get_active());
610 MonitorSection::dim_channel (uint32_t chn)
617 snprintf (buf, sizeof (buf), "monitor-dim-%u", chn);
619 --chn; // 0-based in backend
621 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
623 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
624 _monitor->set_dim (chn, tact->get_active());
630 MonitorSection::solo_channel (uint32_t chn)
637 snprintf (buf, sizeof (buf), "monitor-solo-%u", chn);
639 --chn; // 0-based in backend
641 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
643 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
644 _monitor->set_solo (chn, tact->get_active());
650 MonitorSection::invert_channel (uint32_t chn)
657 snprintf (buf, sizeof (buf), "monitor-invert-%u", chn);
659 --chn; // 0-based in backend
661 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
663 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
664 _monitor->set_polarity (chn, tact->get_active());
669 MonitorSection::register_actions ()
673 Glib::RefPtr<Action> act;
675 monitor_actions = ActionGroup::create (X_("Monitor"));
676 ActionManager::add_action_group (monitor_actions);
678 ActionManager::register_toggle_action (monitor_actions, "monitor-mono", "", _("Switch monitor to mono"),
679 sigc::mem_fun (*this, &MonitorSection::mono));
681 ActionManager::register_toggle_action (monitor_actions, "monitor-cut-all", "", _("Cut monitor"),
682 sigc::mem_fun (*this, &MonitorSection::cut_all));
684 ActionManager::register_toggle_action (monitor_actions, "monitor-dim-all", "", _("Dim monitor"),
685 sigc::mem_fun (*this, &MonitorSection::dim_all));
687 act = ActionManager::register_toggle_action (monitor_actions, "toggle-exclusive-solo", "", _("Toggle exclusive solo mode"),
688 sigc::mem_fun (*this, &MonitorSection::toggle_exclusive_solo));
690 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
691 tact->set_active (Config->get_exclusive_solo());
693 act = ActionManager::register_toggle_action (monitor_actions, "toggle-mute-overrides-solo", "", _("Toggle mute overrides solo mode"),
694 sigc::mem_fun (*this, &MonitorSection::toggle_mute_overrides_solo));
696 tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
697 tact->set_active (Config->get_solo_mute_override());
700 /* note the 1-based counting (for naming - backend uses 0-based) */
702 for (uint32_t chn = 1; chn <= 16; ++chn) {
704 action_name = string_compose (X_("monitor-cut-%1"), chn);
705 action_descr = string_compose (_("Cut monitor channel %1"), chn);
706 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
707 sigc::bind (sigc::mem_fun (*this, &MonitorSection::cut_channel), chn));
709 action_name = string_compose (X_("monitor-dim-%1"), chn);
710 action_descr = string_compose (_("Dim monitor channel %1"), chn);
711 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
712 sigc::bind (sigc::mem_fun (*this, &MonitorSection::dim_channel), chn));
714 action_name = string_compose (X_("monitor-solo-%1"), chn);
715 action_descr = string_compose (_("Solo monitor channel %1"), chn);
716 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
717 sigc::bind (sigc::mem_fun (*this, &MonitorSection::solo_channel), chn));
719 action_name = string_compose (X_("monitor-invert-%1"), chn);
720 action_descr = string_compose (_("Invert monitor channel %1"), chn);
721 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "", action_descr.c_str(),
722 sigc::bind (sigc::mem_fun (*this, &MonitorSection::invert_channel), chn));
727 Glib::RefPtr<ActionGroup> solo_actions = ActionGroup::create (X_("Solo"));
728 RadioAction::Group solo_group;
730 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-in-place", "", _("In-place solo"),
731 sigc::mem_fun (*this, &MonitorSection::solo_use_in_place));
732 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-afl", "", _("After Fade Listen (AFL) solo"),
733 sigc::mem_fun (*this, &MonitorSection::solo_use_afl));
734 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-pfl", "", _("Pre Fade Listen (PFL) solo"),
735 sigc::mem_fun (*this, &MonitorSection::solo_use_pfl));
737 ActionManager::add_action_group (solo_actions);
741 MonitorSection::solo_use_in_place ()
743 /* this is driven by a toggle on a radio group, and so is invoked twice,
744 once for the item that became inactive and once for the one that became
748 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
751 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
753 if (!ract->get_active ()) {
754 /* We are turning SiP off, which means that AFL or PFL will be turned on
755 shortly; don't update the solo model in the mean time, as if the currently
756 configured listen position is not the one that is about to be turned on,
757 things will go wrong.
759 _inhibit_solo_model_update = true;
761 Config->set_solo_control_is_listen_control (!ract->get_active());
762 _inhibit_solo_model_update = false;
768 MonitorSection::solo_use_afl ()
770 /* this is driven by a toggle on a radio group, and so is invoked twice,
771 once for the item that became inactive and once for the one that became
775 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
777 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
779 if (ract->get_active()) {
780 Config->set_solo_control_is_listen_control (true);
781 Config->set_listen_position (AfterFaderListen);
788 MonitorSection::solo_use_pfl ()
790 /* this is driven by a toggle on a radio group, and so is invoked twice,
791 once for the item that became inactive and once for the one that became
795 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-pfl"));
797 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
799 if (ract->get_active()) {
800 Config->set_solo_control_is_listen_control (true);
801 Config->set_listen_position (PreFaderListen);
808 MonitorSection::setup_knob_images ()
812 uint32_t c = ARDOUR_UI::config()->color_by_name ("monitor knob");
814 snprintf (buf, 16, "#%x", (c >> 8));
815 MotionFeedback::set_lamp_color (buf);
816 big_knob_pixbuf = MotionFeedback::render_pixbuf (80);
820 error << "No usable large knob image" << endmsg;
821 throw failed_constructor ();
824 if (!big_knob_pixbuf) {
825 error << "No usable large knob image" << endmsg;
826 throw failed_constructor ();
831 little_knob_pixbuf = MotionFeedback::render_pixbuf (30);
835 error << "No usable small knob image" << endmsg;
836 throw failed_constructor ();
839 if (!little_knob_pixbuf) {
840 error << "No usable small knob image" << endmsg;
841 throw failed_constructor ();
847 MonitorSection::update_solo_model ()
849 if (_inhibit_solo_model_update) {
853 const char* action_name = 0;
854 Glib::RefPtr<Action> act;
856 if (Config->get_solo_control_is_listen_control()) {
857 switch (Config->get_listen_position()) {
858 case AfterFaderListen:
859 action_name = X_("solo-use-afl");
862 action_name = X_("solo-use-pfl");
866 action_name = X_("solo-use-in-place");
869 act = ActionManager::get_action (X_("Solo"), action_name);
872 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
874 /* because these are radio buttons, one of them will be
875 active no matter what. to trigger a change in the
876 action so that the view picks it up, toggle it.
878 if (ract->get_active()) {
879 ract->set_active (false);
881 ract->set_active (true);
888 MonitorSection::map_state ()
890 if (!_route || !_monitor) {
894 Glib::RefPtr<Action> act;
896 update_solo_model ();
898 act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
900 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
902 tact->set_active (_monitor->cut_all());
906 act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
908 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
910 tact->set_active (_monitor->dim_all());
914 act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
916 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
918 tact->set_active (_monitor->mono());
922 uint32_t nchans = _monitor->output_streams().n_audio();
924 assert (nchans == _channel_buttons.size ());
926 for (uint32_t n = 0; n < nchans; ++n) {
928 char action_name[32];
930 snprintf (action_name, sizeof (action_name), "monitor-cut-%u", n);
931 act = ActionManager::get_action (X_("Monitor"), action_name);
933 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
935 tact->set_active (_monitor->cut (n));
939 snprintf (action_name, sizeof (action_name), "monitor-dim-%u", n);
940 act = ActionManager::get_action (X_("Monitor"), action_name);
942 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
944 tact->set_active (_monitor->dimmed (n));
948 snprintf (action_name, sizeof (action_name), "monitor-solo-%u", n);
949 act = ActionManager::get_action (X_("Monitor"), action_name);
951 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
953 tact->set_active (_monitor->soloed (n));
957 snprintf (action_name, sizeof (action_name), "monitor-invert-%u", n);
958 act = ActionManager::get_action (X_("Monitor"), action_name);
960 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
962 tact->set_active (_monitor->inverted (n));
969 MonitorSection::do_blink (bool onoff)
972 audition_blink (onoff);
976 MonitorSection::audition_blink (bool onoff)
982 if (_session->is_auditioning()) {
983 rude_audition_button.set_active (onoff);
985 rude_audition_button.set_active (false);
990 MonitorSection::solo_blink (bool onoff)
996 if (_session->soloing() || _session->listening()) {
997 rude_solo_button.set_active (onoff);
999 if (_session->soloing()) {
1000 if (_session->solo_isolated()) {
1001 rude_iso_button.set_active (false);
1006 rude_solo_button.set_active (false);
1007 rude_iso_button.set_active (false);
1012 MonitorSection::cancel_solo (GdkEventButton*)
1015 if (_session->soloing()) {
1016 _session->set_solo (_session->get_routes(), false);
1017 } else if (_session->listening()) {
1018 _session->set_listen (_session->get_routes(), false);
1026 MonitorSection::cancel_isolate (GdkEventButton*)
1029 boost::shared_ptr<RouteList> rl (_session->get_routes ());
1030 _session->set_solo_isolated (rl, false, Session::rt_cleanup, true);
1037 MonitorSection::cancel_audition (GdkEventButton*)
1040 _session->cancel_audition();
1046 MonitorSection::parameter_changed (std::string name)
1048 if (name == "solo-control-is-listen-control") {
1049 update_solo_model ();
1050 } else if (name == "listen-position") {
1051 update_solo_model ();
1056 MonitorSection::assign_controllables ()
1058 boost::shared_ptr<Controllable> none;
1060 if (!gain_control) {
1061 /* too early - GUI controls not set up yet */
1066 solo_cut_control->set_controllable (_session->solo_cut_control());
1068 solo_cut_control->set_controllable (none);
1072 gain_control->set_controllable (_route->gain_control());
1074 gain_control->set_controllable (none);
1079 cut_all_button.set_controllable (_monitor->cut_control());
1080 cut_all_button.watch ();
1081 dim_all_button.set_controllable (_monitor->dim_control());
1082 dim_all_button.watch ();
1083 mono_button.set_controllable (_monitor->mono_control());
1084 mono_button.watch ();
1086 dim_control->set_controllable (_monitor->dim_level_control ());
1087 solo_boost_control->set_controllable (_monitor->solo_boost_control ());
1091 cut_all_button.set_controllable (none);
1092 dim_all_button.set_controllable (none);
1093 mono_button.set_controllable (none);
1095 dim_control->set_controllable (none);
1096 solo_boost_control->set_controllable (none);
1101 MonitorSection::state_id() const
1103 return "monitor-section";