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/session.h"
27 #include "ardour/audioengine.h"
28 #include "ardour/automation_watch.h"
31 #include "add_route_dialog.h"
32 #include "add_video_dialog.h"
33 #include "ardour_ui.h"
34 #include "big_clock_window.h"
35 #include "bundle_manager.h"
36 #include "global_port_matrix.h"
37 #include "gui_object.h"
38 #include "gui_thread.h"
39 #include "keyeditor.h"
40 #include "location_ui.h"
41 #include "main_clock.h"
42 #include "midi_tracer.h"
44 #include "public_editor.h"
45 #include "rc_option_editor.h"
46 #include "route_params_ui.h"
47 #include "shuttle_control.h"
48 #include "session_option_editor.h"
49 #include "speaker_dialog.h"
52 #include "theme_manager.h"
53 #include "time_info_box.h"
57 using namespace ARDOUR;
61 using namespace Gtkmm2ext;
64 ARDOUR_UI::set_session (Session *s)
66 SessionHandlePtr::set_session (s);
68 if (audio_port_matrix) {
69 audio_port_matrix->set_session (s);
72 if (midi_port_matrix) {
73 midi_port_matrix->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 AutomationWatch::instance().set_session (s);
98 WindowManager::instance().set_session (s);
101 shuttle_box->set_session (s);
104 primary_clock->set_session (s);
105 secondary_clock->set_session (s);
106 big_clock->set_session (s);
107 time_info_box->set_session (s);
108 video_timeline->set_session (s);
110 /* sensitize menu bar options that are now valid */
112 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
113 ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
115 if (_session->locations()->num_range_markers()) {
116 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
118 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
121 if (!_session->monitor_out()) {
122 Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
124 act->set_sensitive (false);
128 /* allow wastebasket flush again */
130 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
132 act->set_sensitive (true);
135 /* there are never any selections on startup */
137 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
138 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
139 ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
140 ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
141 ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
143 rec_button.set_sensitive (true);
145 solo_alert_button.set_active (_session->soloing());
147 setup_session_options ();
149 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::transport_rec_enable_blink));
150 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::solo_blink));
151 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::sync_blink));
152 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::audition_blink));
153 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::feedback_blink));
155 _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
156 _session->StepEditStatusChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::step_edit_status_change, this, _1), gui_context());
157 _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
158 _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_autosave, this), gui_context());
160 _session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
161 _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
162 _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
163 _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
164 _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
165 _session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
167 #ifdef HAVE_JACK_SESSION
168 engine->JackSessionEvent.connect (*_session, MISSING_INVALIDATOR, boost::bind (&Session::jack_session_event, _session, _1), gui_context());
171 /* Clocks are on by default after we are connected to a session, so show that here.
174 connect_dependents_to_session (s);
176 /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
177 restore their modes or are explicitly set, we will cause the "new" mode to be saved
178 back to the session XML ("Extra") state.
181 AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
183 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
188 map_transport_state ();
190 second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second), 1000);
191 point_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds), 100);
192 point_zero_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_one_seconds), 40);
198 ARDOUR_UI::unload_session (bool hide_stuff)
201 ARDOUR_UI::instance()->video_timeline->sync_session_state();
204 if (_session && _session->dirty()) {
205 std::vector<std::string> actions;
206 actions.push_back (_("Don't close"));
207 actions.push_back (_("Just close"));
208 actions.push_back (_("Save and close"));
209 switch (ask_about_saving_session (actions)) {
215 _session->save_state ("");
223 theme_manager->hide ();
226 second_connection.disconnect ();
227 point_one_second_connection.disconnect ();
228 point_oh_five_second_connection.disconnect ();
229 point_zero_one_second_connection.disconnect();
231 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
233 rec_button.set_sensitive (false);
235 ARDOUR_UI::instance()->video_timeline->close_session();
240 /* drop everything attached to the blink signal */
247 session_loaded = false;
249 update_buffer_load ();
255 _hide_splash (gpointer arg)
257 ((ARDOUR_UI*)arg)->hide_splash();
262 ARDOUR_UI::goto_editor_window ()
264 if (splash && splash->is_visible()) {
265 // in 2 seconds, hide the splash screen
266 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000);
269 editor->show_window ();
275 ARDOUR_UI::goto_mixer_window ()
281 Glib::RefPtr<Gdk::Window> win = editor->get_window ();
282 Glib::RefPtr<Gdk::Screen> screen;
285 screen = win->get_screen();
287 screen = Gdk::Screen::get_default();
290 if (screen && screen->get_height() < 700) {
291 Gtk::MessageDialog msg (_("This screen is not tall enough to display the mixer window"));
296 mixer->show_window ();
303 ARDOUR_UI::toggle_mixer_window ()
305 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-mixer"));
310 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
312 if (tact->get_active()) {
313 goto_mixer_window ();
320 ARDOUR_UI::toggle_editor_mixer ()
322 if (editor && mixer) {
324 if (editor->get_screen() != mixer->get_screen()) {
325 // different screens, so don't do anything
329 /* See if they are obscuring each other */
334 editor->get_position (ex, ey);
335 editor->get_size (ew, eh);
337 mixer->get_position (mx, my);
338 mixer->get_size (mw, mh);
354 if (!gdk_rectangle_intersect (&e, &m, &r)) {
355 /* they do not intersect so do not toggle */
360 if (mixer && mixer->fully_visible()) {
361 goto_editor_window ();
363 goto_mixer_window ();
368 ARDOUR_UI::new_midi_tracer_window ()
370 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
375 std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
376 while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
380 if (i == _midi_tracer_windows.end()) {
381 /* all our MIDITracer windows are visible; make a new one */
382 MidiTracer* t = new MidiTracer ();
384 _midi_tracer_windows.push_back (t);
386 /* re-use the hidden one */
392 ARDOUR_UI::create_bundle_manager ()
394 return new BundleManager (_session);
398 ARDOUR_UI::create_add_video_dialog ()
400 return new AddVideoDialog (_session);
404 ARDOUR_UI::create_session_option_editor ()
406 return new SessionOptionEditor (_session);
410 ARDOUR_UI::create_big_clock_window ()
412 return new BigClockWindow (*big_clock);
416 ARDOUR_UI::handle_locations_change (Location *)
419 if (_session->locations()->num_range_markers()) {
420 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
422 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
428 ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor)
430 if (window_was_editor) {
432 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
433 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
434 if (big_clock_window) {
435 big_clock_window->set_transient_for (*editor);
441 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
442 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
443 if (big_clock_window) {
444 big_clock_window->set_transient_for (*mixer);