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