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