remove unused variable
[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/audioengine.h"
27 #include "ardour/automation_watch.h"
28 #include "ardour/profile.h"
29 #include "ardour/session.h"
30
31 #ifdef interface
32 #undef interface
33 #endif
34
35 #include "actions.h"
36 #include "add_route_dialog.h"
37 #include "add_video_dialog.h"
38 #include "ardour_ui.h"
39 #include "big_clock_window.h"
40 #include "bundle_manager.h"
41 #include "global_port_matrix.h"
42 #include "gui_object.h"
43 #include "gui_thread.h"
44 #include "keyeditor.h"
45 #include "location_ui.h"
46 #include "main_clock.h"
47 #include "meter_patterns.h"
48 #include "midi_tracer.h"
49 #include "mixer_ui.h"
50 #include "public_editor.h"
51 #include "rc_option_editor.h"
52 #include "route_params_ui.h"
53 #include "shuttle_control.h"
54 #include "session_option_editor.h"
55 #include "speaker_dialog.h"
56 #include "splash.h"
57 #include "sfdb_ui.h"
58 #include "theme_manager.h"
59 #include "time_info_box.h"
60
61 #include <gtkmm2ext/keyboard.h>
62
63 #include "i18n.h"
64
65 using namespace ARDOUR;
66 using namespace PBD;
67 using namespace Glib;
68 using namespace Gtk;
69 using namespace Gtkmm2ext;
70
71 void
72 ARDOUR_UI::set_session (Session *s)
73 {
74         SessionHandlePtr::set_session (s);
75
76         if (!_session) {
77                 WM::Manager::instance().set_session (s);
78                 /* Session option editor cannot exist across change-of-session */
79                 session_option_editor.drop_window ();
80                 /* Ditto for AddVideoDialog */
81                 add_video_dialog.drop_window ();
82                 return;
83         }
84
85         const XMLNode* node = _session->extra_xml (X_("UI"));
86
87         if (node) {
88                 const XMLNodeList& children = node->children();
89                 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
90                         if ((*i)->name() == GUIObjectState::xml_node_name) {
91                                 gui_object_state->load (**i);
92                                 break;
93                         }
94                 }
95         }
96
97         WM::Manager::instance().set_session (s);
98
99         AutomationWatch::instance().set_session (s);
100
101         if (shuttle_box) {
102                 shuttle_box->set_session (s);
103         }
104
105         primary_clock->set_session (s);
106         secondary_clock->set_session (s);
107         big_clock->set_session (s);
108         time_info_box->set_session (s);
109         video_timeline->set_session (s);
110
111         /* sensitize menu bar options that are now valid */
112
113         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
114         ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
115
116         if (_session->locations()->num_range_markers()) {
117                 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
118         } else {
119                 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
120         }
121
122         if (!_session->monitor_out()) {
123                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
124                 if (act) {
125                         act->set_sensitive (false);
126                 }
127         }
128
129         /* allow wastebasket flush again */
130
131         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
132         if (act) {
133                 act->set_sensitive (true);
134         }
135
136         /* there are never any selections on startup */
137
138         ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
139         ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
140         ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
141         ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
142         ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
143
144         rec_button.set_sensitive (true);
145
146         solo_alert_button.set_active (_session->soloing());
147
148         setup_session_options ();
149
150         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::transport_rec_enable_blink));
151         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::solo_blink));
152         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::sync_blink));
153         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::audition_blink));
154         Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::feedback_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, boost::bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
162         _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
163         _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
164         _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
165         _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
166         _session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
167
168         /* Clocks are on by default after we are connected to a session, so show that here.
169         */
170
171         connect_dependents_to_session (s);
172
173         /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
174            restore their modes or are explicitly set, we will cause the "new" mode to be saved
175            back to the session XML ("Extra") state.
176          */
177
178         AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
179
180         Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
181
182         start_clocking ();
183         start_blinking ();
184
185         map_transport_state ();
186
187         second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second), 1000);
188         point_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds), 100);
189         point_zero_something_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_something_seconds), 40);
190
191         update_format ();
192
193         if (meter_box.get_parent()) {
194                 transport_tearoff_hbox.remove (meter_box);
195                 transport_tearoff_hbox.remove (editor_meter_peak_display);
196         }
197
198         if (editor_meter) {
199                 meter_box.remove(*editor_meter);
200                 delete editor_meter;
201                 editor_meter = 0;
202                 editor_meter_peak_display.hide();
203         }
204
205         if (meter_box.get_parent()) {
206                 transport_tearoff_hbox.remove (meter_box);
207                 transport_tearoff_hbox.remove (editor_meter_peak_display);
208         }
209
210         if (_session && 
211             _session->master_out() && 
212             _session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
213
214                 if (!ARDOUR::Profile->get_trx()) {
215                         editor_meter = new LevelMeterHBox(_session);
216                         editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
217                         editor_meter->clear_meters();
218                         editor_meter->set_type (_session->master_out()->meter_type());
219                         editor_meter->setup_meters (30, 12, 6);
220                         editor_meter->show();
221                         meter_box.pack_start(*editor_meter);
222                 }
223
224                 ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
225                 ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
226                 ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
227
228                 editor_meter_peak_display.set_name ("meterbridge peakindicator");
229                 editor_meter_peak_display.set_elements((ArdourButton::Element) (ArdourButton::Edge|ArdourButton::Body));
230                 editor_meter_peak_display.unset_flags (Gtk::CAN_FOCUS);
231                 editor_meter_peak_display.set_size_request(6, -1);
232                 editor_meter_peak_display.set_corner_radius(2);
233
234                 editor_meter_max_peak = -INFINITY;
235                 editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
236
237                 if (Config->get_show_editor_meter() && !ARDOUR::Profile->get_trx()) {
238                         transport_tearoff_hbox.pack_start (meter_box, false, false);
239                         transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
240                         meter_box.show();
241                         editor_meter_peak_display.show();
242                 }
243         }
244 }
245
246 int
247 ARDOUR_UI::unload_session (bool hide_stuff)
248 {
249         if (_session) {
250                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
251         }
252
253         if (_session && _session->dirty()) {
254                 std::vector<std::string> actions;
255                 actions.push_back (_("Don't close"));
256                 actions.push_back (_("Just close"));
257                 actions.push_back (_("Save and close"));
258                 switch (ask_about_saving_session (actions)) {
259                 case -1:
260                         // cancel
261                         return 1;
262
263                 case 1:
264                         _session->save_state ("");
265                         break;
266                 }
267         }
268
269         if (hide_stuff) {
270                 editor->hide ();
271                 mixer->hide ();
272                 meterbridge->hide ();
273                 theme_manager->hide ();
274                 audio_port_matrix->hide();
275                 midi_port_matrix->hide();
276                 route_params->hide();
277         }
278
279         second_connection.disconnect ();
280         point_one_second_connection.disconnect ();
281         point_zero_something_second_connection.disconnect();
282
283         if (editor_meter) {
284                 meter_box.remove(*editor_meter);
285                 delete editor_meter;
286                 editor_meter = 0;
287                 editor_meter_peak_display.hide();
288         }
289
290         ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
291
292         rec_button.set_sensitive (false);
293
294         WM::Manager::instance().set_session ((ARDOUR::Session*) 0);
295
296         if (ARDOUR_UI::instance()->video_timeline) {
297                 ARDOUR_UI::instance()->video_timeline->close_session();
298         }
299
300         stop_blinking ();
301         stop_clocking ();
302
303         /* drop everything attached to the blink signal */
304
305         Blink.clear ();
306
307         delete _session;
308         _session = 0;
309
310         session_loaded = false;
311
312         update_buffer_load ();
313
314         return 0;
315 }
316
317 static bool
318 _hide_splash (gpointer arg)
319 {
320         ((ARDOUR_UI*)arg)->hide_splash();
321         return false;
322 }
323
324 void
325 ARDOUR_UI::goto_editor_window ()
326 {
327         if (splash && splash->is_visible()) {
328                 // in 2 seconds, hide the splash screen
329                 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000);
330         }
331
332         editor->show_window ();
333         editor->present ();
334         /* mixer should now be on top */
335         WM::Manager::instance().set_transient_for (editor);
336         _mixer_on_top = false;
337 }
338
339 void
340 ARDOUR_UI::goto_mixer_window ()
341 {
342         Glib::RefPtr<Gdk::Window> win;
343         Glib::RefPtr<Gdk::Screen> screen;
344         
345         if (editor) {
346                 win = editor->get_window ();
347         }
348
349         if (win) {
350                 screen = win->get_screen();
351         } else {
352                 screen = Gdk::Screen::get_default();
353         }
354         
355         if (g_getenv ("ARDOUR_LOVES_STUPID_TINY_SCREENS") == 0 && screen && screen->get_height() < 700) {
356                 Gtk::MessageDialog msg (_("This screen is not tall enough to display the mixer window"));
357                 msg.run ();
358                 return;
359         }
360
361         mixer->show_window ();
362         mixer->present ();
363         /* mixer should now be on top */
364         WM::Manager::instance().set_transient_for (mixer);
365         _mixer_on_top = true;
366 }
367
368 void
369 ARDOUR_UI::toggle_mixer_window ()
370 {
371         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-mixer"));
372         if (!act) {
373                 return;
374         }
375
376         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
377
378         if (tact->get_active()) {
379                 goto_mixer_window ();
380         } else {
381                 mixer->hide ();
382         }
383 }
384
385 void
386 ARDOUR_UI::toggle_meterbridge ()
387 {
388         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-meterbridge"));
389         if (!act) {
390                 return;
391         }
392
393         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
394
395         if (tact->get_active()) {
396                 meterbridge->show_window ();
397         } else {
398                 meterbridge->hide_window (NULL);
399         }
400 }
401
402 void
403 ARDOUR_UI::toggle_editor_mixer ()
404 {
405         bool obscuring = false;
406         /* currently, if windows are on different
407            screens then we do nothing; but in the
408            future we may want to bring the window 
409            to the front or something, so I'm leaving this 
410            variable for future use
411         */
412         bool same_screen = true; 
413         
414         if (editor && mixer) {
415
416                 /* remeber: Screen != Monitor (Screen is a separately rendered
417                  * continuous geometry that make include 1 or more monitors.
418                  */
419                 
420                 if (editor->get_screen() != mixer->get_screen() && (mixer->get_screen() != 0) && (editor->get_screen() != 0)) {
421                         // different screens, so don't do anything
422                         same_screen = false;
423                 } else {
424                         // they are on the same screen, see if they are obscuring each other
425
426                         gint ex, ey, ew, eh;
427                         gint mx, my, mw, mh;
428
429                         editor->get_position (ex, ey);
430                         editor->get_size (ew, eh);
431
432                         mixer->get_position (mx, my);
433                         mixer->get_size (mw, mh);
434
435                         GdkRectangle e;
436                         GdkRectangle m;
437                         GdkRectangle r;
438
439                         e.x = ex;
440                         e.y = ey;
441                         e.width = ew;
442                         e.height = eh;
443
444                         m.x = mx;
445                         m.y = my;
446                         m.width = mw;
447                         m.height = mh;
448
449                         if (gdk_rectangle_intersect (&e, &m, &r)) {
450                                 obscuring = true;
451                         }
452                 }
453         }
454
455         if (mixer && !mixer->not_visible() && mixer->property_has_toplevel_focus()) {
456                 if (obscuring && same_screen) {
457                         goto_editor_window();
458                 }
459         } else if (editor && !editor->not_visible() && editor->property_has_toplevel_focus()) {
460                 if (obscuring && same_screen) {
461                         goto_mixer_window();
462                 }
463         } else if (mixer && mixer->not_visible()) {
464                 if (obscuring && same_screen) {
465                         goto_mixer_window ();
466                 }
467         } else if (editor && editor->not_visible()) {
468                 if (obscuring && same_screen) {
469                         goto_editor_window ();
470                 }
471         } else if (obscuring && same_screen) {
472                 //it's unclear what to do here, so just do the opposite of what we did last time  (old behavior)
473                 if (_mixer_on_top) {
474                         goto_editor_window ();
475                 } else {
476                         goto_mixer_window ();
477                 }
478         }
479 }
480
481 void
482 ARDOUR_UI::new_midi_tracer_window ()
483 {
484         RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
485         if (!act) {
486                 return;
487         }
488
489         std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
490         while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
491                 ++i;
492         }
493
494         if (i == _midi_tracer_windows.end()) {
495                 /* all our MIDITracer windows are visible; make a new one */
496                 MidiTracer* t = new MidiTracer ();
497                 t->show_all ();
498                 _midi_tracer_windows.push_back (t);
499         } else {
500                 /* re-use the hidden one */
501                 (*i)->show_all ();
502         }
503 }
504
505 BundleManager*
506 ARDOUR_UI::create_bundle_manager ()
507 {
508         return new BundleManager (_session);
509 }
510
511 AddVideoDialog*
512 ARDOUR_UI::create_add_video_dialog ()
513 {
514         return new AddVideoDialog (_session);
515 }
516
517 SessionOptionEditor*
518 ARDOUR_UI::create_session_option_editor ()
519 {
520         return new SessionOptionEditor (_session);
521 }
522
523 BigClockWindow*
524 ARDOUR_UI::create_big_clock_window ()
525 {
526         return new BigClockWindow (*big_clock);
527 }
528
529 void
530 ARDOUR_UI::handle_locations_change (Location *)
531 {
532         if (_session) {
533                 if (_session->locations()->num_range_markers()) {
534                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
535                 } else {
536                         ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
537                 }
538         }
539 }
540
541 bool
542 ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor)
543 {
544         if (window_was_editor) {
545
546                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
547                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
548                         if (big_clock_window) {
549                                 big_clock_window->set_transient_for (*editor);
550                         }
551                 }
552
553         } else {
554
555                 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
556                     (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
557                         if (big_clock_window) {
558                                 big_clock_window->set_transient_for (*mixer);
559                         }
560                 }
561         }
562
563         return false;
564 }
565
566 bool
567 ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
568 {
569         if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier|Gtkmm2ext::Keyboard::TertiaryModifier)) {
570                 ArdourMeter::ResetAllPeakDisplays ();
571         } else if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
572                 if (_session->master_out()) {
573                         ArdourMeter::ResetGroupPeakDisplays (_session->master_out()->route_group());
574                 }
575         } else if (_session->master_out()) {
576                 ArdourMeter::ResetRoutePeakDisplays (_session->master_out().get());
577         }
578         return true;
579 }
580
581 void
582 ARDOUR_UI::toggle_mixer_space()
583 {
584         Glib::RefPtr<Action> act = ActionManager::get_action ("Common", "ToggleMaximalMixer");
585
586         if (act) {
587                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
588                 if (tact->get_active()) {
589                         mixer->maximise_mixer_space ();
590                 } else {
591                         mixer->restore_mixer_space ();
592                 }
593         }
594 }