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