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