NO-OP; clean up script spacing and remove goto
[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_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
233                 ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
234                 ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
235                 ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
236
237                 editor_meter_peak_display.set_name ("meterbridge peakindicator");
238                 editor_meter_peak_display.unset_flags (Gtk::CAN_FOCUS);
239                 editor_meter_peak_display.set_size_request (std::max(9.f, rintf(8.f * UIConfiguration::instance().get_ui_scale())), -1);
240                 editor_meter_peak_display.set_corner_radius (3.0);
241
242                 editor_meter_max_peak = -INFINITY;
243                 editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
244
245                 repack_transport_hbox ();
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                 /* both in the same window */
337                 if (_tabs.get_current_page() == _tabs.page_num (editor->contents())) {
338                         _tabs.set_current_page (_tabs.page_num (mixer->contents()));
339                 } else if (_tabs.get_current_page() == _tabs.page_num (mixer->contents())) {
340                         _tabs.set_current_page (_tabs.page_num (editor->contents()));
341                 } else {
342                         /* go to mixer */
343                         _tabs.set_current_page (_tabs.page_num (mixer->contents()));
344                 }
345                 return;
346         }
347
348
349         if (editor->tabbed() && !mixer->tabbed()) {
350                 /* editor is tabbed, mixer is not */
351
352                 Gtk::Window* mwin = mixer->current_toplevel ();
353
354                 if (!mwin) {
355                         /* mixer's own window doesn't exist */
356                         mixer->make_visible ();
357                 } else if (!mwin->is_mapped ()) {
358                         /* mixer's own window exists but isn't mapped */
359                         mixer->make_visible ();
360                 } else {
361                         /* mixer window is mapped, editor is visible as tab */
362                         Gtk::Widget* f = mwin->get_focus();
363                         if (f && f->has_focus()) {
364                                 /* mixer has focus, switch to editor */
365                                 editor->make_visible ();
366                         } else {
367                                 mixer->make_visible ();
368                         }
369                 }
370                 return;
371         }
372
373         if (!editor->tabbed() && mixer->tabbed()) {
374                 /* mixer is tabbed, editor is not */
375
376                 Gtk::Window* ewin = editor->current_toplevel ();
377
378                 if (!ewin) {
379                         /* mixer's own window doesn't exist */
380                         editor->make_visible ();
381                 } else if (!ewin->is_mapped ()) {
382                         /* editor's own window exists but isn't mapped */
383                         editor->make_visible ();
384                 } else {
385                         /* editor window is mapped, mixer is visible as tab */
386                         Gtk::Widget* f = ewin->get_focus();
387                         if (f && f->has_focus()) {
388                                 /* editor has focus, switch to mixer */
389                                 mixer->make_visible ();
390                         } else {
391                                 editor->make_visible ();
392                         }
393                 }
394                 return;
395         }
396 }
397
398 void
399 ARDOUR_UI::step_up_through_tabs ()
400 {
401         std::vector<Tabbable*> candidates;
402
403         /* this list must match the order of visibility buttons */
404
405         if (!editor->window_visible()) {
406                 candidates.push_back (editor);
407         }
408
409         if (!mixer->window_visible()) {
410                 candidates.push_back (mixer);
411         }
412
413         if (!rc_option_editor->window_visible()) {
414                 candidates.push_back (rc_option_editor);
415         }
416
417         if (candidates.size() < 2) {
418                 /* nothing to be done with zero or one visible in tabs */
419                 return;
420         }
421
422         std::vector<Tabbable*>::iterator prev = candidates.end();
423         std::vector<Tabbable*>::iterator i;
424         Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
425
426         for (i = candidates.begin(); i != candidates.end(); ++i) {
427                 if (w == &(*i)->contents()) {
428                         if (prev != candidates.end()) {
429                                 _tabs.set_current_page (_tabs.page_num ((*prev)->contents()));
430                         } else {
431                                 _tabs.set_current_page (_tabs.page_num (candidates.back()->contents()));
432                         }
433                         return;
434                 }
435                 prev = i;
436         }
437 }
438
439 void
440 ARDOUR_UI::step_down_through_tabs ()
441 {
442         std::vector<Tabbable*> candidates;
443
444         /* this list must match the order of visibility buttons */
445
446         if (!editor->window_visible()) {
447                 candidates.push_back (editor);
448         }
449
450         if (!mixer->window_visible()) {
451                 candidates.push_back (mixer);
452         }
453
454         if (!rc_option_editor->window_visible()) {
455                 candidates.push_back (rc_option_editor);
456         }
457
458         if (candidates.size() < 2) {
459                 /* nothing to be done with zero or one visible in tabs */
460                 return;
461         }
462
463         std::vector<Tabbable*>::reverse_iterator next = candidates.rend();
464         std::vector<Tabbable*>::reverse_iterator i;
465         Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
466
467         for (i = candidates.rbegin(); i != candidates.rend(); ++i) {
468                 if (w == &(*i)->contents()) {
469                         if (next != candidates.rend()) {
470                                 _tabs.set_current_page (_tabs.page_num ((*next)->contents()));
471                         } else {
472                                 _tabs.set_current_page (_tabs.page_num (candidates.front()->contents()));
473                         }
474                         break;
475                 }
476                 next = i;
477         }
478 }
479
480 void
481 ARDOUR_UI::key_change_tabbable_visibility (Tabbable* t)
482 {
483         if (!t) {
484                 return;
485         }
486
487         if (t->tabbed()) {
488                 _tabs.set_current_page (_tabs.page_num (t->contents()));
489         } else if (!t->fully_visible()) {
490                 t->make_visible ();
491         } else {
492                 _main_window.present ();
493         }
494 }
495
496 void
497 ARDOUR_UI::button_change_tabbable_visibility (Tabbable* t)
498 {
499         /* For many/most users, clicking a button in the main window will make it
500            the main/front/key window, which will change any stacking relationship they
501            were trying to modify by clicking on the button in the first
502            place. This button-aware method knows that click on
503            a button designed to show/hide a Tabbable that has its own window
504            will have made that window be obscured (as the main window comes to
505            the front). We therefore *hide* the Tabbable's window if it is even
506            partially visible, believing that this is likely because the
507            Tabbable window used to be front, the user clicked to change that,
508            and before we even get here, the main window has become front.
509         */
510
511         if (!t) {
512                 return;
513         }
514
515         if (t->tabbed()) {
516                 _tabs.set_current_page (_tabs.page_num (t->contents()));
517         } else if (t->visible()) {
518                 t->hide();
519         } else {
520                 t->make_visible ();
521         }
522 }
523
524 void
525 ARDOUR_UI::show_tabbable (Tabbable* t)
526 {
527         if (!t) {
528                 return;
529         }
530
531         t->make_visible ();
532 }
533
534 void
535 ARDOUR_UI::hide_tabbable (Tabbable* t)
536 {
537         if (!t) {
538                 return;
539         }
540         t->make_invisible ();
541 }
542
543 void
544 ARDOUR_UI::attach_tabbable (Tabbable* t)
545 {
546         if (!t) {
547                 return;
548         }
549
550         t->attach ();
551 }
552
553 void
554 ARDOUR_UI::detach_tabbable (Tabbable* t)
555 {
556         if (!t) {
557                 return;
558         }
559         t->detach ();
560 }
561
562 void
563 ARDOUR_UI::tabs_page_added (Widget*,guint)
564 {
565         if (_tabs.get_n_pages() > 1) {
566
567                 std::vector<TargetEntry> drag_target_entries;
568                 drag_target_entries.push_back (TargetEntry ("tabbable"));
569
570                 editor_visibility_button.drag_source_set (drag_target_entries);
571                 mixer_visibility_button.drag_source_set (drag_target_entries);
572                 prefs_visibility_button.drag_source_set (drag_target_entries);
573
574                 editor_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (editor->name(),
575                                                                                               Pango::FontDescription ("Sans 24"),
576                                                                                               0, 0,
577                                                                                               Gdk::Color ("red")));
578                 mixer_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (mixer->name(),
579                                                                                              Pango::FontDescription ("Sans 24"),
580                                                                                              0, 0,
581                                                                                              Gdk::Color ("red")));
582                 prefs_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (rc_option_editor->name(),
583                                                                                              Pango::FontDescription ("Sans 24"),
584                                                                                              0, 0,
585                                                                                              Gdk::Color ("red")));
586         }
587 }
588
589 void
590 ARDOUR_UI::tabs_page_removed (Widget*, guint)
591 {
592         if (_tabs.get_n_pages() < 2) {
593                 editor_visibility_button.drag_source_unset ();
594                 mixer_visibility_button.drag_source_unset ();
595                 prefs_visibility_button.drag_source_unset ();
596         }
597 }
598
599 void
600 ARDOUR_UI::tabs_switch (GtkNotebookPage*, guint page)
601 {
602         if (editor && (page == (guint) _tabs.page_num (editor->contents()))) {
603                 editor_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
604
605                 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
606                         mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
607                 }
608
609                 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
610                         prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
611                 }
612         } else if (mixer && (page == (guint) _tabs.page_num (mixer->contents()))) {
613
614                 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
615                         editor_visibility_button.set_active_state (Gtkmm2ext::Off);
616                 }
617
618                 mixer_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
619
620                 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
621                         prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
622                 }
623
624         } else if (page == (guint) _tabs.page_num (rc_option_editor->contents())) {
625
626                 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
627                         editor_visibility_button.set_active_state (Gtkmm2ext::Off);
628                 }
629
630                 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
631                         mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
632                 }
633
634                 prefs_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
635         }
636
637 }
638
639 void
640 ARDOUR_UI::tabbable_state_change (Tabbable& t)
641 {
642         std::vector<std::string> insensitive_action_names;
643         std::vector<std::string> sensitive_action_names;
644         std::vector<std::string> active_action_names;
645         std::vector<std::string> inactive_action_names;
646         Glib::RefPtr<Action> action;
647         std::string downcased_name = downcase (t.name());
648         enum ViewState {
649                 Tabbed,
650                 Windowed,
651                 Hidden
652         };
653         ViewState vs;
654
655         if (t.tabbed()) {
656
657                 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
658                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
659                 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
660                 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
661
662                 vs = Tabbed;
663
664         } else if (t.tabbed_by_default ()) {
665
666                 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
667                 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
668                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
669                 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
670
671                 vs = Hidden;
672
673         } else if (t.window_visible()) {
674
675                 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
676                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
677                 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
678                 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
679
680                 active_action_names.push_back (string_compose ("show-%1", downcased_name));
681                 inactive_action_names.push_back (string_compose ("hide-%1", downcased_name));
682
683                 vs = Windowed;
684
685         } else {
686
687                 /* not currently visible. allow user to retab it or just make
688                  * it visible.
689                  */
690
691                 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
692                 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
693                 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
694                 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
695
696                 active_action_names.push_back (string_compose ("hide-%1", downcased_name));
697                 inactive_action_names.push_back (string_compose ("show-%1", downcased_name));
698
699                 vs = Hidden;
700         }
701
702         for (std::vector<std::string>::iterator s = insensitive_action_names.begin(); s != insensitive_action_names.end(); ++s) {
703                 action = ActionManager::get_action (X_("Common"), (*s).c_str());
704                 if (action) {
705                         action->set_sensitive (false);
706                 }
707         }
708
709         for (std::vector<std::string>::iterator s = sensitive_action_names.begin(); s != sensitive_action_names.end(); ++s) {
710                 action = ActionManager::get_action (X_("Common"), (*s).c_str());
711                 if (action) {
712                         action->set_sensitive (true);
713                 }
714         }
715
716         ArdourButton* vis_button = 0;
717         std::vector<ArdourButton*> other_vis_buttons;
718
719         if (&t == editor) {
720                 vis_button = &editor_visibility_button;
721                 other_vis_buttons.push_back (&mixer_visibility_button);
722                 other_vis_buttons.push_back (&prefs_visibility_button);
723         } else if (&t == mixer) {
724                 vis_button = &mixer_visibility_button;
725                 other_vis_buttons.push_back (&editor_visibility_button);
726                 other_vis_buttons.push_back (&prefs_visibility_button);
727         } else if (&t == rc_option_editor) {
728                 vis_button = &prefs_visibility_button;
729                 other_vis_buttons.push_back (&editor_visibility_button);
730                 other_vis_buttons.push_back (&mixer_visibility_button);
731         }
732
733         if (!vis_button) {
734                 return;
735         }
736
737         switch (vs) {
738         case Tabbed:
739                 vis_button->set_active_state (Gtkmm2ext::ImplicitActive);
740                 break;
741         case Windowed:
742                 vis_button->set_active_state (Gtkmm2ext::ExplicitActive);
743                 break;
744         case Hidden:
745                 vis_button->set_active_state (Gtkmm2ext::Off);
746                 break;
747         }
748
749         for (std::vector<ArdourButton*>::iterator b = other_vis_buttons.begin(); b != other_vis_buttons.end(); ++b) {
750                 (*b)->set_active_state (Gtkmm2ext::Off);
751         }
752 }
753
754 void
755 ARDOUR_UI::toggle_meterbridge ()
756 {
757         assert (editor && mixer && meterbridge);
758
759         bool show = false;
760         bool obscuring = false;
761
762         if (meterbridge->not_visible ()) {
763                 show = true;
764         } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) ||
765                    (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) {
766                 obscuring = true;
767         }
768
769         if (obscuring && ((editor->own_window() && editor->own_window()->property_has_toplevel_focus()) ||
770                           (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
771                 show = true;
772         }
773
774         if (show) {
775                 meterbridge->show_window ();
776                 meterbridge->present ();
777                 meterbridge->raise ();
778         } else {
779                 meterbridge->hide_window (NULL);
780         }
781 }
782
783 void
784 ARDOUR_UI::toggle_luawindow ()
785 {
786         assert (editor && luawindow);
787
788         bool show = false;
789
790         if (luawindow->not_visible ()) {
791                 show = true;
792         }
793         // TODO check overlap
794
795         if (show) {
796                 luawindow->show_window ();
797                 luawindow->present ();
798                 luawindow->raise ();
799         } else {
800                 luawindow->hide_window (NULL);
801         }
802 }
803
804
805 void
806 ARDOUR_UI::new_midi_tracer_window ()
807 {
808         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
809         if (!act) {
810                 return;
811         }
812
813         std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
814         while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
815                 ++i;
816         }
817
818         if (i == _midi_tracer_windows.end()) {
819                 /* all our MIDITracer windows are visible; make a new one */
820                 MidiTracer* t = new MidiTracer ();
821                 t->show_all ();
822                 _midi_tracer_windows.push_back (t);
823         } else {
824                 /* re-use the hidden one */
825                 (*i)->show_all ();
826         }
827 }
828
829 KeyEditor*
830 ARDOUR_UI::create_key_editor ()
831 {
832         KeyEditor* kedit = new KeyEditor;
833
834         for (std::list<Bindings*>::iterator b = Bindings::bindings.begin(); b != Bindings::bindings.end(); ++b) {
835                 kedit->add_tab ((*b)->name(), **b);
836         }
837
838         return kedit;
839 }
840
841 BundleManager*
842 ARDOUR_UI::create_bundle_manager ()
843 {
844         return new BundleManager (_session);
845 }
846
847 AddVideoDialog*
848 ARDOUR_UI::create_add_video_dialog ()
849 {
850         return new AddVideoDialog (_session);
851 }
852
853 SessionOptionEditor*
854 ARDOUR_UI::create_session_option_editor ()
855 {
856         return new SessionOptionEditor (_session);
857 }
858
859 BigClockWindow*
860 ARDOUR_UI::create_big_clock_window ()
861 {
862         return new BigClockWindow (*big_clock);
863 }
864
865 void
866 ARDOUR_UI::handle_locations_change (Location *)
867 {
868         if (_session) {
869                 if (_session->locations()->num_range_markers()) {
870                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
871                 } else {
872                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
873                 }
874         }
875 }
876
877 bool
878 ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object)
879 {
880         if (object == editor) {
881
882                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
883                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
884                         if (big_clock_window) {
885                                 big_clock_window->set_transient_for (*editor->own_window());
886                         }
887                 }
888
889         } else if (object == mixer) {
890
891                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
892                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
893                         if (big_clock_window) {
894                                 big_clock_window->set_transient_for (*mixer->own_window());
895                         }
896                 }
897         }
898
899         return false;
900 }
901
902 bool
903 ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
904 {
905         if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier|Gtkmm2ext::Keyboard::TertiaryModifier)) {
906                 ArdourMeter::ResetAllPeakDisplays ();
907         } else if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
908                 if (_session->master_out()) {
909                         ArdourMeter::ResetGroupPeakDisplays (_session->master_out()->route_group());
910                 }
911         } else if (_session->master_out()) {
912                 ArdourMeter::ResetRoutePeakDisplays (_session->master_out().get());
913         }
914         return false;
915 }
916
917 void
918 ARDOUR_UI::toggle_mixer_space()
919 {
920         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMaximalMixer");
921
922         if (act) {
923                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
924                 if (tact->get_active()) {
925                         mixer->maximise_mixer_space ();
926                 } else {
927                         mixer->restore_mixer_space ();
928                 }
929         }
930 }
931
932 void
933 ARDOUR_UI::toggle_mixer_list()
934 {
935         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMixerList");
936
937         if (act) {
938                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
939                         mixer->show_mixer_list (tact->get_active());
940         }
941 }
942
943 void
944 ARDOUR_UI::toggle_monitor_section_visibility ()
945 {
946         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
947
948         if (act) {
949                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
950                         mixer->show_monitor_section (tact->get_active());
951         }
952 }