remove tab-related code for tabbed notebook, add tooltips to new buttons
[ardour.git] / gtk2_ardour / ardour_ui_dialogs.cc
1 /*
2     Copyright (C) 2000 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 /* This file contains any ARDOUR_UI methods that require knowledge of
21    the various dialog boxes, and exists so that no compilation dependency
22    exists between the main ARDOUR_UI modules and their respective classes.
23    This is to cut down on the compile times.  It also helps with my sanity.
24 */
25
26 #include <vector>
27
28 #include "pbd/convert.h"
29
30 #include "ardour/audioengine.h"
31 #include "ardour/automation_watch.h"
32 #include "ardour/control_protocol_manager.h"
33 #include "ardour/profile.h"
34 #include "ardour/session.h"
35 #include "control_protocol/control_protocol.h"
36
37 #include "actions.h"
38 #include "add_route_dialog.h"
39 #include "add_video_dialog.h"
40 #include "ardour_ui.h"
41 #include "big_clock_window.h"
42 #include "bundle_manager.h"
43 #include "global_port_matrix.h"
44 #include "gui_object.h"
45 #include "gui_thread.h"
46 #include "keyeditor.h"
47 #include "location_ui.h"
48 #include "main_clock.h"
49 #include "meterbridge.h"
50 #include "meter_patterns.h"
51 #include "midi_tracer.h"
52 #include "mixer_ui.h"
53 #include "public_editor.h"
54 #include "rc_option_editor.h"
55 #include "route_params_ui.h"
56 #include "shuttle_control.h"
57 #include "session_option_editor.h"
58 #include "speaker_dialog.h"
59 #include "splash.h"
60 #include "sfdb_ui.h"
61 #include "theme_manager.h"
62 #include "time_info_box.h"
63 #include "timers.h"
64
65 #include <gtkmm2ext/keyboard.h>
66
67 #include "i18n.h"
68
69 using namespace ARDOUR;
70 using namespace PBD;
71 using namespace Glib;
72 using namespace Gtk;
73 using namespace Gtkmm2ext;
74
75 void
76 ARDOUR_UI::set_session (Session *s)
77 {
78         SessionHandlePtr::set_session (s);
79
80         if (!_session) {
81                 WM::Manager::instance().set_session (s);
82                 /* Session option editor cannot exist across change-of-session */
83                 session_option_editor.drop_window ();
84                 /* Ditto for AddVideoDialog */
85                 add_video_dialog.drop_window ();
86                 return;
87         }
88
89         const XMLNode* node = _session->extra_xml (X_("UI"));
90
91         if (node) {
92                 const XMLNodeList& children = node->children();
93                 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
94                         if ((*i)->name() == GUIObjectState::xml_node_name) {
95                                 gui_object_state->load (**i);
96                                 break;
97                         }
98                 }
99         }
100
101         WM::Manager::instance().set_session (s);
102
103         AutomationWatch::instance().set_session (s);
104
105         if (shuttle_box) {
106                 shuttle_box->set_session (s);
107         }
108
109         primary_clock->set_session (s);
110         secondary_clock->set_session (s);
111         big_clock->set_session (s);
112         time_info_box->set_session (s);
113         video_timeline->set_session (s);
114
115         /* sensitize menu bar options that are now valid */
116
117         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
118         ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
119
120         if (_session->locations()->num_range_markers()) {
121                 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
122         } else {
123                 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
124         }
125
126         if (!_session->monitor_out()) {
127                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
128                 if (act) {
129                         act->set_sensitive (false);
130                 }
131         }
132
133         /* allow wastebasket flush again */
134
135         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
136         if (act) {
137                 act->set_sensitive (true);
138         }
139
140         /* there are never any selections on startup */
141
142         ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
143         ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
144         ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
145         ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
146         ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
147
148         rec_button.set_sensitive (true);
149
150         solo_alert_button.set_active (_session->soloing());
151
152         setup_session_options ();
153
154         blink_connection = Timers::blink_connect (sigc::mem_fun(*this, &ARDOUR_UI::blink_handler));
155
156         _session->SaveSessionRequested.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::save_session_at_its_request, this, _1), gui_context());
157         _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
158         _session->StepEditStatusChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::step_edit_status_change, this, _1), gui_context());
159         _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
160         _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dirty_changed, this), gui_context());
161
162         _session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
163         _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
164         _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
165         _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
166         _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
167         _session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
168
169         /* Clocks are on by default after we are connected to a session, so show that here.
170         */
171
172         connect_dependents_to_session (s);
173
174         /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
175            restore their modes or are explicitly set, we will cause the "new" mode to be saved
176            back to the session XML ("Extra") state.
177          */
178
179         AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
180
181         Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
182
183         start_clocking ();
184
185         map_transport_state ();
186
187         second_connection = Timers::second_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second));
188         point_one_second_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds));
189         point_zero_something_second_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_something_seconds));
190         set_fps_timeout_connection();
191
192         update_format ();
193
194         if (meter_box.get_parent()) {
195                 transport_hbox.remove (meter_box);
196                 transport_hbox.remove (editor_meter_peak_display);
197         }
198
199         if (editor_meter) {
200                 meter_box.remove(*editor_meter);
201                 delete editor_meter;
202                 editor_meter = 0;
203                 editor_meter_peak_display.hide();
204         }
205
206         if (meter_box.get_parent()) {
207                 transport_hbox.remove (meter_box);
208                 transport_hbox.remove (editor_meter_peak_display);
209         }
210
211         if (_session &&
212             _session->master_out() &&
213             _session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
214
215                 if (!ARDOUR::Profile->get_trx()) {
216                         editor_meter = new LevelMeterHBox(_session);
217                         editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
218                         editor_meter->clear_meters();
219                         editor_meter->set_type (_session->master_out()->meter_type());
220                         editor_meter->setup_meters (30, 12, 6);
221                         editor_meter->show();
222                         meter_box.pack_start(*editor_meter);
223                 }
224
225                 ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
226                 ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
227                 ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
228
229                 editor_meter_peak_display.set_name ("meterbridge peakindicator");
230                 editor_meter_peak_display.unset_flags (Gtk::CAN_FOCUS);
231                 editor_meter_peak_display.set_size_request (std::max(9.f, rintf(8.f * UIConfiguration::instance().get_ui_scale())), -1);
232                 editor_meter_peak_display.set_corner_radius (3.0);
233
234                 editor_meter_max_peak = -INFINITY;
235                 editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
236
237                 if (UIConfiguration::instance().get_show_editor_meter() && !ARDOUR::Profile->get_trx()) {
238                         transport_hbox.pack_start (meter_box, false, false);
239                         transport_hbox.pack_start (editor_meter_peak_display, false, false);
240                         meter_box.show();
241                         editor_meter_peak_display.show();
242                 }
243         }
244
245         update_title ();
246 }
247
248 int
249 ARDOUR_UI::unload_session (bool hide_stuff)
250 {
251         if (_session) {
252                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
253         }
254
255         if (_session && _session->dirty()) {
256                 std::vector<std::string> actions;
257                 actions.push_back (_("Don't close"));
258                 actions.push_back (_("Just close"));
259                 actions.push_back (_("Save and close"));
260                 switch (ask_about_saving_session (actions)) {
261                 case -1:
262                         // cancel
263                         return 1;
264
265                 case 1:
266                         _session->save_state ("");
267                         break;
268                 }
269         }
270
271         {
272                 // tear down session specific CPI (owned by rc_config_editor which can remain)
273                 ControlProtocolManager& m = ControlProtocolManager::instance ();
274                 for (std::list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
275                         if (*i && (*i)->protocol && (*i)->protocol->has_editor ()) {
276                                 (*i)->protocol->tear_down_gui ();
277                         }
278                 }
279         }
280
281         if (hide_stuff) {
282                 editor->hide ();
283                 mixer->hide ();
284                 meterbridge->hide ();
285                 audio_port_matrix->hide();
286                 midi_port_matrix->hide();
287                 route_params->hide();
288         }
289
290         second_connection.disconnect ();
291         point_one_second_connection.disconnect ();
292         point_zero_something_second_connection.disconnect();
293         fps_connection.disconnect();
294
295         if (editor_meter) {
296                 meter_box.remove(*editor_meter);
297                 delete editor_meter;
298                 editor_meter = 0;
299                 editor_meter_peak_display.hide();
300         }
301
302         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
303
304         rec_button.set_sensitive (false);
305
306         WM::Manager::instance().set_session ((ARDOUR::Session*) 0);
307
308         if (ARDOUR_UI::instance()->video_timeline) {
309                 ARDOUR_UI::instance()->video_timeline->close_session();
310         }
311
312         stop_clocking ();
313
314         /* drop everything attached to the blink signal */
315
316         blink_connection.disconnect ();
317
318         delete _session;
319         _session = 0;
320
321         session_loaded = false;
322
323         update_buffer_load ();
324         update_title ();
325
326         return 0;
327 }
328
329 void
330 ARDOUR_UI::show_tabbable (Tabbable* t)
331 {
332         if (!t) {
333                 return;
334         }
335
336         t->make_visible ();
337 }
338
339 void
340 ARDOUR_UI::hide_tabbable (Tabbable* t)
341 {
342         if (!t) {
343                 return;
344         }
345         t->make_invisible ();
346 }
347
348 void
349 ARDOUR_UI::attach_tabbable (Tabbable* t)
350 {
351         if (!t) {
352                 return;
353         }
354
355         t->attach ();
356 }
357
358 void
359 ARDOUR_UI::detach_tabbable (Tabbable* t)
360 {
361         if (!t) {
362                 return;
363         }
364         t->detach ();
365 }
366
367 void
368 ARDOUR_UI::tabs_switch (GtkNotebookPage*, guint page)
369 {
370         if (page == (guint) _tabs.page_num (editor->contents())) {
371                 editor_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
372                 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
373                         mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
374                 }
375                 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
376                         prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
377                 }
378         } else if (page == (guint) _tabs.page_num (mixer->contents())) {
379                 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
380                         editor_visibility_button.set_active_state (Gtkmm2ext::Off);
381                 }
382                 mixer_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
383
384                 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
385                         prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
386                 }
387         } else {
388                 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
389                         editor_visibility_button.set_active_state (Gtkmm2ext::Off);
390                 }
391                 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
392                         mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
393                 }
394                 prefs_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
395         }
396
397 }
398
399 void
400 ARDOUR_UI::tabbable_state_change (Tabbable& t)
401 {
402         std::vector<std::string> insensitive_action_names;
403         std::vector<std::string> sensitive_action_names;
404         std::vector<std::string> active_action_names;
405         std::vector<std::string> inactive_action_names;
406         Glib::RefPtr<Action> action;
407         std::string downcased_name = downcase (t.name());
408         enum ViewState {
409                 Tabbed,
410                 Windowed,
411                 Hidden
412         };
413         ViewState vs;
414
415         if (t.tabbed()) {
416
417                 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
418                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
419                 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
420                 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
421
422                 vs = Tabbed;
423
424         } else if (t.tabbed_by_default ()) {
425
426                 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
427                 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
428                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
429                 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
430
431                 vs = Hidden;
432
433         } else if (t.window_visible()) {
434
435                 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
436                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
437                 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
438                 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
439
440                 active_action_names.push_back (string_compose ("show-%1", downcased_name));
441                 inactive_action_names.push_back (string_compose ("hide-%1", downcased_name));
442
443                 vs = Windowed;
444
445         } else {
446
447                 /* not currently visible. allow user to retab it or just make
448                  * it visible.
449                  */
450
451                 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
452                 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
453                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
454                 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
455
456                 active_action_names.push_back (string_compose ("hide-%1", downcased_name));
457                 inactive_action_names.push_back (string_compose ("show-%1", downcased_name));
458
459                 vs = Hidden;
460         }
461
462         for (std::vector<std::string>::iterator s = insensitive_action_names.begin(); s != insensitive_action_names.end(); ++s) {
463                 action = ActionManager::get_action (X_("Common"), (*s).c_str());
464                 if (action) {
465                         action->set_sensitive (false);
466                 }
467         }
468
469         for (std::vector<std::string>::iterator s = sensitive_action_names.begin(); s != sensitive_action_names.end(); ++s) {
470                 action = ActionManager::get_action (X_("Common"), (*s).c_str());
471                 if (action) {
472                         action->set_sensitive (true);
473                 }
474         }
475
476         ArdourButton* vis_button = 0;
477         std::vector<ArdourButton*> other_vis_buttons;
478
479         if (&t == editor) {
480                 vis_button = &editor_visibility_button;
481                 other_vis_buttons.push_back (&mixer_visibility_button);
482                 other_vis_buttons.push_back (&prefs_visibility_button);
483         } else if (&t == mixer) {
484                 vis_button = &mixer_visibility_button;
485                 other_vis_buttons.push_back (&editor_visibility_button);
486                 other_vis_buttons.push_back (&prefs_visibility_button);
487         } else {
488                 vis_button = &prefs_visibility_button;
489                 other_vis_buttons.push_back (&editor_visibility_button);
490                 other_vis_buttons.push_back (&mixer_visibility_button);
491         }
492
493         if (!vis_button) {
494                 return;
495         }
496
497         switch (vs) {
498         case Tabbed:
499                 vis_button->set_active_state (Gtkmm2ext::ImplicitActive);
500                 break;
501         case Windowed:
502                 vis_button->set_active_state (Gtkmm2ext::ExplicitActive);
503                 break;
504         case Hidden:
505                 vis_button->set_active_state (Gtkmm2ext::Off);
506                 break;
507         }
508 }
509
510 void
511 ARDOUR_UI::toggle_meterbridge ()
512 {
513         assert (editor && mixer && meterbridge);
514
515         bool show = false;
516         bool obscuring = false;
517
518         if (meterbridge->not_visible ()) {
519                 show = true;
520         } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) ||
521                    (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) {
522                 obscuring = true;
523         }
524
525         if (obscuring && (editor->own_window()->property_has_toplevel_focus() || (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
526                 show = true;
527         }
528
529         if (show) {
530                 meterbridge->show_window ();
531                 meterbridge->present ();
532                 meterbridge->raise ();
533         } else {
534                 meterbridge->hide_window (NULL);
535         }
536 }
537
538 void
539 ARDOUR_UI::new_midi_tracer_window ()
540 {
541         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
542         if (!act) {
543                 return;
544         }
545
546         std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
547         while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
548                 ++i;
549         }
550
551         if (i == _midi_tracer_windows.end()) {
552                 /* all our MIDITracer windows are visible; make a new one */
553                 MidiTracer* t = new MidiTracer ();
554                 t->show_all ();
555                 _midi_tracer_windows.push_back (t);
556         } else {
557                 /* re-use the hidden one */
558                 (*i)->show_all ();
559         }
560 }
561
562 KeyEditor*
563 ARDOUR_UI::create_key_editor ()
564 {
565         KeyEditor* kedit = new KeyEditor;
566
567         if (global_bindings) {
568                 kedit->add_tab (_("Global"), *global_bindings);
569         }
570
571         if (editor->bindings) {
572                 kedit->add_tab (_("Editing"), *editor->bindings);
573         }
574
575         if (mixer->bindings) {
576                 kedit->add_tab (_("Mixing"), *mixer->bindings);
577         }
578
579         return kedit;
580 }
581
582 BundleManager*
583 ARDOUR_UI::create_bundle_manager ()
584 {
585         return new BundleManager (_session);
586 }
587
588 AddVideoDialog*
589 ARDOUR_UI::create_add_video_dialog ()
590 {
591         return new AddVideoDialog (_session);
592 }
593
594 SessionOptionEditor*
595 ARDOUR_UI::create_session_option_editor ()
596 {
597         return new SessionOptionEditor (_session);
598 }
599
600 BigClockWindow*
601 ARDOUR_UI::create_big_clock_window ()
602 {
603         return new BigClockWindow (*big_clock);
604 }
605
606 void
607 ARDOUR_UI::handle_locations_change (Location *)
608 {
609         if (_session) {
610                 if (_session->locations()->num_range_markers()) {
611                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
612                 } else {
613                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
614                 }
615         }
616 }
617
618 bool
619 ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object)
620 {
621         if (object == editor) {
622
623                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
624                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
625                         if (big_clock_window) {
626                                 big_clock_window->set_transient_for (*editor->own_window());
627                         }
628                 }
629
630         } else if (object == mixer) {
631
632                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
633                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
634                         if (big_clock_window) {
635                                 big_clock_window->set_transient_for (*mixer->own_window());
636                         }
637                 }
638         }
639
640         return false;
641 }
642
643 bool
644 ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
645 {
646         if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier|Gtkmm2ext::Keyboard::TertiaryModifier)) {
647                 ArdourMeter::ResetAllPeakDisplays ();
648         } else if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
649                 if (_session->master_out()) {
650                         ArdourMeter::ResetGroupPeakDisplays (_session->master_out()->route_group());
651                 }
652         } else if (_session->master_out()) {
653                 ArdourMeter::ResetRoutePeakDisplays (_session->master_out().get());
654         }
655         return false;
656 }
657
658 void
659 ARDOUR_UI::toggle_mixer_space()
660 {
661         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMaximalMixer");
662
663         if (act) {
664                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
665                 if (tact->get_active()) {
666                         mixer->maximise_mixer_space ();
667                 } else {
668                         mixer->restore_mixer_space ();
669                 }
670         }
671 }
672
673 void
674 ARDOUR_UI::toggle_mixer_list()
675 {
676         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMixerList");
677
678         if (act) {
679                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
680                         mixer->show_mixer_list (tact->get_active());
681         }
682 }
683
684 void
685 ARDOUR_UI::toggle_monitor_section_visibility ()
686 {
687         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
688
689         if (act) {
690                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
691                         mixer->show_monitor_section (tact->get_active());
692         }
693 }