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