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