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