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