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