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