Fix corruption of follow playhead state on quit (#4048).
[ardour2.git] / gtk2_ardour / ardour_ui_dialogs.cc
blob582c635ca7bbb56cab38314c2c05f2d1feb09d6f
1 /*
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"
29 #include "actions.h"
30 #include "add_route_dialog.h"
31 #include "ardour_ui.h"
32 #include "bundle_manager.h"
33 #include "global_port_matrix.h"
34 #include "gui_thread.h"
35 #include "keyeditor.h"
36 #include "location_ui.h"
37 #include "midi_tracer.h"
38 #include "mixer_ui.h"
39 #include "public_editor.h"
40 #include "rc_option_editor.h"
41 #include "route_params_ui.h"
42 #include "shuttle_control.h"
43 #include "session_option_editor.h"
44 #include "speaker_dialog.h"
45 #include "sfdb_ui.h"
46 #include "theme_manager.h"
48 #include "i18n.h"
50 using namespace ARDOUR;
51 using namespace PBD;
52 using namespace Glib;
53 using namespace Gtk;
54 using namespace Gtkmm2ext;
56 void
57 ARDOUR_UI::set_session (Session *s)
59 SessionHandlePtr::set_session (s);
61 if (!_session) {
62 return;
65 if (location_ui->get()) {
66 location_ui->get()->set_session(s);
69 if (speaker_config_window->get()) {
70 speaker_config_window->get()->set_speakers (s->get_speakers());
73 if (route_params) {
74 route_params->set_session (s);
77 if (add_route_dialog) {
78 add_route_dialog->set_session (s);
81 if (session_option_editor) {
82 session_option_editor->set_session (s);
85 if (shuttle_box) {
86 shuttle_box->set_session (s);
89 for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
90 if (_global_port_matrix[*i]->get()) {
91 _global_port_matrix[*i]->get()->set_session (_session);
95 primary_clock.set_session (s);
96 secondary_clock.set_session (s);
97 big_clock.set_session (s);
98 preroll_clock.set_session (s);
99 postroll_clock.set_session (s);
101 /* sensitize menu bar options that are now valid */
103 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
104 ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
106 if (_session->locations()->num_range_markers()) {
107 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
108 } else {
109 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
112 if (!_session->monitor_out()) {
113 Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
114 if (act) {
115 act->set_sensitive (false);
119 /* allow wastebasket flush again */
121 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
122 if (act) {
123 act->set_sensitive (true);
126 /* there are never any selections on startup */
128 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
129 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
130 ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
131 ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
132 ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
134 rec_button.set_sensitive (true);
136 solo_alert_button.set_active (_session->soloing());
138 setup_session_options ();
140 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::transport_rec_enable_blink));
141 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::solo_blink));
142 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::sync_blink));
143 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::audition_blink));
145 _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
146 _session->StepEditStatusChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::step_edit_status_change, this, _1), gui_context());
147 _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
148 _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_autosave, this), gui_context());
150 _session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
151 _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
152 _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
153 _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
154 _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
156 #ifdef HAVE_JACK_SESSION
157 engine->JackSessionEvent.connect (*_session, MISSING_INVALIDATOR, ui_bind (&Session::jack_session_event, _session, _1), gui_context());
158 #endif
160 /* Clocks are on by default after we are connected to a session, so show that here.
163 connect_dependents_to_session (s);
165 /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
166 restore their modes or are explicitly set, we will cause the "new" mode to be saved
167 back to the session XML ("Extra") state.
170 AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
172 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
174 start_clocking ();
175 start_blinking ();
177 map_transport_state ();
179 second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second), 1000);
180 point_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds), 100);
181 point_zero_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_one_seconds), 40);
185 ARDOUR_UI::unload_session (bool hide_stuff)
187 if (_session && _session->dirty()) {
188 switch (ask_about_saving_session (_("close"))) {
189 case -1:
190 // cancel
191 return 1;
193 case 1:
194 _session->save_state ("");
195 break;
199 if (hide_stuff) {
200 editor->hide ();
201 mixer->hide ();
202 theme_manager->hide ();
205 second_connection.disconnect ();
206 point_one_second_connection.disconnect ();
207 point_oh_five_second_connection.disconnect ();
208 point_zero_one_second_connection.disconnect();
210 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
212 rec_button.set_sensitive (false);
214 stop_blinking ();
215 stop_clocking ();
217 /* drop everything attached to the blink signal */
219 Blink.clear ();
221 delete _session;
223 update_buffer_load ();
225 return 0;
228 void
229 ARDOUR_UI::toggle_big_clock_window ()
231 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBigClock"));
232 if (act) {
233 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
235 if (tact->get_active()) {
236 big_clock_window->get()->show_all ();
237 big_clock_window->get()->present ();
238 } else {
239 big_clock_window->get()->hide ();
244 void
245 ARDOUR_UI::toggle_speaker_config_window ()
247 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-speaker-config"));
248 if (act) {
249 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
251 if (tact->get_active()) {
252 speaker_config_window->get()->show_all ();
253 speaker_config_window->get()->present ();
254 } else {
255 speaker_config_window->get()->hide ();
260 void
261 ARDOUR_UI::new_midi_tracer_window ()
263 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
264 if (!act) {
265 return;
268 std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
269 while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
270 ++i;
273 if (i == _midi_tracer_windows.end()) {
274 /* all our MIDITracer windows are visible; make a new one */
275 MidiTracer* t = new MidiTracer ();
276 manage_window (*t);
277 t->show_all ();
278 _midi_tracer_windows.push_back (t);
279 } else {
280 /* re-use the hidden one */
281 (*i)->show_all ();
285 void
286 ARDOUR_UI::toggle_rc_options_window ()
288 if (rc_option_editor == 0) {
289 rc_option_editor = new RCOptionEditor;
290 rc_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleRCOptionsEditor")));
291 rc_option_editor->set_session (_session);
294 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleRCOptionsEditor"));
295 if (act) {
296 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
298 if (tact->get_active()) {
299 rc_option_editor->show_all ();
300 rc_option_editor->present ();
301 } else {
302 rc_option_editor->hide ();
307 void
308 ARDOUR_UI::toggle_session_options_window ()
310 if (session_option_editor == 0) {
311 session_option_editor = new SessionOptionEditor (_session);
312 session_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleSessionOptionsEditor")));
315 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleSessionOptionsEditor"));
316 if (act) {
317 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
319 if (tact->get_active()) {
320 session_option_editor->show_all ();
321 session_option_editor->present ();
322 } else {
323 session_option_editor->hide ();
329 ARDOUR_UI::create_location_ui ()
331 if (location_ui->get() == 0) {
332 location_ui->set (new LocationUIWindow ());
333 location_ui->get()->set_session (_session);
334 location_ui->get()->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleLocations")));
336 return 0;
339 void
340 ARDOUR_UI::toggle_location_window ()
342 if (create_location_ui()) {
343 return;
346 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleLocations"));
347 if (act) {
348 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
350 if (tact->get_active()) {
351 location_ui->get()->show_all ();
352 location_ui->get()->present ();
353 } else {
354 location_ui->get()->hide ();
359 void
360 ARDOUR_UI::toggle_key_editor ()
362 if (key_editor == 0) {
363 key_editor = new KeyEditor;
364 key_editor->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleKeyEditor")));
367 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleKeyEditor"));
368 if (act) {
369 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
371 if (tact->get_active()) {
372 key_editor->show_all ();
373 key_editor->present ();
374 } else {
375 key_editor->hide ();
380 void
381 ARDOUR_UI::toggle_theme_manager ()
383 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleThemeManager"));
384 if (act) {
385 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
387 if (tact->get_active()) {
388 theme_manager->show_all ();
389 theme_manager->present ();
390 } else {
391 theme_manager->hide ();
396 void
397 ARDOUR_UI::create_bundle_manager ()
399 if (bundle_manager == 0) {
400 bundle_manager = new BundleManager (_session);
401 bundle_manager->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBundleManager")));
405 void
406 ARDOUR_UI::toggle_bundle_manager ()
408 create_bundle_manager ();
410 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBundleManager"));
411 if (act) {
412 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
414 if (tact->get_active()) {
415 bundle_manager->show_all ();
416 bundle_manager->present ();
417 } else {
418 bundle_manager->hide ();
424 ARDOUR_UI::create_route_params ()
426 if (route_params == 0) {
427 route_params = new RouteParams_UI ();
428 route_params->set_session (_session);
429 route_params->signal_unmap().connect (sigc::bind(sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleInspector")));
431 return 0;
434 void
435 ARDOUR_UI::toggle_route_params_window ()
437 if (create_route_params ()) {
438 return;
441 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleInspector"));
442 if (act) {
443 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
445 if (tact->get_active()) {
446 route_params->show_all ();
447 route_params->present ();
448 } else {
449 route_params->hide ();
454 void
455 ARDOUR_UI::handle_locations_change (Location *)
457 if (_session) {
458 if (_session->locations()->num_range_markers()) {
459 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
460 } else {
461 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
466 bool
467 ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor)
469 if (window_was_editor) {
471 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
472 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
473 float_big_clock (editor);
476 } else {
478 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
479 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
480 float_big_clock (mixer);
484 return false;