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);
238 if (editor_meter_table.get_parent()) {
239 transport_hbox.remove (editor_meter_table);
241 if (editor_meter_peak_display.get_parent ()) {
242 editor_meter_table.remove (editor_meter_peak_display);
246 _session->master_out() &&
247 _session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
249 editor_meter = new LevelMeterHBox(_session);
250 editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
251 editor_meter->clear_meters();
252 editor_meter->setup_meters (30, 10, 6);
253 editor_meter->show();
255 editor_meter_table.set_spacings(3);
256 editor_meter_table.attach(*editor_meter, 0,1, 0,1, FILL, EXPAND|FILL, 0, 1);
257 editor_meter_table.attach(editor_meter_peak_display, 0,1, 1,2, FILL, SHRINK, 0, 0);
259 editor_meter->show();
260 editor_meter_peak_display.show();
262 ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
263 ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
264 ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
266 editor_meter_peak_display.set_name ("meterbridge peakindicator");
267 editor_meter_peak_display.unset_flags (Gtk::CAN_FOCUS);
268 editor_meter_peak_display.set_size_request (-1, std::max (5.f, std::min (12.f, rintf (8.f * UIConfiguration::instance().get_ui_scale()))) );
269 editor_meter_peak_display.set_corner_radius (1.0);
271 editor_meter_max_peak = -INFINITY;
272 editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
274 repack_transport_hbox ();
281 ARDOUR_UI::unload_session (bool hide_stuff)
284 ARDOUR_UI::instance()->video_timeline->sync_session_state();
286 /* Unconditionally save session-specific GUI settings:
287 * Playhead position, zoom/scroll with stationary PH,
288 * window and pane positions, etc.
290 * While many GUI operations immediately cause an instant.xml
291 * save, changing the playhead-pos in particular does not,
292 * nor mark the session dirty.
294 save_ardour_state ();
297 if (_session && _session->dirty()) {
298 std::vector<std::string> actions;
299 actions.push_back (_("Don't close"));
300 actions.push_back (_("Just close"));
301 actions.push_back (_("Save and close"));
302 switch (ask_about_saving_session (actions)) {
308 _session->save_state ("");
314 // tear down session specific CPI (owned by rc_config_editor which can remain)
315 ControlProtocolManager& m = ControlProtocolManager::instance ();
316 for (std::list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
317 if (*i && (*i)->protocol && (*i)->protocol->has_editor ()) {
318 (*i)->protocol->tear_down_gui ();
324 close_all_dialogs ();
327 meterbridge->hide ();
328 audio_port_matrix->hide();
329 midi_port_matrix->hide();
330 route_params->hide();
333 second_connection.disconnect ();
334 point_one_second_connection.disconnect ();
335 point_zero_something_second_connection.disconnect();
336 fps_connection.disconnect();
339 editor_meter_table.remove(*editor_meter);
342 editor_meter_peak_display.hide();
345 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
347 WM::Manager::instance().set_session ((ARDOUR::Session*) 0);
349 if (ARDOUR_UI::instance()->video_timeline) {
350 ARDOUR_UI::instance()->video_timeline->close_session();
355 /* drop everything attached to the blink signal */
357 blink_connection.disconnect ();
359 ARDOUR::Session* session_to_delete = _session;
361 delete session_to_delete;
369 ARDOUR_UI::toggle_editor_and_mixer ()
371 if (editor->tabbed() && mixer->tabbed()) {
372 /* both in the same window */
373 if (_tabs.get_current_page() == _tabs.page_num (editor->contents())) {
374 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
375 } else if (_tabs.get_current_page() == _tabs.page_num (mixer->contents())) {
376 _tabs.set_current_page (_tabs.page_num (editor->contents()));
379 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
385 if (editor->tabbed() && !mixer->tabbed()) {
386 /* editor is tabbed, mixer is not */
388 Gtk::Window* mwin = mixer->current_toplevel ();
391 /* mixer's own window doesn't exist */
392 mixer->make_visible ();
393 } else if (!mwin->is_mapped ()) {
394 /* mixer's own window exists but isn't mapped */
395 mixer->make_visible ();
397 /* mixer window is mapped, editor is visible as tab */
398 Gtk::Widget* f = mwin->get_focus();
399 if (f && f->has_focus()) {
400 /* mixer has focus, switch to editor */
401 editor->make_visible ();
403 mixer->make_visible ();
409 if (!editor->tabbed() && mixer->tabbed()) {
410 /* mixer is tabbed, editor is not */
412 Gtk::Window* ewin = editor->current_toplevel ();
415 /* mixer's own window doesn't exist */
416 editor->make_visible ();
417 } else if (!ewin->is_mapped ()) {
418 /* editor's own window exists but isn't mapped */
419 editor->make_visible ();
421 /* editor window is mapped, mixer is visible as tab */
422 Gtk::Widget* f = ewin->get_focus();
423 if (f && f->has_focus()) {
424 /* editor has focus, switch to mixer */
425 mixer->make_visible ();
427 editor->make_visible ();
435 ARDOUR_UI::step_up_through_tabs ()
437 std::vector<Tabbable*> candidates;
439 /* this list must match the order of visibility buttons */
441 if (!editor->window_visible()) {
442 candidates.push_back (editor);
445 if (!mixer->window_visible()) {
446 candidates.push_back (mixer);
449 if (!rc_option_editor->window_visible()) {
450 candidates.push_back (rc_option_editor);
453 if (candidates.size() < 2) {
454 /* nothing to be done with zero or one visible in tabs */
458 std::vector<Tabbable*>::iterator prev = candidates.end();
459 std::vector<Tabbable*>::iterator i;
460 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
462 for (i = candidates.begin(); i != candidates.end(); ++i) {
463 if (w == &(*i)->contents()) {
464 if (prev != candidates.end()) {
465 _tabs.set_current_page (_tabs.page_num ((*prev)->contents()));
467 _tabs.set_current_page (_tabs.page_num (candidates.back()->contents()));
476 ARDOUR_UI::step_down_through_tabs ()
478 std::vector<Tabbable*> candidates;
480 /* this list must match the order of visibility buttons */
482 if (!editor->window_visible()) {
483 candidates.push_back (editor);
486 if (!mixer->window_visible()) {
487 candidates.push_back (mixer);
490 if (!rc_option_editor->window_visible()) {
491 candidates.push_back (rc_option_editor);
494 if (candidates.size() < 2) {
495 /* nothing to be done with zero or one visible in tabs */
499 std::vector<Tabbable*>::reverse_iterator next = candidates.rend();
500 std::vector<Tabbable*>::reverse_iterator i;
501 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page ());
503 for (i = candidates.rbegin(); i != candidates.rend(); ++i) {
504 if (w == &(*i)->contents()) {
505 if (next != candidates.rend()) {
506 _tabs.set_current_page (_tabs.page_num ((*next)->contents()));
508 _tabs.set_current_page (_tabs.page_num (candidates.front()->contents()));
517 ARDOUR_UI::key_change_tabbable_visibility (Tabbable* t)
524 _tabs.set_current_page (_tabs.page_num (t->contents()));
525 } else if (!t->fully_visible()) {
528 _main_window.present ();
533 ARDOUR_UI::button_change_tabbable_visibility (Tabbable* t)
535 /* For many/most users, clicking a button in the main window will make it
536 the main/front/key window, which will change any stacking relationship they
537 were trying to modify by clicking on the button in the first
538 place. This button-aware method knows that click on
539 a button designed to show/hide a Tabbable that has its own window
540 will have made that window be obscured (as the main window comes to
541 the front). We therefore *hide* the Tabbable's window if it is even
542 partially visible, believing that this is likely because the
543 Tabbable window used to be front, the user clicked to change that,
544 and before we even get here, the main window has become front.
552 _tabs.set_current_page (_tabs.page_num (t->contents()));
553 } else if (t->visible()) {
561 ARDOUR_UI::show_tabbable (Tabbable* t)
571 ARDOUR_UI::hide_tabbable (Tabbable* t)
576 t->make_invisible ();
580 ARDOUR_UI::attach_tabbable (Tabbable* t)
590 ARDOUR_UI::detach_tabbable (Tabbable* t)
599 ARDOUR_UI::tabs_page_added (Widget*,guint)
601 if (_tabs.get_n_pages() > 1) {
603 std::vector<TargetEntry> drag_target_entries;
604 drag_target_entries.push_back (TargetEntry ("tabbable"));
606 editor_visibility_button.drag_source_set (drag_target_entries);
607 mixer_visibility_button.drag_source_set (drag_target_entries);
608 prefs_visibility_button.drag_source_set (drag_target_entries);
610 editor_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (editor->name(),
611 Pango::FontDescription ("Sans 24"),
613 Gdk::Color ("red")));
614 mixer_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (mixer->name(),
615 Pango::FontDescription ("Sans 24"),
617 Gdk::Color ("red")));
618 prefs_visibility_button.drag_source_set_icon (Gtkmm2ext::pixbuf_from_string (rc_option_editor->name(),
619 Pango::FontDescription ("Sans 24"),
621 Gdk::Color ("red")));
626 ARDOUR_UI::tabs_page_removed (Widget*, guint)
628 if (_tabs.get_n_pages() < 2) {
629 editor_visibility_button.drag_source_unset ();
630 mixer_visibility_button.drag_source_unset ();
631 prefs_visibility_button.drag_source_unset ();
636 ARDOUR_UI::tabs_switch (GtkNotebookPage*, guint page)
638 if (editor && (page == (guint) _tabs.page_num (editor->contents()))) {
639 editor_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
641 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
642 mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
645 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
646 prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
648 } else if (mixer && (page == (guint) _tabs.page_num (mixer->contents()))) {
650 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
651 editor_visibility_button.set_active_state (Gtkmm2ext::Off);
654 mixer_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
656 if (rc_option_editor && (rc_option_editor->tabbed() || rc_option_editor->tabbed_by_default())) {
657 prefs_visibility_button.set_active_state (Gtkmm2ext::Off);
660 } else if (page == (guint) _tabs.page_num (rc_option_editor->contents())) {
662 if (editor && (editor->tabbed() || editor->tabbed_by_default())) {
663 editor_visibility_button.set_active_state (Gtkmm2ext::Off);
666 if (mixer && (mixer->tabbed() || mixer->tabbed_by_default())) {
667 mixer_visibility_button.set_active_state (Gtkmm2ext::Off);
670 prefs_visibility_button.set_active_state (Gtkmm2ext::ImplicitActive);
676 ARDOUR_UI::tabbable_state_change (Tabbable& t)
678 std::vector<std::string> insensitive_action_names;
679 std::vector<std::string> sensitive_action_names;
680 std::vector<std::string> active_action_names;
681 std::vector<std::string> inactive_action_names;
682 Glib::RefPtr<Action> action;
683 std::string downcased_name = downcase (t.name());
693 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
694 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
695 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
696 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
700 } else if (t.tabbed_by_default ()) {
702 insensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
703 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
704 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
705 sensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
709 } else if (t.window_visible()) {
711 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
712 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
713 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
714 sensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
716 active_action_names.push_back (string_compose ("show-%1", downcased_name));
717 inactive_action_names.push_back (string_compose ("hide-%1", downcased_name));
723 /* not currently visible. allow user to retab it or just make
727 insensitive_action_names.push_back (string_compose ("detach-%1", downcased_name));
728 insensitive_action_names.push_back (string_compose ("hide-%1", downcased_name));
729 sensitive_action_names.push_back (string_compose ("show-%1", downcased_name));
730 sensitive_action_names.push_back (string_compose ("attach-%1", downcased_name));
732 active_action_names.push_back (string_compose ("hide-%1", downcased_name));
733 inactive_action_names.push_back (string_compose ("show-%1", downcased_name));
738 for (std::vector<std::string>::iterator s = insensitive_action_names.begin(); s != insensitive_action_names.end(); ++s) {
739 action = ActionManager::get_action (X_("Common"), (*s).c_str(), false);
741 action->set_sensitive (false);
745 for (std::vector<std::string>::iterator s = sensitive_action_names.begin(); s != sensitive_action_names.end(); ++s) {
746 action = ActionManager::get_action (X_("Common"), (*s).c_str(), false);
748 action->set_sensitive (true);
752 ArdourButton* vis_button = 0;
753 std::vector<ArdourButton*> other_vis_buttons;
756 vis_button = &editor_visibility_button;
757 other_vis_buttons.push_back (&mixer_visibility_button);
758 other_vis_buttons.push_back (&prefs_visibility_button);
759 } else if (&t == mixer) {
760 vis_button = &mixer_visibility_button;
761 other_vis_buttons.push_back (&editor_visibility_button);
762 other_vis_buttons.push_back (&prefs_visibility_button);
763 } else if (&t == rc_option_editor) {
764 vis_button = &prefs_visibility_button;
765 other_vis_buttons.push_back (&editor_visibility_button);
766 other_vis_buttons.push_back (&mixer_visibility_button);
775 vis_button->set_active_state (Gtkmm2ext::ImplicitActive);
778 vis_button->set_active_state (Gtkmm2ext::ExplicitActive);
781 vis_button->set_active_state (Gtkmm2ext::Off);
785 for (std::vector<ArdourButton*>::iterator b = other_vis_buttons.begin(); b != other_vis_buttons.end(); ++b) {
786 (*b)->set_active_state (Gtkmm2ext::Off);
791 ARDOUR_UI::toggle_meterbridge ()
793 assert (editor && mixer && meterbridge);
796 bool obscuring = false;
798 if (meterbridge->not_visible ()) {
800 } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) ||
801 (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) {
805 if (obscuring && ((editor->own_window() && editor->own_window()->property_has_toplevel_focus()) ||
806 (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
811 meterbridge->show_window ();
812 meterbridge->present ();
813 meterbridge->raise ();
815 meterbridge->hide_window (NULL);
820 ARDOUR_UI::toggle_luawindow ()
822 assert (editor && luawindow);
826 if (luawindow->not_visible ()) {
829 // TODO check overlap
832 luawindow->show_window ();
833 luawindow->present ();
836 luawindow->hide_window (NULL);
842 ARDOUR_UI::new_midi_tracer_window ()
844 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
849 std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
850 while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
854 if (i == _midi_tracer_windows.end()) {
855 /* all our MIDITracer windows are visible; make a new one */
856 MidiTracer* t = new MidiTracer ();
858 _midi_tracer_windows.push_back (t);
860 /* re-use the hidden one */
866 ARDOUR_UI::create_key_editor ()
868 KeyEditor* kedit = new KeyEditor;
870 for (std::list<Bindings*>::iterator b = Bindings::bindings.begin(); b != Bindings::bindings.end(); ++b) {
871 kedit->add_tab ((*b)->name(), **b);
878 ARDOUR_UI::create_bundle_manager ()
880 return new BundleManager (_session);
884 ARDOUR_UI::create_add_video_dialog ()
886 return new AddVideoDialog (_session);
890 ARDOUR_UI::create_session_option_editor ()
892 return new SessionOptionEditor (_session);
896 ARDOUR_UI::create_big_clock_window ()
898 return new BigClockWindow (*big_clock);
902 ARDOUR_UI::create_big_transport_window ()
904 BigTransportWindow* btw = new BigTransportWindow ();
905 btw->set_session (_session);
909 VirtualKeyboardWindow*
910 ARDOUR_UI::create_virtual_keyboard_window ()
912 VirtualKeyboardWindow* vkbd = new VirtualKeyboardWindow ();
913 vkbd->set_session (_session);
918 ARDOUR_UI::handle_locations_change (Location *)
921 if (_session->locations()->num_range_markers()) {
922 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
924 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
930 ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object)
932 if (object == editor) {
934 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
935 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
936 if (big_clock_window) {
937 big_clock_window->set_transient_for (*editor->own_window());
939 if (big_transport_window) {
940 big_transport_window->set_transient_for (*editor->own_window());
942 if (virtual_keyboard_window) {
943 virtual_keyboard_window->set_transient_for (*editor->own_window());
947 } else if (object == mixer) {
949 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
950 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
951 if (big_clock_window) {
952 big_clock_window->set_transient_for (*mixer->own_window());
954 if (big_transport_window) {
955 big_transport_window->set_transient_for (*mixer->own_window());
957 if (virtual_keyboard_window) {
958 virtual_keyboard_window->set_transient_for (*mixer->own_window());
967 ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
969 if (ev->button == 1) {
970 ArdourMeter::ResetAllPeakDisplays ();
976 ARDOUR_UI::toggle_mixer_space()
978 Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action ("Common", "ToggleMaximalMixer");
979 if (tact->get_active()) {
980 mixer->maximise_mixer_space ();
982 mixer->restore_mixer_space ();