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