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