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