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