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>
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.
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.
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.
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.
36 #include <gtkmm/treemodelfilter.h>
38 #include "pbd/convert.h"
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"
46 #include "control_protocol/control_protocol.h"
48 #include "gtkmm2ext/keyboard.h"
49 #include "gtkmm2ext/utils.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"
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"
82 #include "time_info_box.h"
84 #include "transport_masters_dialog.h"
85 #include "virtual_keyboard_window.h"
89 using namespace ARDOUR;
93 using namespace Gtkmm2ext;
94 using namespace ArdourWidgets;
97 ARDOUR_UI::set_session (Session *s)
99 SessionHandlePtr::set_session (s);
101 transport_ctrl.set_session (s);
103 if (big_transport_window) {
104 big_transport_window->set_session (s);
107 if (virtual_keyboard_window) {
108 virtual_keyboard_window->set_session (s);
112 WM::Manager::instance().set_session (s);
113 /* Session option editor cannot exist across change-of-session */
114 session_option_editor.drop_window ();
115 /* Ditto for AddVideoDialog */
116 add_video_dialog.drop_window ();
117 /* screensaver + layered button sensitivity */
118 map_transport_state ();
122 const XMLNode* node = _session->extra_xml (X_("UI"));
125 const XMLNodeList& children = node->children();
126 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
127 if ((*i)->name() == GUIObjectState::xml_node_name) {
128 gui_object_state->load (**i);
134 WM::Manager::instance().set_session (s);
136 AutomationWatch::instance().set_session (s);
138 shuttle_box.set_session (s);
139 mini_timeline.set_session (s);
140 time_info_box->set_session (s);
142 primary_clock->set_session (s);
143 secondary_clock->set_session (s);
144 big_clock->set_session (s);
145 video_timeline->set_session (s);
146 lua_script_window->set_session (s);
147 plugin_dsp_load_window->set_session (s);
148 transport_masters_window->set_session (s);
149 rc_option_editor->set_session (s);
151 /* sensitize menu bar options that are now valid */
153 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
154 ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
156 if (_session->locations()->num_range_markers()) {
157 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
159 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
162 /* allow wastebasket flush again */
164 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
166 act->set_sensitive (true);
169 /* there are never any selections on startup */
171 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
172 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
173 ActionManager::set_sensitive (ActionManager::route_selection_sensitive_actions, false);
174 ActionManager::set_sensitive (ActionManager::bus_selection_sensitive_actions, false);
175 ActionManager::set_sensitive (ActionManager::vca_selection_sensitive_actions, false);
176 ActionManager::set_sensitive (ActionManager::stripable_selection_sensitive_actions, false);
177 ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
178 ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
179 ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
181 solo_alert_button.set_active (_session->soloing());
183 setup_session_options ();
185 blink_connection = Timers::blink_connect (sigc::mem_fun(*this, &ARDOUR_UI::blink_handler));
187 _session->SaveSessionRequested.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::save_session_at_its_request, this, _1), gui_context());
188 _session->StateSaved.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_title, this), gui_context());
189 _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
190 _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
191 _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dirty_changed, this), gui_context());
193 _session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
194 _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
195 _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
196 _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
197 _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
198 _session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
200 _session->LatencyUpdated.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_latency_updated, this), gui_context());
201 session_latency_updated ();
203 /* Clocks are on by default after we are connected to a session, so show that here.
206 connect_dependents_to_session (s);
208 /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
209 restore their modes or are explicitly set, we will cause the "new" mode to be saved
210 back to the session XML ("Extra") state.
213 AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
215 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
219 map_transport_state ();
221 second_connection = Timers::second_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second));
222 point_one_second_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds));
223 point_zero_something_second_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_something_seconds));
224 set_fps_timeout_connection();
228 if (editor_meter_table.get_parent()) {
229 transport_hbox.remove (editor_meter_table);
233 editor_meter_table.remove(*editor_meter);
236 editor_meter_peak_display.hide();
239 if (editor_meter_table.get_parent()) {
240 transport_hbox.remove (editor_meter_table);
244 _session->master_out() &&
245 _session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
247 editor_meter = new LevelMeterHBox(_session);
248 editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
249 editor_meter->clear_meters();
250 editor_meter->setup_meters (30, 10, 6);
251 editor_meter->show();
253 editor_meter_table.set_spacings(3);
254 editor_meter_table.attach(*editor_meter, 0,1, 0,1, FILL, EXPAND|FILL, 0, 1);
255 editor_meter_table.attach(editor_meter_peak_display, 0,1, 1,2, FILL, SHRINK, 0, 0);
257 editor_meter->show();
258 editor_meter_peak_display.show();
260 ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
261 ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
262 ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
264 editor_meter_peak_display.set_name ("meterbridge peakindicator");
265 editor_meter_peak_display.unset_flags (Gtk::CAN_FOCUS);
266 editor_meter_peak_display.set_size_request (-1, std::max (5.f, std::min (12.f, rintf (8.f * UIConfiguration::instance().get_ui_scale()))) );
267 editor_meter_peak_display.set_corner_radius (1.0);
269 editor_meter_max_peak = -INFINITY;
270 editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
272 repack_transport_hbox ();
279 ARDOUR_UI::unload_session (bool hide_stuff)
282 ARDOUR_UI::instance()->video_timeline->sync_session_state();
284 /* Unconditionally save session-specific GUI settings:
285 * Playhead position, zoom/scroll with stationary PH,
286 * window and pane positions, etc.
288 * While many GUI operations immediately cause an instant.xml
289 * save, changing the playhead-pos in particular does not,
290 * nor mark the session dirty.
292 save_ardour_state ();
295 if (_session && _session->dirty()) {
296 std::vector<std::string> actions;
297 actions.push_back (_("Don't close"));
298 actions.push_back (_("Just close"));
299 actions.push_back (_("Save and close"));
300 switch (ask_about_saving_session (actions)) {
306 _session->save_state ("");
312 // tear down session specific CPI (owned by rc_config_editor which can remain)
313 ControlProtocolManager& m = ControlProtocolManager::instance ();
314 for (std::list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
315 if (*i && (*i)->protocol && (*i)->protocol->has_editor ()) {
316 (*i)->protocol->tear_down_gui ();
322 close_all_dialogs ();
325 meterbridge->hide ();
326 audio_port_matrix->hide();
327 midi_port_matrix->hide();
328 route_params->hide();
331 second_connection.disconnect ();
332 point_one_second_connection.disconnect ();
333 point_zero_something_second_connection.disconnect();
334 fps_connection.disconnect();
337 editor_meter_table.remove(*editor_meter);
340 editor_meter_peak_display.hide();
343 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
345 WM::Manager::instance().set_session ((ARDOUR::Session*) 0);
347 if (ARDOUR_UI::instance()->video_timeline) {
348 ARDOUR_UI::instance()->video_timeline->close_session();
353 /* drop everything attached to the blink signal */
355 blink_connection.disconnect ();
357 ARDOUR::Session* session_to_delete = _session;
359 delete session_to_delete;
367 ARDOUR_UI::toggle_editor_and_mixer ()
369 if (editor->tabbed() && mixer->tabbed()) {
370 /* both in the same window */
371 if (_tabs.get_current_page() == _tabs.page_num (editor->contents())) {
372 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
373 } else if (_tabs.get_current_page() == _tabs.page_num (mixer->contents())) {
374 _tabs.set_current_page (_tabs.page_num (editor->contents()));
377 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
383 if (editor->tabbed() && !mixer->tabbed()) {
384 /* editor is tabbed, mixer is not */
386 Gtk::Window* mwin = mixer->current_toplevel ();
389 /* mixer's own window doesn't exist */
390 mixer->make_visible ();
391 } else if (!mwin->is_mapped ()) {
392 /* mixer's own window exists but isn't mapped */
393 mixer->make_visible ();
395 /* mixer window is mapped, editor is visible as tab */
396 Gtk::Widget* f = mwin->get_focus();
397 if (f && f->has_focus()) {
398 /* mixer has focus, switch to editor */
399 editor->make_visible ();
401 mixer->make_visible ();
407 if (!editor->tabbed() && mixer->tabbed()) {
408 /* mixer is tabbed, editor is not */
410 Gtk::Window* ewin = editor->current_toplevel ();
413 /* mixer's own window doesn't exist */
414 editor->make_visible ();
415 } else if (!ewin->is_mapped ()) {
416 /* editor's own window exists but isn't mapped */
417 editor->make_visible ();
419 /* editor window is mapped, mixer is visible as tab */
420 Gtk::Widget* f = ewin->get_focus();
421 if (f && f->has_focus()) {
422 /* editor has focus, switch to mixer */
423 mixer->make_visible ();
425 editor->make_visible ();
433 ARDOUR_UI::step_up_through_tabs ()
435 std::vector<Tabbable*> candidates;
437 /* this list must match the order of visibility buttons */
439 if (!editor->window_visible()) {
440 candidates.push_back (editor);
443 if (!mixer->window_visible()) {
444 candidates.push_back (mixer);
447 if (!rc_option_editor->window_visible()) {
448 candidates.push_back (rc_option_editor);
451 if (candidates.size() < 2) {
452 /* nothing to be done with zero or one visible in tabs */
456 std::vector<Tabbable*>::iterator prev = candidates.end();
457 std::vector<Tabbable*>::iterator i;
458 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
460 for (i = candidates.begin(); i != candidates.end(); ++i) {
461 if (w == &(*i)->contents()) {
462 if (prev != candidates.end()) {
463 _tabs.set_current_page (_tabs.page_num ((*prev)->contents()));
465 _tabs.set_current_page (_tabs.page_num (candidates.back()->contents()));
474 ARDOUR_UI::step_down_through_tabs ()
476 std::vector<Tabbable*> candidates;
478 /* this list must match the order of visibility buttons */
480 if (!editor->window_visible()) {
481 candidates.push_back (editor);
484 if (!mixer->window_visible()) {
485 candidates.push_back (mixer);
488 if (!rc_option_editor->window_visible()) {
489 candidates.push_back (rc_option_editor);
492 if (candidates.size() < 2) {
493 /* nothing to be done with zero or one visible in tabs */
497 std::vector<Tabbable*>::reverse_iterator next = candidates.rend();
498 std::vector<Tabbable*>::reverse_iterator i;
499 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
501 for (i = candidates.rbegin(); i != candidates.rend(); ++i) {
502 if (w == &(*i)->contents()) {
503 if (next != candidates.rend()) {
504 _tabs.set_current_page (_tabs.page_num ((*next)->contents()));
506 _tabs.set_current_page (_tabs.page_num (candidates.front()->contents()));
515 ARDOUR_UI::key_change_tabbable_visibility (Tabbable* t)
522 _tabs.set_current_page (_tabs.page_num (t->contents()));
523 } else if (!t->fully_visible()) {
526 _main_window.present ();
531 ARDOUR_UI::button_change_tabbable_visibility (Tabbable* t)
533 /* For many/most users, clicking a button in the main window will make it
534 the main/front/key window, which will change any stacking relationship they
535 were trying to modify by clicking on the button in the first
536 place. This button-aware method knows that click on
537 a button designed to show/hide a Tabbable that has its own window
538 will have made that window be obscured (as the main window comes to
539 the front). We therefore *hide* the Tabbable's window if it is even
540 partially visible, believing that this is likely because the
541 Tabbable window used to be front, the user clicked to change that,
542 and before we even get here, the main window has become front.
550 _tabs.set_current_page (_tabs.page_num (t->contents()));
551 } else if (t->visible()) {
559 ARDOUR_UI::show_tabbable (Tabbable* t)
569 ARDOUR_UI::hide_tabbable (Tabbable* t)
574 t->make_invisible ();
578 ARDOUR_UI::attach_tabbable (Tabbable* t)
588 ARDOUR_UI::detach_tabbable (Tabbable* t)
597 ARDOUR_UI::tabs_page_added (Widget*,guint)
599 if (_tabs.get_n_pages() > 1) {
601 std::vector<TargetEntry> drag_target_entries;
602 drag_target_entries.push_back (TargetEntry ("tabbable"));
604 editor_visibility_button.drag_source_set (drag_target_entries);
605 mixer_visibility_button.drag_source_set (drag_target_entries);
606 prefs_visibility_button.drag_source_set (drag_target_entries);
608 editor_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (editor->name(),
609 Pango::FontDescription ("Sans 24"),
611 Gdk::Color ("red")));
612 mixer_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (mixer->name(),
613 Pango::FontDescription ("Sans 24"),
615 Gdk::Color ("red")));
616 prefs_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (rc_option_editor->name(),
617 Pango::FontDescription ("Sans 24"),
619 Gdk::Color ("red")));
624 ARDOUR_UI::tabs_page_removed (Widget*, guint)
626 if (_tabs.get_n_pages() < 2) {
627 editor_visibility_button.drag_source_unset ();
628 mixer_visibility_button.drag_source_unset ();
629 prefs_visibility_button.drag_source_unset ();
634 ARDOUR_UI::tabs_switch (GtkNotebookPage*, guint page)
636 if (editor && (page == (guint) _tabs.page_num (editor->contents()))) {
637 editor_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
639 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
640 mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
643 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
644 prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
646 } else if (mixer && (page == (guint) _tabs.page_num (mixer->contents()))) {
648 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
649 editor_visibility_button.set_active_state (Gtkmm2ext::Off);
652 mixer_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
654 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
655 prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
658 } else if (page == (guint) _tabs.page_num (rc_option_editor->contents())) {
660 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
661 editor_visibility_button.set_active_state (Gtkmm2ext::Off);
664 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
665 mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
668 prefs_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
674 ARDOUR_UI::tabbable_state_change (Tabbable& t)
676 std::vector<std::string> insensitive_action_names;
677 std::vector<std::string> sensitive_action_names;
678 std::vector<std::string> active_action_names;
679 std::vector<std::string> inactive_action_names;
680 Glib::RefPtr<Action> action;
681 std::string downcased_name = downcase (t.name());
691 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
692 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
693 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
694 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
698 } else if (t.tabbed_by_default ()) {
700 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
701 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
702 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
703 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
707 } else if (t.window_visible()) {
709 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
710 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
711 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
712 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
714 active_action_names.push_back (string_compose ("show-%1", downcased_name));
715 inactive_action_names.push_back (string_compose ("hide-%1", downcased_name));
721 /* not currently visible. allow user to retab it or just make
725 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
726 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
727 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
728 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
730 active_action_names.push_back (string_compose ("hide-%1", downcased_name));
731 inactive_action_names.push_back (string_compose ("show-%1", downcased_name));
736 for (std::vector<std::string>::iterator s = insensitive_action_names.begin(); s != insensitive_action_names.end(); ++s) {
737 action = ActionManager::get_action (X_("Common"), (*s).c_str(), false);
739 action->set_sensitive (false);
743 for (std::vector<std::string>::iterator s = sensitive_action_names.begin(); s != sensitive_action_names.end(); ++s) {
744 action = ActionManager::get_action (X_("Common"), (*s).c_str(), false);
746 action->set_sensitive (true);
750 ArdourButton* vis_button = 0;
751 std::vector<ArdourButton*> other_vis_buttons;
754 vis_button = &editor_visibility_button;
755 other_vis_buttons.push_back (&mixer_visibility_button);
756 other_vis_buttons.push_back (&prefs_visibility_button);
757 } else if (&t == mixer) {
758 vis_button = &mixer_visibility_button;
759 other_vis_buttons.push_back (&editor_visibility_button);
760 other_vis_buttons.push_back (&prefs_visibility_button);
761 } else if (&t == rc_option_editor) {
762 vis_button = &prefs_visibility_button;
763 other_vis_buttons.push_back (&editor_visibility_button);
764 other_vis_buttons.push_back (&mixer_visibility_button);
773 vis_button->set_active_state (Gtkmm2ext::ImplicitActive);
776 vis_button->set_active_state (Gtkmm2ext::ExplicitActive);
779 vis_button->set_active_state (Gtkmm2ext::Off);
783 for (std::vector<ArdourButton*>::iterator b = other_vis_buttons.begin(); b != other_vis_buttons.end(); ++b) {
784 (*b)->set_active_state (Gtkmm2ext::Off);
789 ARDOUR_UI::toggle_meterbridge ()
791 assert (editor && mixer && meterbridge);
794 bool obscuring = false;
796 if (meterbridge->not_visible ()) {
798 } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) ||
799 (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) {
803 if (obscuring && ((editor->own_window() && editor->own_window()->property_has_toplevel_focus()) ||
804 (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
809 meterbridge->show_window ();
810 meterbridge->present ();
811 meterbridge->raise ();
813 meterbridge->hide_window (NULL);
818 ARDOUR_UI::toggle_luawindow ()
820 assert (editor && luawindow);
824 if (luawindow->not_visible ()) {
827 // TODO check overlap
830 luawindow->show_window ();
831 luawindow->present ();
834 luawindow->hide_window (NULL);
840 ARDOUR_UI::new_midi_tracer_window ()
842 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
847 std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
848 while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
852 if (i == _midi_tracer_windows.end()) {
853 /* all our MIDITracer windows are visible; make a new one */
854 MidiTracer* t = new MidiTracer ();
856 _midi_tracer_windows.push_back (t);
858 /* re-use the hidden one */
864 ARDOUR_UI::create_key_editor ()
866 KeyEditor* kedit = new KeyEditor;
868 for (std::list<Bindings*>::iterator b = Bindings::bindings.begin(); b != Bindings::bindings.end(); ++b) {
869 kedit->add_tab ((*b)->name(), **b);
876 ARDOUR_UI::create_bundle_manager ()
878 return new BundleManager (_session);
882 ARDOUR_UI::create_add_video_dialog ()
884 return new AddVideoDialog (_session);
888 ARDOUR_UI::create_session_option_editor ()
890 return new SessionOptionEditor (_session);
894 ARDOUR_UI::create_big_clock_window ()
896 return new BigClockWindow (*big_clock);
900 ARDOUR_UI::create_big_transport_window ()
902 BigTransportWindow* btw = new BigTransportWindow ();
903 btw->set_session (_session);
907 VirtualKeyboardWindow*
908 ARDOUR_UI::create_virtual_keyboard_window ()
910 VirtualKeyboardWindow* vkbd = new VirtualKeyboardWindow ();
911 vkbd->set_session (_session);
916 ARDOUR_UI::handle_locations_change (Location *)
919 if (_session->locations()->num_range_markers()) {
920 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
922 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
928 ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object)
930 if (object == editor) {
932 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
933 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
934 if (big_clock_window) {
935 big_clock_window->set_transient_for (*editor->own_window());
937 if (big_transport_window) {
938 big_transport_window->set_transient_for (*editor->own_window());
940 if (virtual_keyboard_window) {
941 virtual_keyboard_window->set_transient_for (*editor->own_window());
945 } else if (object == mixer) {
947 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
948 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
949 if (big_clock_window) {
950 big_clock_window->set_transient_for (*mixer->own_window());
952 if (big_transport_window) {
953 big_transport_window->set_transient_for (*mixer->own_window());
955 if (virtual_keyboard_window) {
956 virtual_keyboard_window->set_transient_for (*mixer->own_window());
965 ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
967 if (ev->button == 1) {
968 ArdourMeter::ResetAllPeakDisplays ();
974 ARDOUR_UI::toggle_mixer_space()
976 Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action ("Common", "ToggleMaximalMixer");
977 if (tact->get_active()) {
978 mixer->maximise_mixer_space ();
980 mixer->restore_mixer_space ();