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