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