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)
335 if (splash && splash->is_visible()) {
336 // in 2 seconds, hide the splash screen
337 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000);
344 ARDOUR_UI::hide_tabbable (Tabbable* t)
346 t->make_invisible ();
350 ARDOUR_UI::attach_tabbable (Tabbable* t)
352 if (splash && splash->is_visible()) {
353 // in 2 seconds, hide the splash screen
354 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000);
361 ARDOUR_UI::detach_tabbable (Tabbable* t)
367 ARDOUR_UI::toggle_meterbridge ()
369 assert (editor && mixer && meterbridge);
372 bool obscuring = false;
374 if (meterbridge->not_visible ()) {
376 } else if ((editor->window_visible() && ARDOUR_UI_UTILS::windows_overlap (editor->own_window(), meterbridge)) ||
377 (mixer->window_visible () && ARDOUR_UI_UTILS::windows_overlap (mixer->own_window(), meterbridge))) {
381 if (obscuring && (editor->own_window()->property_has_toplevel_focus() || (mixer->own_window() && mixer->own_window()->property_has_toplevel_focus()))) {
386 meterbridge->show_window ();
387 meterbridge->present ();
388 meterbridge->raise ();
390 meterbridge->hide_window (NULL);
395 ARDOUR_UI::new_midi_tracer_window ()
397 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
402 std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
403 while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
407 if (i == _midi_tracer_windows.end()) {
408 /* all our MIDITracer windows are visible; make a new one */
409 MidiTracer* t = new MidiTracer ();
411 _midi_tracer_windows.push_back (t);
413 /* re-use the hidden one */
419 ARDOUR_UI::create_bundle_manager ()
421 return new BundleManager (_session);
425 ARDOUR_UI::create_add_video_dialog ()
427 return new AddVideoDialog (_session);
431 ARDOUR_UI::create_session_option_editor ()
433 return new SessionOptionEditor (_session);
437 ARDOUR_UI::create_big_clock_window ()
439 return new BigClockWindow (*big_clock);
443 ARDOUR_UI::handle_locations_change (Location *)
446 if (_session->locations()->num_range_markers()) {
447 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
449 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
455 ARDOUR_UI::tabbed_window_state_event_handler (GdkEventWindowState* ev, void* object)
457 if (object == editor) {
459 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
460 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
461 if (big_clock_window) {
462 big_clock_window->set_transient_for (*editor->own_window());
466 } else if (object == mixer) {
468 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
469 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
470 if (big_clock_window) {
471 big_clock_window->set_transient_for (*mixer->own_window());
480 ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
482 if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier|Gtkmm2ext::Keyboard::TertiaryModifier)) {
483 ArdourMeter::ResetAllPeakDisplays ();
484 } else if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
485 if (_session->master_out()) {
486 ArdourMeter::ResetGroupPeakDisplays (_session->master_out()->route_group());
488 } else if (_session->master_out()) {
489 ArdourMeter::ResetRoutePeakDisplays (_session->master_out().get());
495 ARDOUR_UI::toggle_mixer_space()
497 Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMaximalMixer");
500 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
501 if (tact->get_active()) {
502 mixer->maximise_mixer_space ();
504 mixer->restore_mixer_space ();
510 ARDOUR_UI::toggle_mixer_list()
512 Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMixerList");
515 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
516 mixer->show_mixer_list (tact->get_active());
521 ARDOUR_UI::toggle_monitor_section_visibility ()
523 Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMonitorSection");
526 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
527 mixer->show_monitor_section (tact->get_active());