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