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