vtl: resume if "don't close/exit" is selected
[ardour.git] / gtk2_ardour / ardour_ui_dialogs.cc
1 /*
2     Copyright (C) 2000 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
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.
24 */
25
26 #include "ardour/session.h"
27 #include "ardour/audioengine.h"
28 #include "ardour/automation_watch.h"
29
30 #include "actions.h"
31 #include "add_route_dialog.h"
32 #include "ardour_ui.h"
33 #include "bundle_manager.h"
34 #include "global_port_matrix.h"
35 #include "gui_object.h"
36 #include "gui_thread.h"
37 #include "keyeditor.h"
38 #include "location_ui.h"
39 #include "main_clock.h"
40 #include "midi_tracer.h"
41 #include "mixer_ui.h"
42 #include "public_editor.h"
43 #include "rc_option_editor.h"
44 #include "route_params_ui.h"
45 #include "shuttle_control.h"
46 #include "session_option_editor.h"
47 #include "speaker_dialog.h"
48 #include "sfdb_ui.h"
49 #include "theme_manager.h"
50 #include "time_info_box.h"
51
52 #include "i18n.h"
53
54 using namespace ARDOUR;
55 using namespace PBD;
56 using namespace Glib;
57 using namespace Gtk;
58 using namespace Gtkmm2ext;
59
60 void
61 ARDOUR_UI::set_session (Session *s)
62 {
63         SessionHandlePtr::set_session (s);
64
65         for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
66                 GlobalPortMatrixWindow* w;
67                 if ((w = _global_port_matrix[*i]->get()) != 0) {
68                         w->set_session (s);
69                 }
70         }
71
72         if (!_session) {
73                 return;
74         }
75
76         const XMLNode* node = _session->extra_xml (X_("UI"));
77
78         if (node) {
79                 const XMLNodeList& children = node->children();
80                 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
81                         if ((*i)->name() == GUIObjectState::xml_node_name) {
82                                 gui_object_state->load (**i);
83                                 break;
84                         }
85                 }
86         }
87
88         AutomationWatch::instance().set_session (s);
89
90         if (location_ui->get()) {
91                 location_ui->get()->set_session(s);
92         }
93
94         if (speaker_config_window->get()) {
95                 speaker_config_window->get()->set_speakers (s->get_speakers());
96         }
97
98         if (route_params) {
99                 route_params->set_session (s);
100         }
101
102         if (add_route_dialog) {
103                 add_route_dialog->set_session (s);
104         }
105
106         if (session_option_editor) {
107                 session_option_editor->set_session (s);
108         }
109
110         if (shuttle_box) {
111                 shuttle_box->set_session (s);
112         }
113
114         for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
115                 if (_global_port_matrix[*i]->get()) {
116                         _global_port_matrix[*i]->get()->set_session (_session);
117                 }
118         }
119
120         primary_clock->set_session (s);
121         secondary_clock->set_session (s);
122         big_clock->set_session (s);
123         time_info_box->set_session (s);
124 #ifdef WITH_VIDEOTIMELINE
125         video_timeline->set_session (s);
126 #endif
127
128         /* sensitize menu bar options that are now valid */
129
130         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
131         ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
132
133         if (_session->locations()->num_range_markers()) {
134                 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
135         } else {
136                 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
137         }
138
139         if (!_session->monitor_out()) {
140                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
141                 if (act) {
142                         act->set_sensitive (false);
143                 }
144         }
145
146         /* allow wastebasket flush again */
147
148         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
149         if (act) {
150                 act->set_sensitive (true);
151         }
152
153         /* there are never any selections on startup */
154
155         ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
156         ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
157         ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
158         ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
159         ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
160
161         rec_button.set_sensitive (true);
162
163         solo_alert_button.set_active (_session->soloing());
164
165         setup_session_options ();
166
167         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::transport_rec_enable_blink));
168         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::solo_blink));
169         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::sync_blink));
170         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::audition_blink));
171         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::feedback_blink));
172
173         _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
174         _session->StepEditStatusChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::step_edit_status_change, this, _1), gui_context());
175         _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
176         _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_autosave, this), gui_context());
177
178         _session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
179         _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
180         _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
181         _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
182         _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
183         _session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
184
185 #ifdef HAVE_JACK_SESSION
186         engine->JackSessionEvent.connect (*_session, MISSING_INVALIDATOR, boost::bind (&Session::jack_session_event, _session, _1), gui_context());
187 #endif
188
189         /* Clocks are on by default after we are connected to a session, so show that here.
190         */
191
192         connect_dependents_to_session (s);
193
194         /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
195            restore their modes or are explicitly set, we will cause the "new" mode to be saved
196            back to the session XML ("Extra") state.
197          */
198
199         AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
200
201         Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
202
203         start_clocking ();
204         start_blinking ();
205
206         map_transport_state ();
207
208         second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second), 1000);
209         point_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds), 100);
210         point_zero_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_one_seconds), 40);
211
212         update_format ();
213 }
214
215 int
216 ARDOUR_UI::unload_session (bool hide_stuff)
217 {
218 #ifdef WITH_VIDEOTIMELINE
219         if (_session) {
220                 /* close video-monitor
221                  * this needed to enfore querying its settings (window size,..)
222                  * which are reported asynchroneously.
223                  */
224                 ARDOUR_UI::instance()->video_timeline->close_session();
225         }
226 #endif
227         if (_session && _session->dirty()) {
228                 std::vector<std::string> actions;
229                 actions.push_back (_("Don't close"));
230                 actions.push_back (_("Just close"));
231                 actions.push_back (_("Save and close"));
232                 switch (ask_about_saving_session (actions)) {
233                 case -1:
234                         ARDOUR_UI::instance()->video_timeline->set_session(_session);
235                         // cancel
236                         return 1;
237
238                 case 1:
239                         _session->save_state ("");
240                         break;
241                 }
242         }
243
244         if (hide_stuff) {
245                 editor->hide ();
246                 mixer->hide ();
247                 theme_manager->hide ();
248         }
249
250         second_connection.disconnect ();
251         point_one_second_connection.disconnect ();
252         point_oh_five_second_connection.disconnect ();
253         point_zero_one_second_connection.disconnect();
254
255         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
256
257         rec_button.set_sensitive (false);
258
259         stop_blinking ();
260         stop_clocking ();
261
262         /* drop everything attached to the blink signal */
263
264         Blink.clear ();
265
266         delete _session;
267         _session = 0;
268
269         session_loaded = false;
270
271         update_buffer_load ();
272
273         return 0;
274 }
275
276 void
277 ARDOUR_UI::toggle_big_clock_window ()
278 {
279         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBigClock"));
280         if (act) {
281                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
282
283                 if (tact->get_active()) {
284                         big_clock_window->get()->show_all ();
285                         big_clock_window->get()->present ();
286                 } else {
287                         big_clock_window->get()->hide ();
288                 }
289         }
290 }
291
292 void
293 ARDOUR_UI::toggle_speaker_config_window ()
294 {
295         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-speaker-config"));
296         if (act) {
297                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
298
299                 if (tact->get_active()) {
300                         speaker_config_window->get()->show_all ();
301                         speaker_config_window->get()->present ();
302                 } else {
303                         speaker_config_window->get()->hide ();
304                 }
305         }
306 }
307
308 void
309 ARDOUR_UI::new_midi_tracer_window ()
310 {
311         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
312         if (!act) {
313                 return;
314         }
315
316         std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
317         while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
318                 ++i;
319         }
320
321         if (i == _midi_tracer_windows.end()) {
322                 /* all our MIDITracer windows are visible; make a new one */
323                 MidiTracer* t = new MidiTracer ();
324                 manage_window (*t);
325                 t->show_all ();
326                 _midi_tracer_windows.push_back (t);
327         } else {
328                 /* re-use the hidden one */
329                 (*i)->show_all ();
330         }
331 }
332
333 void
334 ARDOUR_UI::toggle_rc_options_window ()
335 {
336         if (rc_option_editor == 0) {
337                 rc_option_editor = new RCOptionEditor;
338                 rc_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleRCOptionsEditor")));
339                 rc_option_editor->set_session (_session);
340         }
341
342         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleRCOptionsEditor"));
343         if (act) {
344                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
345
346                 if (tact->get_active()) {
347                         rc_option_editor->show_all ();
348                         rc_option_editor->present ();
349                 } else {
350                         rc_option_editor->hide ();
351                 }
352         }
353 }
354
355 void
356 ARDOUR_UI::toggle_session_options_window ()
357 {
358         if (session_option_editor == 0) {
359                 session_option_editor = new SessionOptionEditor (_session);
360                 session_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleSessionOptionsEditor")));
361         }
362
363         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleSessionOptionsEditor"));
364         if (act) {
365                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
366
367                 if (tact->get_active()) {
368                         session_option_editor->show_all ();
369                         session_option_editor->present ();
370                 } else {
371                         session_option_editor->hide ();
372                 }
373         }
374 }
375
376 int
377 ARDOUR_UI::create_location_ui ()
378 {
379         if (location_ui->get() == 0) {
380                 location_ui->set (new LocationUIWindow ());
381                 location_ui->get()->set_session (_session);
382                 location_ui->get()->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleLocations")));
383         }
384         return 0;
385 }
386
387 void
388 ARDOUR_UI::toggle_location_window ()
389 {
390         if (create_location_ui()) {
391                 return;
392         }
393
394         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleLocations"));
395         if (act) {
396                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
397
398                 if (tact->get_active()) {
399                         location_ui->get()->show_all ();
400                         location_ui->get()->present ();
401                 } else {
402                         location_ui->get()->hide ();
403                 }
404         }
405 }
406
407 void
408 ARDOUR_UI::toggle_key_editor ()
409 {
410         if (key_editor == 0) {
411                 key_editor = new KeyEditor;
412                 key_editor->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleKeyEditor")));
413         }
414
415         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleKeyEditor"));
416         if (act) {
417                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
418
419                 if (tact->get_active()) {
420                         key_editor->show_all ();
421                         key_editor->present ();
422                 } else {
423                         key_editor->hide ();
424                 }
425         }
426 }
427
428 void
429 ARDOUR_UI::toggle_theme_manager ()
430 {
431         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleThemeManager"));
432         if (act) {
433                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
434
435                 if (tact->get_active()) {
436                         theme_manager->show_all ();
437                         theme_manager->present ();
438                 } else {
439                         theme_manager->hide ();
440                 }
441         }
442 }
443
444 void
445 ARDOUR_UI::create_bundle_manager ()
446 {
447         if (bundle_manager == 0) {
448                 bundle_manager = new BundleManager (_session);
449                 bundle_manager->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBundleManager")));
450         }
451 }
452
453 void
454 ARDOUR_UI::toggle_bundle_manager ()
455 {
456         create_bundle_manager ();
457
458         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBundleManager"));
459         if (act) {
460                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
461
462                 if (tact->get_active()) {
463                         bundle_manager->show_all ();
464                         bundle_manager->present ();
465                 } else {
466                         bundle_manager->hide ();
467                 }
468         }
469 }
470
471 int
472 ARDOUR_UI::create_route_params ()
473 {
474         if (route_params == 0) {
475                 route_params = new RouteParams_UI ();
476                 route_params->set_session (_session);
477                 route_params->signal_unmap().connect (sigc::bind(sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleInspector")));
478         }
479         return 0;
480 }
481
482 void
483 ARDOUR_UI::toggle_route_params_window ()
484 {
485         if (create_route_params ()) {
486                 return;
487         }
488
489         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleInspector"));
490         if (act) {
491                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
492
493                 if (tact->get_active()) {
494                         route_params->show_all ();
495                         route_params->present ();
496                 } else {
497                         route_params->hide ();
498                 }
499         }
500 }
501
502 void
503 ARDOUR_UI::handle_locations_change (Location *)
504 {
505         if (_session) {
506                 if (_session->locations()->num_range_markers()) {
507                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
508                 } else {
509                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
510                 }
511         }
512 }
513
514 bool
515 ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor)
516 {
517         if (window_was_editor) {
518
519                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
520                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
521                         float_big_clock (editor);
522                 }
523
524         } else {
525
526                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
527                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
528                         float_big_clock (mixer);
529                 }
530         }
531
532         return false;
533 }