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