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