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