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