90cc8907430246b81c76802770d476b08bf1d4c8
[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 "lua_script_manager.h"
53 #include "luawindow.h"
54 #include "main_clock.h"
55 #include "meterbridge.h"
56 #include "meter_patterns.h"
57 #include "monitor_section.h"
58 #include "midi_tracer.h"
59 #include "mixer_ui.h"
60 #include "public_editor.h"
61 #include "processor_box.h"
62 #include "rc_option_editor.h"
63 #include "route_params_ui.h"
64 #include "shuttle_control.h"
65 #include "session_option_editor.h"
66 #include "speaker_dialog.h"
67 #include "splash.h"
68 #include "sfdb_ui.h"
69 #include "theme_manager.h"
70 #include "timers.h"
71
72 #include "pbd/i18n.h"
73
74 using namespace ARDOUR;
75 using namespace PBD;
76 using namespace Glib;
77 using namespace Gtk;
78 using namespace Gtkmm2ext;
79
80 void
81 ARDOUR_UI::set_session (Session *s)
82 {
83         SessionHandlePtr::set_session (s);
84
85         if (!_session) {
86                 WM::Manager::instance().set_session (s);
87                 /* Session option editor cannot exist across change-of-session */
88                 session_option_editor.drop_window ();
89                 /* Ditto for AddVideoDialog */
90                 add_video_dialog.drop_window ();
91                 return;
92         }
93
94         const XMLNode* node = _session->extra_xml (X_("UI"));
95
96         if (node) {
97                 const XMLNodeList& children = node->children();
98                 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
99                         if ((*i)->name() == GUIObjectState::xml_node_name) {
100                                 gui_object_state->load (**i);
101                                 break;
102                         }
103                 }
104         }
105
106         WM::Manager::instance().set_session (s);
107
108         AutomationWatch::instance().set_session (s);
109
110         if (shuttle_box) {
111                 shuttle_box->set_session (s);
112         }
113
114         primary_clock->set_session (s);
115         secondary_clock->set_session (s);
116         big_clock->set_session (s);
117         video_timeline->set_session (s);
118
119         /* sensitize menu bar options that are now valid */
120
121         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
122         ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
123
124         if (_session->locations()->num_range_markers()) {
125                 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
126         } else {
127                 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
128         }
129
130         if (!_session->monitor_out()) {
131                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
132                 if (act) {
133                         act->set_sensitive (false);
134                 }
135         }
136
137         /* allow wastebasket flush again */
138
139         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
140         if (act) {
141                 act->set_sensitive (true);
142         }
143
144         /* there are never any selections on startup */
145
146         ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
147         ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
148         ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
149         ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
150         ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
151
152         rec_button.set_sensitive (true);
153
154         solo_alert_button.set_active (_session->soloing());
155
156         setup_session_options ();
157
158         blink_connection = Timers::blink_connect (sigc::mem_fun(*this, &ARDOUR_UI::blink_handler));
159
160         _session->SaveSessionRequested.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::save_session_at_its_request, this, _1), gui_context());
161         _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
162         _session->StepEditStatusChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::step_edit_status_change, this, _1), gui_context());
163         _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
164         _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dirty_changed, this), gui_context());
165
166         _session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
167         _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
168         _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
169         _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
170         _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
171         _session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
172
173         /* Clocks are on by default after we are connected to a session, so show that here.
174         */
175
176         connect_dependents_to_session (s);
177
178         /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
179            restore their modes or are explicitly set, we will cause the "new" mode to be saved
180            back to the session XML ("Extra") state.
181          */
182
183         AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
184
185         Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
186
187         start_clocking ();
188
189         map_transport_state ();
190
191         second_connection = Timers::second_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second));
192         point_one_second_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds));
193         point_zero_something_second_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_something_seconds));
194         set_fps_timeout_connection();
195
196         update_format ();
197
198         if (meter_box.get_parent()) {
199                 transport_hbox.remove (meter_box);
200                 transport_hbox.remove (editor_meter_peak_display);
201         }
202
203         if (editor_meter) {
204                 meter_box.remove(*editor_meter);
205                 delete editor_meter;
206                 editor_meter = 0;
207                 editor_meter_peak_display.hide();
208         }
209
210         if (meter_box.get_parent()) {
211                 transport_hbox.remove (meter_box);
212                 transport_hbox.remove (editor_meter_peak_display);
213         }
214
215         if (_session &&
216             _session->master_out() &&
217             _session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
218
219                 if (!ARDOUR::Profile->get_trx()) {
220                         editor_meter = new LevelMeterHBox(_session);
221                         editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
222                         editor_meter->clear_meters();
223                         editor_meter->set_type (_session->master_out()->meter_type());
224                         editor_meter->setup_meters (30, 10, 6);
225                         editor_meter->show();
226                         meter_box.pack_start(*editor_meter);
227                 }
228
229                 ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
230                 ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
231                 ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
232
233                 editor_meter_peak_display.set_name ("meterbridge peakindicator");
234                 editor_meter_peak_display.unset_flags (Gtk::CAN_FOCUS);
235                 editor_meter_peak_display.set_size_request (std::max(9.f, rintf(8.f * UIConfiguration::instance().get_ui_scale())), -1);
236                 editor_meter_peak_display.set_corner_radius (3.0);
237
238                 editor_meter_max_peak = -INFINITY;
239                 editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
240
241                 if (UIConfiguration::instance().get_show_editor_meter() && !ARDOUR::Profile->get_trx()) {
242                         transport_hbox.pack_start (meter_box, false, false);
243                         transport_hbox.pack_start (editor_meter_peak_display, false, false);
244                         meter_box.show();
245                         editor_meter_peak_display.show();
246                 }
247         }
248
249         update_title ();
250 }
251
252 int
253 ARDOUR_UI::unload_session (bool hide_stuff)
254 {
255         if (_session) {
256                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
257         }
258
259         if (_session && _session->dirty()) {
260                 std::vector<std::string> actions;
261                 actions.push_back (_("Don't close"));
262                 actions.push_back (_("Just close"));
263                 actions.push_back (_("Save and close"));
264                 switch (ask_about_saving_session (actions)) {
265                 case -1:
266                         // cancel
267                         return 1;
268
269                 case 1:
270                         _session->save_state ("");
271                         break;
272                 }
273         }
274
275         {
276                 // tear down session specific CPI (owned by rc_config_editor which can remain)
277                 ControlProtocolManager& m = ControlProtocolManager::instance ();
278                 for (std::list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
279                         if (*i && (*i)->protocol && (*i)->protocol->has_editor ()) {
280                                 (*i)->protocol->tear_down_gui ();
281                         }
282                 }
283         }
284
285         if (hide_stuff) {
286                 editor->hide ();
287                 mixer->hide ();
288                 meterbridge->hide ();
289                 audio_port_matrix->hide();
290                 midi_port_matrix->hide();
291                 route_params->hide();
292         }
293
294         second_connection.disconnect ();
295         point_one_second_connection.disconnect ();
296         point_zero_something_second_connection.disconnect();
297         fps_connection.disconnect();
298
299         if (editor_meter) {
300                 meter_box.remove(*editor_meter);
301                 delete editor_meter;
302                 editor_meter = 0;
303                 editor_meter_peak_display.hide();
304         }
305
306         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
307
308         rec_button.set_sensitive (false);
309
310         WM::Manager::instance().set_session ((ARDOUR::Session*) 0);
311
312         if (ARDOUR_UI::instance()->video_timeline) {
313                 ARDOUR_UI::instance()->video_timeline->close_session();
314         }
315
316         stop_clocking ();
317
318         /* drop everything attached to the blink signal */
319
320         blink_connection.disconnect ();
321
322         delete _session;
323         _session = 0;
324
325         session_loaded = false;
326
327         update_buffer_load ();
328         update_title ();
329
330         return 0;
331 }
332
333 void
334 ARDOUR_UI::toggle_editor_and_mixer ()
335 {
336         if (editor->tabbed() && mixer->tabbed()) {
337                 /* both in the same window */
338                 if (_tabs.get_current_page() == _tabs.page_num (editor->contents())) {
339                         _tabs.set_current_page (_tabs.page_num (mixer->contents()));
340                 } else if (_tabs.get_current_page() == _tabs.page_num (mixer->contents())) {
341                         _tabs.set_current_page (_tabs.page_num (editor->contents()));
342                 } else {
343                         /* go to mixer */
344                         _tabs.set_current_page (_tabs.page_num (mixer->contents()));
345                 }
346                 return;
347         }
348
349
350         if (editor->tabbed() && !mixer->tabbed()) {
351                 /* editor is tabbed, mixer is not */
352
353                 Gtk::Window* mwin = mixer->current_toplevel ();
354
355                 if (!mwin) {
356                         /* mixer's own window doesn't exist */
357                         mixer->make_visible ();
358                 } else if (!mwin->is_mapped ()) {
359                         /* mixer's own window exists but isn't mapped */
360                         mixer->make_visible ();
361                 } else {
362                         /* mixer window is mapped, editor is visible as tab */
363                         Gtk::Widget* f = mwin->get_focus();
364                         if (f && f->has_focus()) {
365                                 /* mixer has focus, switch to editor */
366                                 editor->make_visible ();
367                         } else {
368                                 mixer->make_visible ();
369                         }
370                 }
371                 return;
372         }
373
374         if (!editor->tabbed() && mixer->tabbed()) {
375                 /* mixer is tabbed, editor is not */
376
377                 Gtk::Window* ewin = editor->current_toplevel ();
378
379                 if (!ewin) {
380                         /* mixer's own window doesn't exist */
381                         editor->make_visible ();
382                 } else if (!ewin->is_mapped ()) {
383                         /* editor's own window exists but isn't mapped */
384                         editor->make_visible ();
385                 } else {
386                         /* editor window is mapped, mixer is visible as tab */
387                         Gtk::Widget* f = ewin->get_focus();
388                         if (f && f->has_focus()) {
389                                 /* editor has focus, switch to mixer */
390                                 mixer->make_visible ();
391                         } else {
392                                 editor->make_visible ();
393                         }
394                 }
395                 return;
396         }
397 }
398
399 void
400 ARDOUR_UI::step_up_through_tabs ()
401 {
402         std::vector<Tabbable*> candidates;
403
404         /* this list must match the order of visibility buttons */
405
406         if (!editor->window_visible()) {
407                 candidates.push_back (editor);
408         }
409
410         if (!mixer->window_visible()) {
411                 candidates.push_back (mixer);
412         }
413
414         if (!rc_option_editor->window_visible()) {
415                 candidates.push_back (rc_option_editor);
416         }
417
418         if (candidates.size() < 2) {
419                 /* nothing to be done with zero or one visible in tabs */
420                 return;
421         }
422
423         std::vector<Tabbable*>::iterator prev = candidates.end();
424         std::vector<Tabbable*>::iterator i;
425         Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
426
427         for (i = candidates.begin(); i != candidates.end(); ++i) {
428                 if (w == &(*i)->contents()) {
429                         if (prev != candidates.end()) {
430                                 _tabs.set_current_page (_tabs.page_num ((*prev)->contents()));
431                         } else {
432                                 _tabs.set_current_page (_tabs.page_num (candidates.back()->contents()));
433                         }
434                         return;
435                 }
436                 prev = i;
437         }
438 }
439
440 void
441 ARDOUR_UI::step_down_through_tabs ()
442 {
443         std::vector<Tabbable*> candidates;
444
445         /* this list must match the order of visibility buttons */
446
447         if (!editor->window_visible()) {
448                 candidates.push_back (editor);
449         }
450
451         if (!mixer->window_visible()) {
452                 candidates.push_back (mixer);
453         }
454
455         if (!rc_option_editor->window_visible()) {
456                 candidates.push_back (rc_option_editor);
457         }
458
459         if (candidates.size() < 2) {
460                 /* nothing to be done with zero or one visible in tabs */
461                 return;
462         }
463
464         std::vector<Tabbable*>::reverse_iterator next = candidates.rend();
465         std::vector<Tabbable*>::reverse_iterator i;
466         Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
467
468         for (i = candidates.rbegin(); i != candidates.rend(); ++i) {
469                 if (w == &(*i)->contents()) {
470                         if (next != candidates.rend()) {
471                                 _tabs.set_current_page (_tabs.page_num ((*next)->contents()));
472                         } else {
473                                 _tabs.set_current_page (_tabs.page_num (candidates.front()->contents()));
474                         }
475                         break;
476                 }
477                 next = i;
478         }
479 }
480
481 void
482 ARDOUR_UI::key_change_tabbable_visibility (Tabbable* t)
483 {
484         if (!t) {
485                 return;
486         }
487
488         if (t->tabbed()) {
489                 _tabs.set_current_page (_tabs.page_num (t->contents()));
490         } else if (!t->fully_visible()) {
491                 t->make_visible ();
492         } else {
493                 _main_window.present ();
494         }
495 }
496
497 void
498 ARDOUR_UI::button_change_tabbable_visibility (Tabbable* t)
499 {
500         /* For many/most users, clicking a button in the main window will make it
501            the main/front/key window, which will change any stacking relationship they
502            were trying to modify by clicking on the button in the first
503            place. This button-aware method knows that click on
504            a button designed to show/hide a Tabbable that has its own window
505            will have made that window be obscured (as the main window comes to
506            the front). We therefore *hide* the Tabbable's window if it is even
507            partially visible, believing that this is likely because the
508            Tabbable window used to be front, the user clicked to change that,
509            and before we even get here, the main window has become front.
510         */
511
512         if (!t) {
513                 return;
514         }
515
516         if (t->tabbed()) {
517                 _tabs.set_current_page (_tabs.page_num (t->contents()));
518         } else if (t->visible()) {
519                 t->hide();
520         } else {
521                 t->make_visible ();
522         }
523 }
524
525 void
526 ARDOUR_UI::show_tabbable (Tabbable* t)
527 {
528         if (!t) {
529                 return;
530         }
531
532         t->make_visible ();
533 }
534
535 void
536 ARDOUR_UI::hide_tabbable (Tabbable* t)
537 {
538         if (!t) {
539                 return;
540         }
541         t->make_invisible ();
542 }
543
544 void
545 ARDOUR_UI::attach_tabbable (Tabbable* t)
546 {
547         if (!t) {
548                 return;
549         }
550
551         t->attach ();
552 }
553
554 void
555 ARDOUR_UI::detach_tabbable (Tabbable* t)
556 {
557         if (!t) {
558                 return;
559         }
560         t->detach ();
561 }
562
563 void
564 ARDOUR_UI::tabs_page_added (Widget*,guint)
565 {
566         if (_tabs.get_n_pages() > 1) {
567
568                 std::vector<TargetEntry> drag_target_entries;
569                 drag_target_entries.push_back (TargetEntry ("tabbable"));
570
571                 editor_visibility_button.drag_source_set (drag_target_entries);
572                 mixer_visibility_button.drag_source_set (drag_target_entries);
573                 prefs_visibility_button.drag_source_set (drag_target_entries);
574
575                 editor_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (editor->name(),
576                                                                                               Pango::FontDescription ("Sans 24"),
577                                                                                               0, 0,
578                                                                                               Gdk::Color ("red")));
579                 mixer_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (mixer->name(),
580                                                                                              Pango::FontDescription ("Sans 24"),
581                                                                                              0, 0,
582                                                                                              Gdk::Color ("red")));
583                 prefs_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (rc_option_editor->name(),
584                                                                                              Pango::FontDescription ("Sans 24"),
585                                                                                              0, 0,
586                                                                                              Gdk::Color ("red")));
587         }
588 }
589
590 void
591 ARDOUR_UI::tabs_page_removed (Widget*, guint)
592 {
593         if (_tabs.get_n_pages() < 2) {
594                 editor_visibility_button.drag_source_unset ();
595                 mixer_visibility_button.drag_source_unset ();
596                 prefs_visibility_button.drag_source_unset ();
597         }
598 }
599
600 void
601 ARDOUR_UI::tabs_switch (GtkNotebookPage*, guint page)
602 {
603         if (editor && (page == (guint) _tabs.page_num (editor->contents()))) {
604                 editor_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
605
606                 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
607                         mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
608                 }
609
610                 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
611                         prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
612                 }
613         } else if (mixer && (page == (guint) _tabs.page_num (mixer->contents()))) {
614
615                 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
616                         editor_visibility_button.set_active_state (Gtkmm2ext::Off);
617                 }
618
619                 mixer_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
620
621                 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
622                         prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
623                 }
624
625         } else if (page == (guint) _tabs.page_num (rc_option_editor->contents())) {
626
627                 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
628                         editor_visibility_button.set_active_state (Gtkmm2ext::Off);
629                 }
630
631                 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
632                         mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
633                 }
634
635                 prefs_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
636         }
637
638 }
639
640 void
641 ARDOUR_UI::tabbable_state_change (Tabbable& t)
642 {
643         std::vector<std::string> insensitive_action_names;
644         std::vector<std::string> sensitive_action_names;
645         std::vector<std::string> active_action_names;
646         std::vector<std::string> inactive_action_names;
647         Glib::RefPtr<Action> action;
648         std::string downcased_name = downcase (t.name());
649         enum ViewState {
650                 Tabbed,
651                 Windowed,
652                 Hidden
653         };
654         ViewState vs;
655
656         if (t.tabbed()) {
657
658                 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
659                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
660                 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
661                 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
662
663                 vs = Tabbed;
664
665         } else if (t.tabbed_by_default ()) {
666
667                 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
668                 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
669                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
670                 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
671
672                 vs = Hidden;
673
674         } else if (t.window_visible()) {
675
676                 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
677                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
678                 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
679                 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
680
681                 active_action_names.push_back (string_compose ("show-%1", downcased_name));
682                 inactive_action_names.push_back (string_compose ("hide-%1", downcased_name));
683
684                 vs = Windowed;
685
686         } else {
687
688                 /* not currently visible. allow user to retab it or just make
689                  * it visible.
690                  */
691
692                 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
693                 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
694                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
695                 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
696
697                 active_action_names.push_back (string_compose ("hide-%1", downcased_name));
698                 inactive_action_names.push_back (string_compose ("show-%1", downcased_name));
699
700                 vs = Hidden;
701         }
702
703         for (std::vector<std::string>::iterator s = insensitive_action_names.begin(); s != insensitive_action_names.end(); ++s) {
704                 action = ActionManager::get_action (X_("Common"), (*s).c_str());
705                 if (action) {
706                         action->set_sensitive (false);
707                 }
708         }
709
710         for (std::vector<std::string>::iterator s = sensitive_action_names.begin(); s != sensitive_action_names.end(); ++s) {
711                 action = ActionManager::get_action (X_("Common"), (*s).c_str());
712                 if (action) {
713                         action->set_sensitive (true);
714                 }
715         }
716
717         ArdourButton* vis_button = 0;
718         std::vector<ArdourButton*> other_vis_buttons;
719
720         if (&t == editor) {
721                 vis_button = &editor_visibility_button;
722                 other_vis_buttons.push_back (&mixer_visibility_button);
723                 other_vis_buttons.push_back (&prefs_visibility_button);
724         } else if (&t == mixer) {
725                 vis_button = &mixer_visibility_button;
726                 other_vis_buttons.push_back (&editor_visibility_button);
727                 other_vis_buttons.push_back (&prefs_visibility_button);
728         } else if (&t == rc_option_editor) {
729                 vis_button = &prefs_visibility_button;
730                 other_vis_buttons.push_back (&editor_visibility_button);
731                 other_vis_buttons.push_back (&mixer_visibility_button);
732         }
733
734         if (!vis_button) {
735                 return;
736         }
737
738         switch (vs) {
739         case Tabbed:
740                 vis_button->set_active_state (Gtkmm2ext::ImplicitActive);
741                 break;
742         case Windowed:
743                 vis_button->set_active_state (Gtkmm2ext::ExplicitActive);
744                 break;
745         case Hidden:
746                 vis_button->set_active_state (Gtkmm2ext::Off);
747                 break;
748         }
749
750         for (std::vector<ArdourButton*>::iterator b = other_vis_buttons.begin(); b != other_vis_buttons.end(); ++b) {
751                 (*b)->set_active_state (Gtkmm2ext::Off);
752         }
753 }
754
755 void
756 ARDOUR_UI::toggle_meterbridge ()
757 {
758         assert (editor && mixer && meterbridge);
759
760         bool show = false;
761         bool obscuring = false;
762
763         if (meterbridge->not_visible ()) {
764                 show = true;
765         } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) ||
766                    (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) {
767                 obscuring = true;
768         }
769
770         if (obscuring && ((editor->own_window() && editor->own_window()->property_has_toplevel_focus()) ||
771                           (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
772                 show = true;
773         }
774
775         if (show) {
776                 meterbridge->show_window ();
777                 meterbridge->present ();
778                 meterbridge->raise ();
779         } else {
780                 meterbridge->hide_window (NULL);
781         }
782 }
783
784 void
785 ARDOUR_UI::toggle_luawindow ()
786 {
787         assert (editor && luawindow);
788
789         bool show = false;
790
791         if (luawindow->not_visible ()) {
792                 show = true;
793         }
794         // TODO check overlap
795
796         if (show) {
797                 luawindow->show_window ();
798                 luawindow->present ();
799                 luawindow->raise ();
800         } else {
801                 luawindow->hide_window (NULL);
802         }
803 }
804
805
806 void
807 ARDOUR_UI::new_midi_tracer_window ()
808 {
809         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
810         if (!act) {
811                 return;
812         }
813
814         std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
815         while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
816                 ++i;
817         }
818
819         if (i == _midi_tracer_windows.end()) {
820                 /* all our MIDITracer windows are visible; make a new one */
821                 MidiTracer* t = new MidiTracer ();
822                 t->show_all ();
823                 _midi_tracer_windows.push_back (t);
824         } else {
825                 /* re-use the hidden one */
826                 (*i)->show_all ();
827         }
828 }
829
830 KeyEditor*
831 ARDOUR_UI::create_key_editor ()
832 {
833         KeyEditor* kedit = new KeyEditor;
834
835         for (std::list<Bindings*>::iterator b = Bindings::bindings.begin(); b != Bindings::bindings.end(); ++b) {
836                 kedit->add_tab ((*b)->name(), **b);
837         }
838
839         return kedit;
840 }
841
842 BundleManager*
843 ARDOUR_UI::create_bundle_manager ()
844 {
845         return new BundleManager (_session);
846 }
847
848 AddVideoDialog*
849 ARDOUR_UI::create_add_video_dialog ()
850 {
851         return new AddVideoDialog (_session);
852 }
853
854 SessionOptionEditor*
855 ARDOUR_UI::create_session_option_editor ()
856 {
857         return new SessionOptionEditor (_session);
858 }
859
860 BigClockWindow*
861 ARDOUR_UI::create_big_clock_window ()
862 {
863         return new BigClockWindow (*big_clock);
864 }
865
866 void
867 ARDOUR_UI::handle_locations_change (Location *)
868 {
869         if (_session) {
870                 if (_session->locations()->num_range_markers()) {
871                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
872                 } else {
873                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
874                 }
875         }
876 }
877
878 bool
879 ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object)
880 {
881         if (object == editor) {
882
883                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
884                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
885                         if (big_clock_window) {
886                                 big_clock_window->set_transient_for (*editor->own_window());
887                         }
888                 }
889
890         } else if (object == mixer) {
891
892                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
893                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
894                         if (big_clock_window) {
895                                 big_clock_window->set_transient_for (*mixer->own_window());
896                         }
897                 }
898         }
899
900         return false;
901 }
902
903 bool
904 ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
905 {
906         if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier|Gtkmm2ext::Keyboard::TertiaryModifier)) {
907                 ArdourMeter::ResetAllPeakDisplays ();
908         } else if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
909                 if (_session->master_out()) {
910                         ArdourMeter::ResetGroupPeakDisplays (_session->master_out()->route_group());
911                 }
912         } else if (_session->master_out()) {
913                 ArdourMeter::ResetRoutePeakDisplays (_session->master_out().get());
914         }
915         return false;
916 }
917
918 void
919 ARDOUR_UI::toggle_mixer_space()
920 {
921         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMaximalMixer");
922
923         if (act) {
924                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
925                 if (tact->get_active()) {
926                         mixer->maximise_mixer_space ();
927                 } else {
928                         mixer->restore_mixer_space ();
929                 }
930         }
931 }
932
933 void
934 ARDOUR_UI::toggle_mixer_list()
935 {
936         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMixerList");
937
938         if (act) {
939                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
940                         mixer->show_mixer_list (tact->get_active());
941         }
942 }
943
944 void
945 ARDOUR_UI::toggle_monitor_section_visibility ()
946 {
947         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
948
949         if (act) {
950                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
951                         mixer->show_monitor_section (tact->get_active());
952         }
953 }