2 Copyright (C) 2000 Paul Davis
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.
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.
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.
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.
26 #include "ardour/audioengine.h"
27 #include "ardour/automation_watch.h"
28 #include "ardour/control_protocol_manager.h"
29 #include "ardour/profile.h"
30 #include "ardour/session.h"
31 #include "control_protocol/control_protocol.h"
34 #include "add_route_dialog.h"
35 #include "add_video_dialog.h"
36 #include "ardour_ui.h"
37 #include "big_clock_window.h"
38 #include "bundle_manager.h"
39 #include "global_port_matrix.h"
40 #include "gui_object.h"
41 #include "gui_thread.h"
42 #include "keyeditor.h"
43 #include "location_ui.h"
44 #include "main_clock.h"
45 #include "meterbridge.h"
46 #include "meter_patterns.h"
47 #include "midi_tracer.h"
49 #include "public_editor.h"
50 #include "rc_option_editor.h"
51 #include "route_params_ui.h"
52 #include "shuttle_control.h"
53 #include "session_option_editor.h"
54 #include "speaker_dialog.h"
57 #include "theme_manager.h"
58 #include "time_info_box.h"
61 #include <gtkmm2ext/keyboard.h>
65 using namespace ARDOUR;
69 using namespace Gtkmm2ext;
72 ARDOUR_UI::set_session (Session *s)
74 SessionHandlePtr::set_session (s);
77 WM::Manager::instance().set_session (s);
78 /* Session option editor cannot exist across change-of-session */
79 session_option_editor.drop_window ();
80 /* Ditto for AddVideoDialog */
81 add_video_dialog.drop_window ();
85 const XMLNode* node = _session->extra_xml (X_("UI"));
88 const XMLNodeList& children = node->children();
89 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
90 if ((*i)->name() == GUIObjectState::xml_node_name) {
91 gui_object_state->load (**i);
97 WM::Manager::instance().set_session (s);
99 AutomationWatch::instance().set_session (s);
102 shuttle_box->set_session (s);
105 primary_clock->set_session (s);
106 secondary_clock->set_session (s);
107 big_clock->set_session (s);
108 time_info_box->set_session (s);
109 video_timeline->set_session (s);
111 /* sensitize menu bar options that are now valid */
113 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
114 ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
116 if (_session->locations()->num_range_markers()) {
117 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
119 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
122 if (!_session->monitor_out()) {
123 Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
125 act->set_sensitive (false);
129 /* allow wastebasket flush again */
131 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
133 act->set_sensitive (true);
136 /* there are never any selections on startup */
138 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
139 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
140 ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
141 ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
142 ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
144 rec_button.set_sensitive (true);
146 solo_alert_button.set_active (_session->soloing());
148 setup_session_options ();
150 blink_connection = Timers::blink_connect (sigc::mem_fun(*this, &ARDOUR_UI::blink_handler));
152 _session->SaveSessionRequested.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::save_session_at_its_request, this, _1), gui_context());
153 _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
154 _session->StepEditStatusChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::step_edit_status_change, this, _1), gui_context());
155 _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
156 _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dirty_changed, this), gui_context());
158 _session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
159 _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
160 _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
161 _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
162 _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
163 _session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
165 /* Clocks are on by default after we are connected to a session, so show that here.
168 connect_dependents_to_session (s);
170 /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
171 restore their modes or are explicitly set, we will cause the "new" mode to be saved
172 back to the session XML ("Extra") state.
175 AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
177 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
181 map_transport_state ();
183 second_connection = Timers::second_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second));
184 point_one_second_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds));
185 point_zero_something_second_connection = Timers::super_rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_something_seconds));
186 set_fps_timeout_connection();
190 if (meter_box.get_parent()) {
191 transport_tearoff_hbox.remove (meter_box);
192 transport_tearoff_hbox.remove (editor_meter_peak_display);
196 meter_box.remove(*editor_meter);
199 editor_meter_peak_display.hide();
202 if (meter_box.get_parent()) {
203 transport_tearoff_hbox.remove (meter_box);
204 transport_tearoff_hbox.remove (editor_meter_peak_display);
208 _session->master_out() &&
209 _session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
211 if (!ARDOUR::Profile->get_trx()) {
212 editor_meter = new LevelMeterHBox(_session);
213 editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
214 editor_meter->clear_meters();
215 editor_meter->set_type (_session->master_out()->meter_type());
216 editor_meter->setup_meters (30, 12, 6);
217 editor_meter->show();
218 meter_box.pack_start(*editor_meter);
221 ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
222 ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
223 ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
225 editor_meter_peak_display.set_name ("meterbridge peakindicator");
226 editor_meter_peak_display.unset_flags (Gtk::CAN_FOCUS);
227 editor_meter_peak_display.set_size_request (std::max(9.f, rintf(8.f * UIConfiguration::instance().get_ui_scale())), -1);
228 editor_meter_peak_display.set_corner_radius (3.0);
230 editor_meter_max_peak = -INFINITY;
231 editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
233 if (UIConfiguration::instance().get_show_editor_meter() && !ARDOUR::Profile->get_trx()) {
234 transport_tearoff_hbox.pack_start (meter_box, false, false);
235 transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
237 editor_meter_peak_display.show();
245 ARDOUR_UI::unload_session (bool hide_stuff)
248 ARDOUR_UI::instance()->video_timeline->sync_session_state();
251 if (_session && _session->dirty()) {
252 std::vector<std::string> actions;
253 actions.push_back (_("Don't close"));
254 actions.push_back (_("Just close"));
255 actions.push_back (_("Save and close"));
256 switch (ask_about_saving_session (actions)) {
262 _session->save_state ("");
268 // tear down session specific CPI (owned by rc_config_editor which can remain)
269 ControlProtocolManager& m = ControlProtocolManager::instance ();
270 for (std::list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
271 if (*i && (*i)->protocol && (*i)->protocol->has_editor ()) {
272 (*i)->protocol->tear_down_gui ();
280 meterbridge->hide ();
281 audio_port_matrix->hide();
282 midi_port_matrix->hide();
283 route_params->hide();
286 second_connection.disconnect ();
287 point_one_second_connection.disconnect ();
288 point_zero_something_second_connection.disconnect();
289 fps_connection.disconnect();
292 meter_box.remove(*editor_meter);
295 editor_meter_peak_display.hide();
298 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
300 rec_button.set_sensitive (false);
302 WM::Manager::instance().set_session ((ARDOUR::Session*) 0);
304 if (ARDOUR_UI::instance()->video_timeline) {
305 ARDOUR_UI::instance()->video_timeline->close_session();
310 /* drop everything attached to the blink signal */
312 blink_connection.disconnect ();
317 session_loaded = false;
319 update_buffer_load ();
326 _hide_splash (gpointer arg)
328 ((ARDOUR_UI*)arg)->hide_splash();
333 ARDOUR_UI::show_tabbable (Tabbable* t)
339 if (splash && splash->is_visible()) {
340 // in 2 seconds, hide the splash screen
341 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000);
348 ARDOUR_UI::hide_tabbable (Tabbable* t)
353 t->make_invisible ();
357 ARDOUR_UI::attach_tabbable (Tabbable* t)
362 if (splash && splash->is_visible()) {
363 // in 2 seconds, hide the splash screen
364 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000);
371 ARDOUR_UI::detach_tabbable (Tabbable* t)
380 ARDOUR_UI::toggle_meterbridge ()
382 assert (editor && mixer && meterbridge);
385 bool obscuring = false;
387 if (meterbridge->not_visible ()) {
389 } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) ||
390 (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) {
394 if (obscuring && (editor->own_window()->property_has_toplevel_focus() || (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
399 meterbridge->show_window ();
400 meterbridge->present ();
401 meterbridge->raise ();
403 meterbridge->hide_window (NULL);
408 ARDOUR_UI::new_midi_tracer_window ()
410 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
415 std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
416 while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
420 if (i == _midi_tracer_windows.end()) {
421 /* all our MIDITracer windows are visible; make a new one */
422 MidiTracer* t = new MidiTracer ();
424 _midi_tracer_windows.push_back (t);
426 /* re-use the hidden one */
432 ARDOUR_UI::create_bundle_manager ()
434 return new BundleManager (_session);
438 ARDOUR_UI::create_add_video_dialog ()
440 return new AddVideoDialog (_session);
444 ARDOUR_UI::create_session_option_editor ()
446 return new SessionOptionEditor (_session);
450 ARDOUR_UI::create_big_clock_window ()
452 return new BigClockWindow (*big_clock);
456 ARDOUR_UI::handle_locations_change (Location *)
459 if (_session->locations()->num_range_markers()) {
460 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
462 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
468 ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object)
470 if (object == editor) {
472 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
473 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
474 if (big_clock_window) {
475 big_clock_window->set_transient_for (*editor->own_window());
479 } else if (object == mixer) {
481 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
482 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
483 if (big_clock_window) {
484 big_clock_window->set_transient_for (*mixer->own_window());
493 ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
495 if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier|Gtkmm2ext::Keyboard::TertiaryModifier)) {
496 ArdourMeter::ResetAllPeakDisplays ();
497 } else if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
498 if (_session->master_out()) {
499 ArdourMeter::ResetGroupPeakDisplays (_session->master_out()->route_group());
501 } else if (_session->master_out()) {
502 ArdourMeter::ResetRoutePeakDisplays (_session->master_out().get());
508 ARDOUR_UI::toggle_mixer_space()
510 Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMaximalMixer");
513 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
514 if (tact->get_active()) {
515 mixer->maximise_mixer_space ();
517 mixer->restore_mixer_space ();
523 ARDOUR_UI::toggle_mixer_list()
525 Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMixerList");
528 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
529 mixer->show_mixer_list (tact->get_active());
534 ARDOUR_UI::toggle_monitor_section_visibility ()
536 Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
539 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
540 mixer->show_monitor_section (tact->get_active());