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