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"
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 "gui_thread.h"
17 #include "monitor_section.h"
18 #include "public_editor.h"
20 #include "volume_controller.h"
24 using namespace ARDOUR;
26 using namespace Gtkmm2ext;
30 Glib::RefPtr<ActionGroup> MonitorSection::monitor_actions;
31 Glib::RefPtr<Gdk::Pixbuf> MonitorSection::big_knob_pixbuf;
32 Glib::RefPtr<Gdk::Pixbuf> MonitorSection::little_knob_pixbuf;
35 fixup_prelight (GdkEventCrossing* /* ignored */, GtkWidget* widget)
37 GtkRcStyle* style = gtk_rc_style_copy (gtk_widget_get_modifier_style (widget));
38 int current = gtk_widget_get_state (widget);
40 style->fg[GTK_STATE_PRELIGHT] = style->fg[current];
41 style->bg[GTK_STATE_PRELIGHT] = style->bg[current];
43 gtk_widget_modify_style(widget, style);
44 g_object_unref(style);
50 block_prelight (Gtk::Widget& w)
52 w.signal_enter_notify_event().connect (sigc::bind (sigc::ptr_fun (fixup_prelight), w.gobj()), false);
55 MonitorSection::MonitorSection (Session* s)
60 , gain_adjustment (1.0, 0.0, 1.0, 0.01, 0.1)
62 , dim_adjustment (0.2, 0.0, 1.0, 0.01, 0.1)
64 , solo_boost_adjustment (1.0, 1.0, 2.0, 0.01, 0.1)
65 , solo_boost_control (0)
66 , solo_cut_adjustment (0.0, 0.0, 1.0, 0.01, 0.1)
67 , solo_cut_control (0)
68 , solo_in_place_button (solo_model_group, _("SiP"))
69 , afl_button (solo_model_group, _("AFL"))
70 , pfl_button (solo_model_group, _("PFL"))
71 , cut_all_button (_("MUTE"))
72 , dim_all_button (_("dim"))
73 , mono_button (_("mono"))
74 , rude_solo_button (_("soloing"))
77 Glib::RefPtr<Action> act;
79 if (!monitor_actions) {
81 /* do some static stuff */
94 dim_control = new VolumeController (little_knob_pixbuf, &dim_adjustment, false, 30, 30);
95 dim_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MonitorSection::dim_level_changed));
97 HBox* dim_packer = manage (new HBox);
100 spin_label = manage (new Label (_("Dim Cut")));
101 spin_packer = manage (new VBox);
102 spin_packer->show ();
103 spin_packer->set_spacing (6);
104 spin_packer->pack_start (*dim_control, false, false);
105 spin_packer->pack_start (*spin_label, false, false);
107 dim_packer->set_spacing (12);
108 dim_packer->pack_start (*spin_packer, true, true);
112 rude_solo_button.set_name ("TransportSoloAlert");
113 rude_solo_button.show ();
114 block_prelight (rude_solo_button);
116 ARDOUR_UI::Blink.connect (sigc::mem_fun (*this, &MonitorSection::solo_blink));
117 rude_solo_button.signal_button_press_event().connect (sigc::mem_fun(*this, &MonitorSection::cancel_solo), false);
118 UI::instance()->set_tip (rude_solo_button, _("When active, something is soloed.\nClick to de-solo everything"));
121 solo_model_box.set_spacing (6);
122 solo_model_box.pack_start (solo_in_place_button, false, false);
123 solo_model_box.pack_start (afl_button, false, false);
124 solo_model_box.pack_start (pfl_button, false, false);
126 solo_in_place_button.show ();
129 solo_model_box.show ();
131 act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
133 act->connect_proxy (solo_in_place_button);
136 act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
138 act->connect_proxy (afl_button);
141 act = ActionManager::get_action (X_("Solo"), X_("solo-use-pfl"));
143 act->connect_proxy (pfl_button);
149 solo_boost_control = new VolumeController (little_knob_pixbuf, &solo_boost_adjustment, false, 30, 30);
150 solo_boost_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MonitorSection::solo_boost_changed));
152 HBox* solo_packer = manage (new HBox);
153 solo_packer->set_spacing (12);
154 solo_packer->show ();
156 spin_label = manage (new Label (_("Solo Boost")));
157 spin_packer = manage (new VBox);
158 spin_packer->show ();
159 spin_packer->set_spacing (6);
160 spin_packer->pack_start (*solo_boost_control, false, false);
161 spin_packer->pack_start (*spin_label, false, false);
163 solo_packer->pack_start (*spin_packer, true, true);
167 solo_cut_control = new VolumeController (little_knob_pixbuf, &solo_cut_adjustment, false, 30, 30);
168 solo_cut_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MonitorSection::solo_cut_changed));
170 spin_label = manage (new Label (_("SiP Cut")));
171 spin_packer = manage (new VBox);
172 spin_packer->show ();
173 spin_packer->set_spacing (6);
174 spin_packer->pack_start (*solo_cut_control, false, false);
175 spin_packer->pack_start (*spin_label, false, false);
177 solo_packer->pack_start (*spin_packer, true, true);
179 upper_packer.set_spacing (12);
180 upper_packer.pack_start (rude_solo_button, false, false);
181 upper_packer.pack_start (solo_model_box, false, false);
182 upper_packer.pack_start (*solo_packer, false, false);
184 act = ActionManager::get_action (X_("Monitor"), X_("monitor-cut-all"));
186 act->connect_proxy (cut_all_button);
189 act = ActionManager::get_action (X_("Monitor"), X_("monitor-dim-all"));
191 act->connect_proxy (dim_all_button);
194 act = ActionManager::get_action (X_("Monitor"), X_("monitor-mono"));
196 act->connect_proxy (mono_button);
199 cut_all_button.set_size_request (50,50);
200 cut_all_button.show ();
202 HBox* bbox = manage (new HBox);
204 bbox->set_spacing (12);
205 bbox->pack_start (mono_button, true, true);
206 bbox->pack_start (dim_all_button, true, true);
208 lower_packer.set_spacing (12);
209 lower_packer.pack_start (*bbox, false, false);
210 lower_packer.pack_start (cut_all_button, false, false);
214 gain_control = new VolumeController (big_knob_pixbuf, &gain_adjustment, false, 80, 80);
215 gain_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MonitorSection::gain_value_changed));
217 spin_label = manage (new Label (_("Gain")));
218 spin_packer = manage (new VBox);
219 spin_packer->show ();
220 spin_packer->set_spacing (6);
221 spin_packer->pack_start (*gain_control, false, false);
222 spin_packer->pack_start (*spin_label, false, false);
224 lower_packer.pack_start (*spin_packer, true, true);
226 vpacker.set_border_width (12);
227 vpacker.set_spacing (12);
228 vpacker.pack_start (upper_packer, false, false);
229 vpacker.pack_start (*dim_packer, false, false);
230 vpacker.pack_start (main_table, false, false);
231 vpacker.pack_start (lower_packer, false, false);
233 hpacker.set_border_width (12);
234 hpacker.set_spacing (12);
235 hpacker.pack_start (vpacker, true, true);
237 gain_control->show_all ();
238 dim_control->show_all ();
239 solo_boost_control->show_all ();
243 upper_packer.show ();
244 lower_packer.show ();
250 _tearoff = new TearOff (hpacker);
252 /* if torn off, make this a normal window */
253 _tearoff->tearoff_window().set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
254 _tearoff->tearoff_window().set_title (X_("Monitor"));
255 _tearoff->tearoff_window().signal_key_press_event().connect (sigc::ptr_fun (forward_key_press), false);
257 /* catch changes that affect us */
259 Config->ParameterChanged.connect (config_connection, ui_bind (&MonitorSection::parameter_changed, this, _1), gui_context());
262 MonitorSection::~MonitorSection ()
264 for (ChannelButtons::iterator i = _channel_buttons.begin(); i != _channel_buttons.end(); ++i) {
268 _channel_buttons.clear ();
272 delete solo_boost_control;
277 MonitorSection::set_session (Session* s)
279 AxisView::set_session (s);
283 _route = _session->monitor_out ();
286 /* session with control outs */
287 _monitor = _route->monitor_control ();
289 /* session with no control outs */
300 /* both might be null */
303 MonitorSection::ChannelButtonSet::ChannelButtonSet ()
309 cut.set_name (X_("MixerMuteButton"));
310 dim.set_name (X_("MixerMuteButton"));
311 solo.set_name (X_("MixerSoloButton"));
313 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (cut.gobj()), false);
314 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dim.gobj()), false);
315 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (invert.gobj()), false);
316 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (solo.gobj()), false);
318 block_prelight (cut);
319 block_prelight (dim);
320 block_prelight (solo);
321 block_prelight (invert);
325 MonitorSection::populate_buttons ()
331 Glib::RefPtr<Action> act;
332 uint32_t nchans = _monitor->output_streams().n_audio();
334 main_table.resize (nchans+1, 5);
335 main_table.set_col_spacings (6);
336 main_table.set_row_spacings (6);
337 main_table.set_homogeneous (true);
339 Label* l1 = manage (new Label (X_("out")));
340 main_table.attach (*l1, 0, 1, 0, 1, SHRINK|FILL, SHRINK|FILL);
341 l1 = manage (new Label (X_("cut")));
342 main_table.attach (*l1, 1, 2, 0, 1, SHRINK|FILL, SHRINK|FILL);
343 l1 = manage (new Label (X_("dim")));
344 main_table.attach (*l1, 2, 3, 0, 1, SHRINK|FILL, SHRINK|FILL);
345 l1 = manage (new Label (X_("solo")));
346 main_table.attach (*l1, 3, 4, 0, 1, SHRINK|FILL, SHRINK|FILL);
347 l1 = manage (new Label (X_("inv")));
348 main_table.attach (*l1, 4, 5, 0, 1, SHRINK|FILL, SHRINK|FILL);
350 const uint32_t row_offset = 1;
352 for (uint32_t i = 0; i < nchans; ++i) {
365 snprintf (buf, sizeof (buf), "%d", i+1);
369 Label* label = manage (new Label (l));
370 main_table.attach (*label, 0, 1, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
372 ChannelButtonSet* cbs = new ChannelButtonSet;
374 _channel_buttons.push_back (cbs);
376 main_table.attach (cbs->cut, 1, 2, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
377 main_table.attach (cbs->dim, 2, 3, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
378 main_table.attach (cbs->solo, 3, 4, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
379 main_table.attach (cbs->invert, 4, 5, i+row_offset, i+row_offset+1, SHRINK|FILL, SHRINK|FILL);
381 snprintf (buf, sizeof (buf), "monitor-cut-%u", i+1);
382 act = ActionManager::get_action (X_("Monitor"), buf);
384 act->connect_proxy (cbs->cut);
387 snprintf (buf, sizeof (buf), "monitor-dim-%u", i+1);
388 act = ActionManager::get_action (X_("Monitor"), buf);
390 act->connect_proxy (cbs->dim);
393 snprintf (buf, sizeof (buf), "monitor-solo-%u", i+1);
394 act = ActionManager::get_action (X_("Monitor"), buf);
396 act->connect_proxy (cbs->solo);
399 snprintf (buf, sizeof (buf), "monitor-invert-%u", i+1);
400 act = ActionManager::get_action (X_("Monitor"), buf);
402 act->connect_proxy (cbs->invert);
406 main_table.show_all ();
410 MonitorSection::set_button_names ()
412 rec_enable_button_label.set_text ("rec");
413 mute_button_label.set_text ("rec");
414 solo_button_label.set_text ("rec");
418 MonitorSection::dim_all ()
424 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
426 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
427 _monitor->set_dim_all (tact->get_active());
433 MonitorSection::cut_all ()
439 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
441 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
442 _monitor->set_cut_all (tact->get_active());
447 MonitorSection::mono ()
453 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
455 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
456 _monitor->set_mono (tact->get_active());
461 MonitorSection::cut_channel (uint32_t chn)
468 snprintf (buf, sizeof (buf), "monitor-cut-%u", chn);
470 --chn; // 0-based in backend
472 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
474 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
475 _monitor->set_cut (chn, tact->get_active());
480 MonitorSection::dim_channel (uint32_t chn)
487 snprintf (buf, sizeof (buf), "monitor-dim-%u", chn);
489 --chn; // 0-based in backend
491 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
493 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
494 _monitor->set_dim (chn, tact->get_active());
500 MonitorSection::solo_channel (uint32_t chn)
507 snprintf (buf, sizeof (buf), "monitor-solo-%u", chn);
509 --chn; // 0-based in backend
511 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
513 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
514 _monitor->set_solo (chn, tact->get_active());
520 MonitorSection::invert_channel (uint32_t chn)
527 snprintf (buf, sizeof (buf), "monitor-invert-%u", chn);
529 --chn; // 0-based in backend
531 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), buf);
533 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
534 _monitor->set_polarity (chn, tact->get_active());
539 MonitorSection::register_actions ()
544 monitor_actions = ActionGroup::create (X_("Monitor"));
545 ActionManager::add_action_group (monitor_actions);
547 ActionManager::register_toggle_action (monitor_actions, "monitor-mono", "",
548 sigc::mem_fun (*this, &MonitorSection::mono));
550 ActionManager::register_toggle_action (monitor_actions, "monitor-cut-all", "",
551 sigc::mem_fun (*this, &MonitorSection::cut_all));
553 ActionManager::register_toggle_action (monitor_actions, "monitor-dim-all", "",
554 sigc::mem_fun (*this, &MonitorSection::dim_all));
556 /* note the 1-based counting (for naming - backend uses 0-based) */
558 for (uint32_t chn = 1; chn <= 16; ++chn) {
560 /* for the time being, do not use the action description because it always
561 shows up in the buttons, which is undesirable.
564 action_name = string_compose (X_("monitor-cut-%1"), chn);
565 action_descr = string_compose (_("Cut Monitor Chn %1"), chn);
566 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "",
567 sigc::bind (sigc::mem_fun (*this, &MonitorSection::cut_channel), chn));
569 action_name = string_compose (X_("monitor-dim-%1"), chn);
570 action_descr = string_compose (_("Dim Monitor Chn %1"), chn+1);
571 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "",
572 sigc::bind (sigc::mem_fun (*this, &MonitorSection::dim_channel), chn));
574 action_name = string_compose (X_("monitor-solo-%1"), chn);
575 action_descr = string_compose (_("Solo Monitor Chn %1"), chn);
576 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "",
577 sigc::bind (sigc::mem_fun (*this, &MonitorSection::solo_channel), chn));
579 action_name = string_compose (X_("monitor-invert-%1"), chn);
580 action_descr = string_compose (_("Invert Monitor Chn %1"), chn);
581 ActionManager::register_toggle_action (monitor_actions, action_name.c_str(), "",
582 sigc::bind (sigc::mem_fun (*this, &MonitorSection::invert_channel), chn));
587 Glib::RefPtr<ActionGroup> solo_actions = ActionGroup::create (X_("Solo"));
588 RadioAction::Group solo_group;
590 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-in-place", "",
591 sigc::mem_fun (*this, &MonitorSection::solo_use_in_place));
592 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-afl", "",
593 sigc::mem_fun (*this, &MonitorSection::solo_use_afl));
594 ActionManager::register_radio_action (solo_actions, solo_group, "solo-use-pfl", "",
595 sigc::mem_fun (*this, &MonitorSection::solo_use_pfl));
597 ActionManager::add_action_group (solo_actions);
601 MonitorSection::solo_use_in_place ()
603 /* this is driven by a toggle on a radio group, and so is invoked twice,
604 once for the item that became inactive and once for the one that became
608 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-in-place"));
611 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
613 Config->set_solo_control_is_listen_control (!ract->get_active());
619 MonitorSection::solo_use_afl ()
621 /* this is driven by a toggle on a radio group, and so is invoked twice,
622 once for the item that became inactive and once for the one that became
626 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
628 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
630 if (ract->get_active()) {
631 Config->set_listen_position (AfterFaderListen);
632 Config->set_solo_control_is_listen_control (true);
639 MonitorSection::solo_use_pfl ()
641 /* this is driven by a toggle on a radio group, and so is invoked twice,
642 once for the item that became inactive and once for the one that became
646 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Solo"), X_("solo-use-afl"));
648 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
650 if (ract->get_active()) {
651 Config->set_listen_position (PreFaderListen);
652 Config->set_solo_control_is_listen_control (true);
659 MonitorSection::setup_knob_images ()
663 big_knob_pixbuf = ::get_icon ("bigknob");
667 error << "No knob image found (or not loadable) at "
670 throw failed_constructor ();
675 little_knob_pixbuf = ::get_icon ("littleknob");
679 error << "No knob image found (or not loadable) at "
682 throw failed_constructor ();
687 MonitorSection::gain_value_changed ()
690 _route->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
695 MonitorSection::dim_level_changed ()
698 _monitor->set_dim_level (dim_adjustment.get_value());
703 MonitorSection::solo_boost_changed ()
706 _monitor->set_solo_boost_level (solo_boost_adjustment.get_value());
711 MonitorSection::nonlinear_gain_printer (SpinButton* button)
713 double val = button->get_adjustment()->get_value();
715 snprintf (buf, sizeof (buf), "%.1f", accurate_coefficient_to_dB (slider_position_to_gain (val)));
716 button->set_text (buf);
721 MonitorSection::linear_gain_printer (SpinButton* button)
723 double val = button->get_adjustment()->get_value();
725 snprintf (buf, sizeof (buf), "%.1f", accurate_coefficient_to_dB (val));
726 button->set_text (buf);
731 MonitorSection::update_solo_model ()
733 const char* action_name;
734 Glib::RefPtr<Action> act;
736 if (Config->get_solo_control_is_listen_control()) {
737 switch (Config->get_listen_position()) {
738 case AfterFaderListen:
739 action_name = X_("solo-use-afl");
742 action_name = X_("solo-use-pfl");
746 action_name = X_("solo-use-in-place");
749 act = ActionManager::get_action (X_("Solo"), action_name);
751 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (act);
753 ract->set_active (true);
759 MonitorSection::map_state ()
761 if (!_route || !_monitor) {
765 gain_control->get_adjustment()->set_value (gain_to_slider_position (_route->gain_control()->get_value()));
766 dim_control->get_adjustment()->set_value (_monitor->dim_level());
767 solo_boost_control->get_adjustment()->set_value (_monitor->solo_boost_level());
769 Glib::RefPtr<Action> act;
771 update_solo_model ();
773 act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
775 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
777 cerr << "Set monitor cut all action to " << _monitor->cut_all () << endl;
778 tact->set_active (_monitor->cut_all());
780 cerr << " no global cut action\n";
783 cerr << " no global cut action2\n";
786 act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
788 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
790 tact->set_active (_monitor->dim_all());
794 act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
796 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
798 tact->set_active (_monitor->mono());
802 uint32_t nchans = _monitor->output_streams().n_audio();
804 assert (nchans == _channel_buttons.size ());
806 for (uint32_t n = 0; n < nchans; ++n) {
808 char action_name[32];
810 snprintf (action_name, sizeof (action_name), "monitor-cut-%u", n+1);
811 act = ActionManager::get_action (X_("Monitor"), action_name);
813 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
815 tact->set_active (_monitor->cut (n));
819 snprintf (action_name, sizeof (action_name), "monitor-dim-%u", n+1);
820 act = ActionManager::get_action (X_("Monitor"), action_name);
822 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
824 tact->set_active (_monitor->dimmed (n));
828 snprintf (action_name, sizeof (action_name), "monitor-solo-%u", n+1);
829 act = ActionManager::get_action (X_("Monitor"), action_name);
831 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
833 tact->set_active (_monitor->soloed (n));
837 snprintf (action_name, sizeof (action_name), "monitor-invert-%u", n+1);
838 act = ActionManager::get_action (X_("Monitor"), action_name);
840 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
842 tact->set_active (_monitor->inverted (n));
849 MonitorSection::solo_blink (bool onoff)
855 if (_session->soloing() || _session->listening()) {
857 rude_solo_button.set_state (STATE_ACTIVE);
859 rude_solo_button.set_state (STATE_NORMAL);
862 // rude_solo_button.set_active (false);
863 rude_solo_button.set_state (STATE_NORMAL);
868 MonitorSection::cancel_solo (GdkEventButton* ev)
871 if (_session->soloing()) {
872 _session->set_solo (_session->get_routes(), false);
873 } else if (_session->listening()) {
874 _session->set_listen (_session->get_routes(), false);
882 MonitorSection::solo_cut_changed ()
884 Config->set_solo_mute_gain (slider_position_to_gain (solo_cut_adjustment.get_value()));
888 MonitorSection::parameter_changed (std::string name)
890 if (name == "solo-control-is-listen-control" ||
891 name == "listen-position") {
892 update_solo_model ();
893 } else if (name == "solo-mute-gain") {
894 solo_cut_adjustment.set_value (gain_to_slider_position (Config->get_solo_mute_gain()));