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