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"
28
#include "ardour/automation_watch.h"
31
#include "add_route_dialog.h"
32
#include "add_video_dialog.h"
33
#include "ardour_ui.h"
34
#include "big_clock_window.h"
35
#include "bundle_manager.h"
36
#include "global_port_matrix.h"
37
#include "gui_object.h"
38
#include "gui_thread.h"
39
#include "keyeditor.h"
40
#include "location_ui.h"
41
#include "main_clock.h"
42
#include "meter_patterns.h"
43
#include "midi_tracer.h"
45
#include "public_editor.h"
46
#include "rc_option_editor.h"
47
#include "route_params_ui.h"
48
#include "shuttle_control.h"
49
#include "session_option_editor.h"
50
#include "speaker_dialog.h"
53
#include "theme_manager.h"
54
#include "time_info_box.h"
56
#include <gtkmm2ext/keyboard.h>
60
using namespace ARDOUR;
64
using namespace Gtkmm2ext;
67
ARDOUR_UI::set_session (Session *s)
69
SessionHandlePtr::set_session (s);
73
WM::Manager::instance().set_session (s);
74
/* Session option editor cannot exist across change-of-session */
75
session_option_editor.drop_window ();
76
/* Ditto for AddVideoDialog */
77
add_video_dialog.drop_window ();
81
const XMLNode* node = _session->extra_xml (X_("UI"));
84
const XMLNodeList& children = node->children();
85
for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
86
if ((*i)->name() == GUIObjectState::xml_node_name) {
87
gui_object_state->load (**i);
93
WM::Manager::instance().set_session (s);
95
AutomationWatch::instance().set_session (s);
98
shuttle_box->set_session (s);
101
primary_clock->set_session (s);
102
secondary_clock->set_session (s);
103
big_clock->set_session (s);
104
time_info_box->set_session (s);
105
video_timeline->set_session (s);
107
/* sensitize menu bar options that are now valid */
109
ActionManager::set_sensitive (ActionManager::session_sensitive_actions, true);
110
ActionManager::set_sensitive (ActionManager::write_sensitive_actions, _session->writable());
112
if (_session->locations()->num_range_markers()) {
113
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
115
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
118
if (!_session->monitor_out()) {
119
Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
121
act->set_sensitive (false);
125
/* allow wastebasket flush again */
127
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
129
act->set_sensitive (true);
132
/* there are never any selections on startup */
134
ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
135
ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, false);
136
ActionManager::set_sensitive (ActionManager::line_selection_sensitive_actions, false);
137
ActionManager::set_sensitive (ActionManager::point_selection_sensitive_actions, false);
138
ActionManager::set_sensitive (ActionManager::playlist_selection_sensitive_actions, false);
140
rec_button.set_sensitive (true);
142
solo_alert_button.set_active (_session->soloing());
144
setup_session_options ();
146
Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::transport_rec_enable_blink));
147
Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::solo_blink));
148
Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::sync_blink));
149
Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::audition_blink));
150
Blink.connect (sigc::mem_fun(*this, &ARDOUR_UI::feedback_blink));
152
_session->RecordStateChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::record_state_changed, this), gui_context());
153
_session->StepEditStatusChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::step_edit_status_change, this, _1), gui_context());
154
_session->TransportStateChange.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::map_transport_state, this), gui_context());
155
_session->DirtyChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_autosave, this), gui_context());
157
_session->Xrun.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::xrun_handler, this, _1), gui_context());
158
_session->SoloActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::soloing_changed, this, _1), gui_context());
159
_session->AuditionActive.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::auditioning_changed, this, _1), gui_context());
160
_session->locations()->added.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
161
_session->locations()->removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::handle_locations_change, this, _1), gui_context());
162
_session->config.ParameterChanged.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_parameter_changed, this, _1), gui_context ());
164
#ifdef HAVE_JACK_SESSION
165
engine->JackSessionEvent.connect (*_session, MISSING_INVALIDATOR, boost::bind (&Session::jack_session_event, _session, _1), gui_context());
168
/* Clocks are on by default after we are connected to a session, so show that here.
171
connect_dependents_to_session (s);
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.
178
AudioClock::ModeChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::store_clock_modes));
180
Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::first_idle));
185
map_transport_state ();
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);
194
meter_box.remove(*editor_meter);
197
editor_meter_peak_display.hide();
200
if (_session && _session->master_out()) {
201
editor_meter = new LevelMeterHBox(_session);
202
editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
203
editor_meter->clear_meters();
204
editor_meter->set_type (_session->master_out()->meter_type());
205
editor_meter->setup_meters (30, 12, 6);
206
editor_meter->show();
207
meter_box.pack_start(*editor_meter);
209
ArdourMeter::ResetAllPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_peak_display));
210
ArdourMeter::ResetRoutePeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_route_peak_display));
211
ArdourMeter::ResetGroupPeakDisplays.connect (sigc::mem_fun(*this, &ARDOUR_UI::reset_group_peak_display));
213
editor_meter_peak_display.set_name ("meterbridge peakindicator");
214
editor_meter_peak_display.set_elements((ArdourButton::Element) (ArdourButton::Edge|ArdourButton::Body));
215
editor_meter_peak_display.unset_flags (Gtk::CAN_FOCUS);
216
editor_meter_peak_display.set_size_request(6, -1);
217
editor_meter_peak_display.set_corner_radius(2);
219
editor_meter_max_peak = -INFINITY;
220
editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
222
if (Config->get_show_editor_meter()) {
224
editor_meter_peak_display.show();
227
editor_meter_peak_display.hide();
234
ARDOUR_UI::unload_session (bool hide_stuff)
237
ARDOUR_UI::instance()->video_timeline->sync_session_state();
240
if (_session && _session->dirty()) {
241
std::vector<std::string> actions;
242
actions.push_back (_("Don't close"));
243
actions.push_back (_("Just close"));
244
actions.push_back (_("Save and close"));
245
switch (ask_about_saving_session (actions)) {
251
_session->save_state ("");
259
meterbridge->hide ();
260
theme_manager->hide ();
261
audio_port_matrix->hide();
262
midi_port_matrix->hide();
263
route_params->hide();
266
second_connection.disconnect ();
267
point_one_second_connection.disconnect ();
268
point_zero_something_second_connection.disconnect();
271
meter_box.remove(*editor_meter);
274
editor_meter_peak_display.hide();
277
ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
279
rec_button.set_sensitive (false);
281
WM::Manager::instance().set_session ((ARDOUR::Session*) 0);
282
ARDOUR_UI::instance()->video_timeline->close_session();
287
/* drop everything attached to the blink signal */
294
session_loaded = false;
296
update_buffer_load ();
302
_hide_splash (gpointer arg)
304
((ARDOUR_UI*)arg)->hide_splash();
309
ARDOUR_UI::goto_editor_window ()
311
if (splash && splash->is_visible()) {
312
// in 2 seconds, hide the splash screen
313
Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 2000);
316
editor->show_window ();
318
/* mixer should now be on top */
319
WM::Manager::instance().set_transient_for (editor);
320
_mixer_on_top = false;
324
ARDOUR_UI::goto_mixer_window ()
326
Glib::RefPtr<Gdk::Window> win;
327
Glib::RefPtr<Gdk::Screen> screen;
330
win = editor->get_window ();
334
screen = win->get_screen();
336
screen = Gdk::Screen::get_default();
339
if (screen && screen->get_height() < 700) {
340
Gtk::MessageDialog msg (_("This screen is not tall enough to display the mixer window"));
345
mixer->show_window ();
347
/* mixer should now be on top */
348
WM::Manager::instance().set_transient_for (mixer);
349
_mixer_on_top = true;
353
ARDOUR_UI::toggle_mixer_window ()
355
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-mixer"));
360
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
362
if (tact->get_active()) {
363
goto_mixer_window ();
370
ARDOUR_UI::toggle_meterbridge ()
372
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("toggle-meterbridge"));
377
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
379
if (tact->get_active()) {
380
meterbridge->show_window ();
382
meterbridge->hide_window (NULL);
387
ARDOUR_UI::toggle_editor_mixer ()
389
bool obscuring = false;
390
/* currently, if windows are on different
391
screens then we do nothing; but in the
392
future we may want to bring the window
393
to the front or something, so I'm leaving this
394
variable for future use
396
bool same_screen = true;
398
if (editor && mixer) {
400
/* remeber: Screen != Monitor (Screen is a separately rendered
401
* continuous geometry that make include 1 or more monitors.
404
if (editor->get_screen() != mixer->get_screen() && (mixer->get_screen() != 0) && (editor->get_screen() != 0)) {
405
// different screens, so don't do anything
408
// they are on the same screen, see if they are obscuring each other
413
editor->get_position (ex, ey);
414
editor->get_size (ew, eh);
416
mixer->get_position (mx, my);
417
mixer->get_size (mw, mh);
433
if (gdk_rectangle_intersect (&e, &m, &r)) {
439
if (mixer && !mixer->not_visible() && mixer->property_has_toplevel_focus()) {
440
if (obscuring && same_screen) {
441
goto_editor_window();
443
} else if (editor && !editor->not_visible() && editor->property_has_toplevel_focus()) {
444
if (obscuring && same_screen) {
447
} else if (mixer && mixer->not_visible()) {
448
if (obscuring && same_screen) {
449
goto_mixer_window ();
451
} else if (editor && editor->not_visible()) {
452
if (obscuring && same_screen) {
453
goto_editor_window ();
455
} else if (obscuring && same_screen) {
456
//it's unclear what to do here, so just do the opposite of what we did last time (old behavior)
458
goto_editor_window ();
460
goto_mixer_window ();
466
ARDOUR_UI::new_midi_tracer_window ()
468
RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("NewMIDITracer"));
473
std::list<MidiTracer*>::iterator i = _midi_tracer_windows.begin ();
474
while (i != _midi_tracer_windows.end() && (*i)->get_visible() == true) {
478
if (i == _midi_tracer_windows.end()) {
479
/* all our MIDITracer windows are visible; make a new one */
480
MidiTracer* t = new MidiTracer ();
482
_midi_tracer_windows.push_back (t);
484
/* re-use the hidden one */
490
ARDOUR_UI::create_bundle_manager ()
492
return new BundleManager (_session);
496
ARDOUR_UI::create_add_video_dialog ()
498
return new AddVideoDialog (_session);
502
ARDOUR_UI::create_session_option_editor ()
504
return new SessionOptionEditor (_session);
508
ARDOUR_UI::create_big_clock_window ()
510
return new BigClockWindow (*big_clock);
514
ARDOUR_UI::handle_locations_change (Location *)
517
if (_session->locations()->num_range_markers()) {
518
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, true);
520
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
526
ARDOUR_UI::main_window_state_event_handler (GdkEventWindowState* ev, bool window_was_editor)
528
if (window_was_editor) {
530
if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
531
(ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
532
if (big_clock_window) {
533
big_clock_window->set_transient_for (*editor);
539
if ((ev->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) &&
540
(ev->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
541
if (big_clock_window) {
542
big_clock_window->set_transient_for (*mixer);
551
ARDOUR_UI::editor_meter_peak_button_release (GdkEventButton* ev)
553
if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier|Gtkmm2ext::Keyboard::TertiaryModifier)) {
554
ArdourMeter::ResetAllPeakDisplays ();
555
} else if (ev->button == 1 && Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
556
if (_session->master_out()) {
557
ArdourMeter::ResetGroupPeakDisplays (_session->master_out()->route_group());
559
} else if (_session->master_out()) {
560
ArdourMeter::ResetRoutePeakDisplays (_session->master_out().get());