Merge branch 'master' into cairocanvas
[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                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
221         }
222 #endif
223         if (_session && _session->dirty()) {
224                 std::vector<std::string> actions;
225                 actions.push_back (_("Don't close"));
226                 actions.push_back (_("Just close"));
227                 actions.push_back (_("Save and close"));
228                 switch (ask_about_saving_session (actions)) {
229                 case -1:
230                         // cancel
231                         return 1;
232
233                 case 1:
234                         _session->save_state ("");
235                         break;
236                 }
237         }
238
239         if (hide_stuff) {
240                 editor->hide ();
241                 mixer->hide ();
242                 theme_manager->hide ();
243         }
244
245         second_connection.disconnect ();
246         point_one_second_connection.disconnect ();
247         point_oh_five_second_connection.disconnect ();
248         point_zero_one_second_connection.disconnect();
249
250         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
251
252         rec_button.set_sensitive (false);
253 #ifdef WITH_VIDEOTIMELINE
254         ARDOUR_UI::instance()->video_timeline->close_session();
255 #endif
256
257         stop_blinking ();
258         stop_clocking ();
259
260         /* drop everything attached to the blink signal */
261
262         Blink.clear ();
263
264         delete _session;
265         _session = 0;
266
267         session_loaded = false;
268
269         update_buffer_load ();
270
271         return 0;
272 }
273
274 void
275 ARDOUR_UI::toggle_big_clock_window ()
276 {
277         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBigClock"));
278         if (act) {
279                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
280
281                 if (tact->get_active()) {
282                         big_clock_window->get()->show_all ();
283                         big_clock_window->get()->present ();
284                 } else {
285                         big_clock_window->get()->hide ();
286                 }
287         }
288 }
289
290 void
291 ARDOUR_UI::toggle_speaker_config_window ()
292 {
293         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-speaker-config"));
294         if (act) {
295                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
296
297                 if (tact->get_active()) {
298                         speaker_config_window->get()->show_all ();
299                         speaker_config_window->get()->present ();
300                 } else {
301                         speaker_config_window->get()->hide ();
302                 }
303         }
304 }
305
306 void
307 ARDOUR_UI::new_midi_tracer_window ()
308 {
309         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
310         if (!act) {
311                 return;
312         }
313
314         std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
315         while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
316                 ++i;
317         }
318
319         if (i == _midi_tracer_windows.end()) {
320                 /* all our MIDITracer windows are visible; make a new one */
321                 MidiTracer* t = new MidiTracer ();
322                 manage_window (*t);
323                 t->show_all ();
324                 _midi_tracer_windows.push_back (t);
325         } else {
326                 /* re-use the hidden one */
327                 (*i)->show_all ();
328         }
329 }
330
331 void
332 ARDOUR_UI::toggle_rc_options_window ()
333 {
334         if (rc_option_editor == 0) {
335                 rc_option_editor = new RCOptionEditor;
336                 rc_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleRCOptionsEditor")));
337                 rc_option_editor->set_session (_session);
338         }
339
340         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleRCOptionsEditor"));
341         if (act) {
342                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
343
344                 if (tact->get_active()) {
345                         rc_option_editor->show_all ();
346                         rc_option_editor->present ();
347                 } else {
348                         rc_option_editor->hide ();
349                 }
350         }
351 }
352
353 void
354 ARDOUR_UI::toggle_session_options_window ()
355 {
356         if (session_option_editor == 0) {
357                 session_option_editor = new SessionOptionEditor (_session);
358                 session_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleSessionOptionsEditor")));
359         }
360
361         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleSessionOptionsEditor"));
362         if (act) {
363                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
364
365                 if (tact->get_active()) {
366                         session_option_editor->show_all ();
367                         session_option_editor->present ();
368                 } else {
369                         session_option_editor->hide ();
370                 }
371         }
372 }
373
374 int
375 ARDOUR_UI::create_location_ui ()
376 {
377         if (location_ui->get() == 0) {
378                 location_ui->set (new LocationUIWindow ());
379                 location_ui->get()->set_session (_session);
380                 location_ui->get()->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleLocations")));
381         }
382         return 0;
383 }
384
385 void
386 ARDOUR_UI::toggle_location_window ()
387 {
388         if (create_location_ui()) {
389                 return;
390         }
391
392         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleLocations"));
393         if (act) {
394                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
395
396                 if (tact->get_active()) {
397                         location_ui->get()->show_all ();
398                         location_ui->get()->present ();
399                 } else {
400                         location_ui->get()->hide ();
401                 }
402         }
403 }
404
405 void
406 ARDOUR_UI::toggle_key_editor ()
407 {
408         if (key_editor == 0) {
409                 key_editor = new KeyEditor;
410                 key_editor->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleKeyEditor")));
411         }
412
413         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleKeyEditor"));
414         if (act) {
415                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
416
417                 if (tact->get_active()) {
418                         key_editor->show_all ();
419                         key_editor->present ();
420                 } else {
421                         key_editor->hide ();
422                 }
423         }
424 }
425
426 void
427 ARDOUR_UI::toggle_theme_manager ()
428 {
429         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleThemeManager"));
430         if (act) {
431                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
432
433                 if (tact->get_active()) {
434                         theme_manager->show_all ();
435                         theme_manager->present ();
436                 } else {
437                         theme_manager->hide ();
438                 }
439         }
440 }
441
442 void
443 ARDOUR_UI::create_bundle_manager ()
444 {
445         if (bundle_manager == 0) {
446                 bundle_manager = new BundleManager (_session);
447                 bundle_manager->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBundleManager")));
448         }
449 }
450
451 void
452 ARDOUR_UI::toggle_bundle_manager ()
453 {
454         create_bundle_manager ();
455
456         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBundleManager"));
457         if (act) {
458                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
459
460                 if (tact->get_active()) {
461                         bundle_manager->show_all ();
462                         bundle_manager->present ();
463                 } else {
464                         bundle_manager->hide ();
465                 }
466         }
467 }
468
469 int
470 ARDOUR_UI::create_route_params ()
471 {
472         if (route_params == 0) {
473                 route_params = new RouteParams_UI ();
474                 route_params->set_session (_session);
475                 route_params->signal_unmap().connect (sigc::bind(sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleInspector")));
476         }
477         return 0;
478 }
479
480 void
481 ARDOUR_UI::toggle_route_params_window ()
482 {
483         if (create_route_params ()) {
484                 return;
485         }
486
487         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleInspector"));
488         if (act) {
489                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
490
491                 if (tact->get_active()) {
492                         route_params->show_all ();
493                         route_params->present ();
494                 } else {
495                         route_params->hide ();
496                 }
497         }
498 }
499
500 void
501 ARDOUR_UI::handle_locations_change (Location *)
502 {
503         if (_session) {
504                 if (_session->locations()->num_range_markers()) {
505                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
506                 } else {
507                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
508                 }
509         }
510 }
511
512 bool
513 ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor)
514 {
515         if (window_was_editor) {
516
517                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
518                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
519                         float_big_clock (editor);
520                 }
521
522         } else {
523
524                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
525                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
526                         float_big_clock (mixer);
527                 }
528         }
529
530         return false;
531 }