Allow multiple MIDI tracer windows.
[ArdourMidi.git] / gtk2_ardour / ardour_ui_dialogs.cc
blob096f8ac730646ba8cedb1891b8aa7c5a3571fcdd
1 /*
2 Copyright (C) 2000 Paul Davis
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.
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.
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.
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.
26 #include "ardour/session.h"
27 #include "ardour/audioengine.h"
29 #include "actions.h"
30 #include "ardour_ui.h"
31 #include "location_ui.h"
32 #include "mixer_ui.h"
33 #include "rc_option_editor.h"
34 #include "session_option_editor.h"
35 #include "public_editor.h"
36 #include "route_params_ui.h"
37 #include "sfdb_ui.h"
38 #include "theme_manager.h"
39 #include "bundle_manager.h"
40 #include "keyeditor.h"
41 #include "gui_thread.h"
42 #include "midi_tracer.h"
44 #include "i18n.h"
46 using namespace ARDOUR;
47 using namespace PBD;
48 using namespace Glib;
49 using namespace Gtk;
50 using namespace Gtkmm2ext;
52 void
53 ARDOUR_UI::set_session (Session *s)
55 SessionHandlePtr::set_session (s);
57 if (!_session) {
58 return;
61 if (location_ui) {
62 location_ui->set_session(s);
65 if (route_params) {
66 route_params->set_session (s);
69 primary_clock.set_session (s);
70 secondary_clock.set_session (s);
71 big_clock.set_session (s);
72 preroll_clock.set_session (s);
73 postroll_clock.set_session (s);
75 /* sensitize menu bar options that are now valid */
77 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
78 ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
80 if (_session->locations()->num_range_markers()) {
81 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
82 } else {
83 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
86 if (!_session->monitor_out()) {
87 Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
88 if (act) {
89 act->set_sensitive (false);
93 /* allow wastebasket flush again */
95 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
96 if (act) {
97 act->set_sensitive (true);
100 /* there are never any selections on startup */
102 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
103 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
104 ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
105 ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
106 ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
108 rec_button.set_sensitive (true);
109 shuttle_box.set_sensitive (true);
110 solo_alert_button.set_active (_session->soloing());
112 setup_session_options ();
114 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::transport_rec_enable_blink));
115 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::solo_blink));
116 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::sync_blink));
117 Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::audition_blink));
119 _session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
120 _session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
121 _session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_autosave, this), gui_context());
123 _session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
124 _session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
125 _session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
126 _session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
127 _session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
129 #ifdef HAVE_JACK_SESSION
130 engine->JackSessionEvent.connect (*_session, MISSING_INVALIDATOR, ui_bind (&Session::jack_session_event, _session, _1), gui_context());
131 #endif
133 /* Clocks are on by default after we are connected to a session, so show that here.
136 connect_dependents_to_session (s);
138 /* listen to clock mode changes. don't do this earlier because otherwise as the clocks
139 restore their modes or are explicitly set, we will cause the "new" mode to be saved
140 back to the session XML ("Extra") state.
143 AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
145 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
147 start_clocking ();
148 start_blinking ();
150 map_transport_state ();
152 second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second), 1000);
153 point_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds), 100);
154 point_zero_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_one_seconds), 40);
158 ARDOUR_UI::unload_session (bool hide_stuff)
160 if (_session && _session->dirty()) {
161 switch (ask_about_saving_session (_("close"))) {
162 case -1:
163 // cancel
164 return 1;
166 case 1:
167 _session->save_state ("");
168 break;
172 if (hide_stuff) {
173 editor->hide ();
174 mixer->hide ();
175 theme_manager->hide ();
178 second_connection.disconnect ();
179 point_one_second_connection.disconnect ();
180 point_oh_five_second_connection.disconnect ();
181 point_zero_one_second_connection.disconnect();
183 ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
185 rec_button.set_sensitive (false);
186 shuttle_box.set_sensitive (false);
188 stop_blinking ();
189 stop_clocking ();
191 /* drop everything attached to the blink signal */
193 Blink.clear ();
195 delete _session;
197 update_buffer_load ();
199 return 0;
202 void
203 ARDOUR_UI::toggle_big_clock_window ()
205 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBigClock"));
206 if (act) {
207 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
209 if (tact->get_active()) {
210 big_clock_window->show_all ();
211 big_clock_window->present ();
212 } else {
213 big_clock_window->hide ();
218 void
219 ARDOUR_UI::new_midi_tracer_window ()
221 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
222 if (!act) {
223 return;
226 std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
227 while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
228 ++i;
231 if (i == _midi_tracer_windows.end()) {
232 /* all our MIDITracer windows are visible; make a new one */
233 MidiTracer* t = new MidiTracer ();
234 manage_window (*t);
235 t->show_all ();
236 _midi_tracer_windows.push_back (t);
237 } else {
238 /* re-use the hidden one */
239 (*i)->show_all ();
243 void
244 ARDOUR_UI::toggle_rc_options_window ()
246 if (rc_option_editor == 0) {
247 rc_option_editor = new RCOptionEditor;
248 rc_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleRCOptionsEditor")));
249 rc_option_editor->set_session (_session);
252 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleRCOptionsEditor"));
253 if (act) {
254 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
256 if (tact->get_active()) {
257 rc_option_editor->show_all ();
258 rc_option_editor->present ();
259 } else {
260 rc_option_editor->hide ();
265 void
266 ARDOUR_UI::toggle_session_options_window ()
268 if (session_option_editor == 0) {
269 session_option_editor = new SessionOptionEditor (_session);
270 session_option_editor->signal_unmap().connect(sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleSessionOptionsEditor")));
273 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleSessionOptionsEditor"));
274 if (act) {
275 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
277 if (tact->get_active()) {
278 session_option_editor->show_all ();
279 session_option_editor->present ();
280 } else {
281 session_option_editor->hide ();
287 ARDOUR_UI::create_location_ui ()
289 if (location_ui == 0) {
290 location_ui = new LocationUIWindow ();
291 location_ui->set_session (_session);
292 location_ui->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleLocations")));
294 return 0;
297 void
298 ARDOUR_UI::toggle_location_window ()
300 if (create_location_ui()) {
301 return;
304 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleLocations"));
305 if (act) {
306 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
308 if (tact->get_active()) {
309 location_ui->show_all ();
310 location_ui->present ();
311 } else {
312 location_ui->hide ();
317 void
318 ARDOUR_UI::toggle_key_editor ()
320 if (key_editor == 0) {
321 key_editor = new KeyEditor;
322 key_editor->signal_unmap().connect (sigc::bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleKeyEditor")));
325 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleKeyEditor"));
326 if (act) {
327 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
329 if (tact->get_active()) {
330 key_editor->show_all ();
331 key_editor->present ();
332 } else {
333 key_editor->hide ();
338 void
339 ARDOUR_UI::toggle_theme_manager ()
341 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleThemeManager"));
342 if (act) {
343 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
345 if (tact->get_active()) {
346 theme_manager->show_all ();
347 theme_manager->present ();
348 } else {
349 theme_manager->hide ();
354 void
355 ARDOUR_UI::create_bundle_manager ()
357 if (bundle_manager == 0) {
358 bundle_manager = new BundleManager (_session);
359 bundle_manager->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBundleManager")));
363 void
364 ARDOUR_UI::toggle_bundle_manager ()
366 create_bundle_manager ();
368 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleBundleManager"));
369 if (act) {
370 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
372 if (tact->get_active()) {
373 bundle_manager->show_all ();
374 bundle_manager->present ();
375 } else {
376 bundle_manager->hide ();
382 ARDOUR_UI::create_route_params ()
384 if (route_params == 0) {
385 route_params = new RouteParams_UI ();
386 route_params->set_session (_session);
387 route_params->signal_unmap().connect (sigc::bind(sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleInspector")));
389 return 0;
392 void
393 ARDOUR_UI::toggle_route_params_window ()
395 if (create_route_params ()) {
396 return;
399 RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleInspector"));
400 if (act) {
401 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
403 if (tact->get_active()) {
404 route_params->show_all ();
405 route_params->present ();
406 } else {
407 route_params->hide ();
412 void
413 ARDOUR_UI::handle_locations_change (Location *)
415 if (_session) {
416 if (_session->locations()->num_range_markers()) {
417 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
418 } else {
419 ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
424 bool
425 ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor)
427 if (window_was_editor) {
429 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
430 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
431 float_big_clock (editor);
434 } else {
436 if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
437 (ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
438 float_big_clock (mixer);
442 return false;