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