2 Copyright (C) 1999-2013 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.
21 #include "gtk2ardour-config.h"
22 #include "gtk2ardour-version.h"
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
43 #include "pbd/gstdio_compat.h"
45 #include <gtkmm/messagedialog.h>
46 #include <gtkmm/accelmap.h>
48 #include "pbd/error.h"
49 #include "pbd/basename.h"
50 #include "pbd/compose.h"
51 #include "pbd/convert.h"
52 #include "pbd/failed_constructor.h"
53 #include "pbd/enumwriter.h"
54 #include "pbd/memento_command.h"
55 #include "pbd/openuri.h"
56 #include "pbd/stl_delete.h"
57 #include "pbd/file_utils.h"
58 #include "pbd/localtime_r.h"
59 #include "pbd/pthread_utils.h"
60 #include "pbd/replace_all.h"
61 #include "pbd/xml++.h"
63 #include "gtkmm2ext/application.h"
64 #include "gtkmm2ext/bindings.h"
65 #include "gtkmm2ext/gtk_ui.h"
66 #include "gtkmm2ext/utils.h"
67 #include "gtkmm2ext/click_box.h"
68 #include "gtkmm2ext/fastmeter.h"
69 #include "gtkmm2ext/popup.h"
70 #include "gtkmm2ext/window_title.h"
72 #include "ardour/ardour.h"
73 #include "ardour/audio_backend.h"
74 #include "ardour/audioengine.h"
75 #include "ardour/audiofilesource.h"
76 #include "ardour/automation_watch.h"
77 #include "ardour/diskstream.h"
78 #include "ardour/filename_extensions.h"
79 #include "ardour/filesystem_paths.h"
80 #include "ardour/ltc_file_reader.h"
81 #include "ardour/port.h"
82 #include "ardour/plugin_manager.h"
83 #include "ardour/process_thread.h"
84 #include "ardour/profile.h"
85 #include "ardour/recent_sessions.h"
86 #include "ardour/session_directory.h"
87 #include "ardour/session_route.h"
88 #include "ardour/session_state_utils.h"
89 #include "ardour/session_utils.h"
90 #include "ardour/source_factory.h"
91 #include "ardour/slave.h"
92 #include "ardour/system_exec.h"
94 #include "LuaBridge/LuaBridge.h"
96 #ifdef WINDOWS_VST_SUPPORT
99 #ifdef AUDIOUNIT_SUPPORT
100 #include "ardour/audio_unit.h"
103 // fix for OSX (nsm.h has a check function, AU/Apple defines check)
108 #include "timecode/time.h"
110 typedef uint64_t microseconds_t;
115 #include "add_route_dialog.h"
116 #include "ambiguous_file_dialog.h"
117 #include "ardour_ui.h"
118 #include "audio_clock.h"
119 #include "audio_region_view.h"
120 #include "big_clock_window.h"
121 #include "bundle_manager.h"
122 #include "duplicate_routes_dialog.h"
124 #include "engine_dialog.h"
125 #include "export_video_dialog.h"
126 #include "export_video_infobox.h"
127 #include "gain_meter.h"
128 #include "global_port_matrix.h"
129 #include "gui_object.h"
130 #include "gui_thread.h"
131 #include "keyboard.h"
132 #include "keyeditor.h"
133 #include "location_ui.h"
134 #include "lua_script_manager.h"
135 #include "luawindow.h"
136 #include "main_clock.h"
137 #include "missing_file_dialog.h"
138 #include "missing_plugin_dialog.h"
139 #include "mixer_ui.h"
140 #include "meterbridge.h"
141 #include "mouse_cursors.h"
144 #include "pingback.h"
145 #include "processor_box.h"
146 #include "prompter.h"
147 #include "public_editor.h"
148 #include "rc_option_editor.h"
149 #include "route_time_axis.h"
150 #include "route_params_ui.h"
151 #include "save_as_dialog.h"
152 #include "script_selector.h"
153 #include "session_dialog.h"
154 #include "session_metadata_dialog.h"
155 #include "session_option_editor.h"
156 #include "shuttle_control.h"
157 #include "speaker_dialog.h"
160 #include "theme_manager.h"
161 #include "time_axis_view_item.h"
164 #include "video_server_dialog.h"
165 #include "add_video_dialog.h"
166 #include "transcode_video_dialog.h"
170 using namespace ARDOUR;
171 using namespace ARDOUR_UI_UTILS;
173 using namespace Gtkmm2ext;
176 using namespace Editing;
178 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
180 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
181 sigc::signal<void> ARDOUR_UI::CloseAllDialogs;
184 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
186 MessageDialog msg (string_compose (_("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
187 "Would you like these files to be copied and used for %1 %2.x?\n\n"
188 "(This will require you to restart %1.)"),
189 PROGRAM_NAME, PROGRAM_VERSION, version),
190 false, /* no markup */
193 true /* modal, though it hardly matters since it is the only window */
196 msg.set_default_response (Gtk::RESPONSE_YES);
199 return (msg.run() == Gtk::RESPONSE_YES);
203 libxml_generic_error_func (void* /* parsing_context*/,
211 vsnprintf (buf, sizeof (buf), msg, ap);
212 error << buf << endmsg;
217 libxml_structured_error_func (void* /* parsing_context*/,
225 replace_all (msg, "\n", "");
227 if (err->file && err->line) {
228 error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
231 error << ':' << err->int2;
238 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
239 : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
240 , session_loaded (false)
241 , gui_object_state (new GUIObjectState)
242 , primary_clock (new MainClock (X_("primary"), X_("transport"), true ))
243 , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
244 , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
246 , global_actions (X_("global"))
247 , ignore_dual_punch (false)
252 , _mixer_on_top (false)
253 , _initial_verbose_plugin_scan (false)
254 , first_time_engine_run (true)
255 , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
256 , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
257 , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
258 , goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd))
259 , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
260 , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
261 , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
262 , auto_return_button (ArdourButton::led_default_elements)
263 , follow_edits_button (ArdourButton::led_default_elements)
264 , auto_input_button (ArdourButton::led_default_elements)
265 , auditioning_alert_button (_("Audition"))
266 , solo_alert_button (_("Solo"))
267 , feedback_alert_button (_("Feedback"))
268 , error_alert_button ( ArdourButton::just_led_default_elements )
270 , editor_meter_peak_display()
271 , _numpad_locate_happening (false)
272 , _session_is_new (false)
273 , last_key_press_time (0)
277 , rc_option_editor (0)
278 , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
279 , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
280 , about (X_("about"), _("About"))
281 , location_ui (X_("locations"), _("Locations"))
282 , route_params (X_("inspector"), _("Tracks and Busses"))
283 , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
284 , export_video_dialog (X_("video-export"), _("Video Export Dialog"))
285 , lua_script_window (X_("script-manager"), _("Script Manager"))
286 , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
287 , add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
288 , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
289 , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
290 , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
291 , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
292 , key_editor (X_("key-editor"), _("Bindings Editor"), boost::bind (&ARDOUR_UI::create_key_editor, this))
293 , video_server_process (0)
295 , have_configure_timeout (false)
296 , last_configure_time (0)
298 , have_disk_speed_dialog_displayed (false)
299 , _status_bar_visibility (X_("status-bar"))
300 , _feedback_exists (false)
301 , _log_not_acknowledged (LogLevelNone)
302 , duplicate_routes_dialog (0)
303 , editor_visibility_button (S_("Window|Editor"))
304 , mixer_visibility_button (S_("Window|Mixer"))
305 , prefs_visibility_button (S_("Window|Preferences"))
307 Gtkmm2ext::init (localedir);
309 UIConfiguration::instance().post_gui_init ();
311 if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
312 MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
314 /* configuration was modified, exit immediately */
318 if (theArdourUI == 0) {
322 /* stop libxml from spewing to stdout/stderr */
324 xmlSetGenericErrorFunc (this, libxml_generic_error_func);
325 xmlSetStructuredErrorFunc (this, libxml_structured_error_func);
327 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
328 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
329 UIConfiguration::instance().map_parameters (pc);
331 roll_button.set_controllable (roll_controllable);
332 stop_button.set_controllable (stop_controllable);
333 goto_start_button.set_controllable (goto_start_controllable);
334 goto_end_button.set_controllable (goto_end_controllable);
335 auto_loop_button.set_controllable (auto_loop_controllable);
336 play_selection_button.set_controllable (play_selection_controllable);
337 rec_button.set_controllable (rec_controllable);
339 roll_button.set_name ("transport button");
340 stop_button.set_name ("transport button");
341 goto_start_button.set_name ("transport button");
342 goto_end_button.set_name ("transport button");
343 auto_loop_button.set_name ("transport button");
344 play_selection_button.set_name ("transport button");
345 rec_button.set_name ("transport recenable button");
346 midi_panic_button.set_name ("transport button");
348 ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
349 ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
351 ARDOUR::Session::VersionMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_format_mismatch, this, _1, _2), gui_context());
353 /* handle dialog requests */
355 ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
357 /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
359 ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
361 /* handle Audio/MIDI setup when session requires it */
363 ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1));
365 /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
367 ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
369 /* handle requests to quit (coming from JACK session) */
371 ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::finish, this), gui_context ());
373 /* tell the user about feedback */
375 ARDOUR::Session::FeedbackDetected.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::feedback_detected, this), gui_context ());
376 ARDOUR::Session::SuccessfulGraphSort.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::successful_graph_sort, this), gui_context ());
378 /* handle requests to deal with missing files */
380 ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
382 /* and ambiguous files */
384 ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
386 /* also plugin scan messages */
387 ARDOUR::PluginScanMessage.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_dialog, this, _1, _2, _3), gui_context());
388 ARDOUR::PluginScanTimeout.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_timeout, this, _1), gui_context());
390 ARDOUR::GUIIdle.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::gui_idle_handler, this), gui_context());
392 Config->ParameterChanged.connect ( forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::set_flat_buttons, this), gui_context() );
395 /* lets get this party started */
397 setup_gtk_ardour_enums ();
400 SessionEvent::create_per_thread_pool ("GUI", 4096);
402 /* we like keyboards */
404 keyboard = new ArdourKeyboard(*this);
406 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
408 keyboard->set_state (*node, Stateful::loading_state_version);
411 UIConfiguration::instance().reset_dpi ();
413 TimeAxisViewItem::set_constant_heights ();
415 /* Set this up so that our window proxies can register actions */
417 ActionManager::init ();
419 /* The following must happen after ARDOUR::init() so that Config is set up */
421 const XMLNode* ui_xml = Config->extra_xml (X_("UI"));
424 key_editor.set_state (*ui_xml, 0);
425 session_option_editor.set_state (*ui_xml, 0);
426 speaker_config_window.set_state (*ui_xml, 0);
427 about.set_state (*ui_xml, 0);
428 add_route_dialog.set_state (*ui_xml, 0);
429 add_video_dialog.set_state (*ui_xml, 0);
430 route_params.set_state (*ui_xml, 0);
431 bundle_manager.set_state (*ui_xml, 0);
432 location_ui.set_state (*ui_xml, 0);
433 big_clock_window.set_state (*ui_xml, 0);
434 audio_port_matrix.set_state (*ui_xml, 0);
435 midi_port_matrix.set_state (*ui_xml, 0);
436 export_video_dialog.set_state (*ui_xml, 0);
437 lua_script_window.set_state (*ui_xml, 0);
440 /* Separate windows */
442 WM::Manager::instance().register_window (&key_editor);
443 WM::Manager::instance().register_window (&session_option_editor);
444 WM::Manager::instance().register_window (&speaker_config_window);
445 WM::Manager::instance().register_window (&about);
446 WM::Manager::instance().register_window (&add_route_dialog);
447 WM::Manager::instance().register_window (&add_video_dialog);
448 WM::Manager::instance().register_window (&route_params);
449 WM::Manager::instance().register_window (&audio_midi_setup);
450 WM::Manager::instance().register_window (&export_video_dialog);
451 WM::Manager::instance().register_window (&lua_script_window);
452 WM::Manager::instance().register_window (&bundle_manager);
453 WM::Manager::instance().register_window (&location_ui);
454 WM::Manager::instance().register_window (&big_clock_window);
455 WM::Manager::instance().register_window (&audio_port_matrix);
456 WM::Manager::instance().register_window (&midi_port_matrix);
458 /* Trigger setting up the color scheme and loading the GTK RC file */
460 UIConfiguration::instance().load_rc_file (false);
462 _process_thread = new ProcessThread ();
463 _process_thread->init ();
465 UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets));
470 GlobalPortMatrixWindow*
471 ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
476 return new GlobalPortMatrixWindow (_session, type);
480 ARDOUR_UI::attach_to_engine ()
482 AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
483 ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
487 ARDOUR_UI::engine_stopped ()
489 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
490 ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
491 ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
492 update_sample_rate (0);
497 ARDOUR_UI::engine_running ()
499 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
500 if (first_time_engine_run) {
502 first_time_engine_run = false;
506 _session->reset_xrun_count ();
508 update_disk_space ();
510 update_xrun_count ();
511 update_sample_rate (AudioEngine::instance()->sample_rate());
512 update_timecode_format ();
513 update_peak_thread_work ();
514 ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true);
515 ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false);
519 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
521 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
522 /* we can't rely on the original string continuing to exist when we are called
523 again in the GUI thread, so make a copy and note that we need to
526 char *copy = strdup (reason);
527 Gtkmm2ext::UI::instance()->call_slot (MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
531 ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
532 ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
534 update_sample_rate (0);
538 /* if the reason is a non-empty string, it means that the backend was shutdown
539 rather than just Ardour.
542 if (strlen (reason)) {
543 msgstr = string_compose (_("The audio backend was shutdown because:\n\n%1"), reason);
545 msgstr = string_compose (_("\
546 The audio backend has either been shutdown or it\n\
547 disconnected %1 because %1\n\
548 was not fast enough. Try to restart\n\
549 the audio backend and save the session."), PROGRAM_NAME);
552 MessageDialog msg (_main_window, msgstr);
553 pop_back_splash (msg);
557 free (const_cast<char*> (reason));
562 ARDOUR_UI::post_engine ()
564 /* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine
566 #ifdef AUDIOUNIT_SUPPORT
568 if (AUPluginInfo::au_get_crashlog(au_msg)) {
569 popup_error(_("Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see the log window for further details."));
570 error << _("Audio Unit Plugin Scan Failed:") << endmsg;
571 info << au_msg << endmsg;
575 ARDOUR::init_post_engine ();
577 /* connect to important signals */
579 AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
580 AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
581 AudioEngine::instance()->BufferSizeChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
582 AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
583 AudioEngine::instance()->BecameSilent.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::audioengine_became_silent, this), gui_context());
585 if (setup_windows ()) {
586 throw failed_constructor ();
589 /* Do this after setup_windows (), as that's when the _status_bar_visibility is created */
590 XMLNode* n = Config->extra_xml (X_("UI"));
592 _status_bar_visibility.set_state (*n);
595 check_memory_locking();
597 /* this is the first point at which all the possible actions are
598 * available, because some of the available actions are dependent on
599 * aspects of the engine/backend.
602 if (ARDOUR_COMMAND_LINE::show_key_actions) {
605 vector<string> paths;
606 vector<string> labels;
607 vector<string> tooltips;
609 vector<Glib::RefPtr<Gtk::Action> > actions;
611 Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
613 vector<string>::iterator k;
614 vector<string>::iterator p;
616 for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) {
621 cout << *p << " => " << *k << endl;
625 halt_connection.disconnect ();
626 AudioEngine::instance()->stop ();
630 /* this being a GUI and all, we want peakfiles */
632 AudioFileSource::set_build_peakfiles (true);
633 AudioFileSource::set_build_missing_peakfiles (true);
635 /* set default clock modes */
637 primary_clock->set_mode (AudioClock::Timecode);
638 secondary_clock->set_mode (AudioClock::BBT);
640 /* start the time-of-day-clock */
643 /* OS X provides a nearly-always visible wallclock, so don't be stupid */
644 update_wall_clock ();
645 Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1);
650 Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
651 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
652 Config->map_parameters (pc);
654 UIConfiguration::instance().map_parameters (pc);
658 ARDOUR_UI::~ARDOUR_UI ()
660 UIConfiguration::instance().save_state();
664 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
665 // don't bother at 'real' exit. the OS cleans up for us.
666 delete big_clock; big_clock = 0;
667 delete primary_clock; primary_clock = 0;
668 delete secondary_clock; secondary_clock = 0;
669 delete _process_thread; _process_thread = 0;
670 delete meterbridge; meterbridge = 0;
671 delete luawindow; luawindow = 0;
672 delete editor; editor = 0;
673 delete mixer; mixer = 0;
675 delete gui_object_state; gui_object_state = 0;
676 FastMeter::flush_pattern_cache ();
677 PixFader::flush_pattern_cache ();
681 /* Small trick to flush main-thread event pool.
682 * Other thread-pools are destroyed at pthread_exit(),
683 * but tmain thread termination is too late to trigger Pool::~Pool()
685 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Clear, SessionEvent::Immediate, 0, 0); // get the pool reference, values don't matter since the event is never queued.
686 delete ev->event_pool();
691 ARDOUR_UI::pop_back_splash (Gtk::Window& win)
693 if (Splash::instance()) {
694 Splash::instance()->pop_back_for (win);
699 ARDOUR_UI::configure_timeout ()
701 if (last_configure_time == 0) {
702 /* no configure events yet */
706 /* force a gap of 0.5 seconds since the last configure event
709 if (get_microseconds() - last_configure_time < 500000) {
712 have_configure_timeout = false;
713 save_ardour_state ();
719 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
721 if (have_configure_timeout) {
722 last_configure_time = get_microseconds();
724 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
725 have_configure_timeout = true;
732 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
734 const XMLProperty* prop;
736 if ((prop = node.property ("roll")) != 0) {
737 roll_controllable->set_id (prop->value());
739 if ((prop = node.property ("stop")) != 0) {
740 stop_controllable->set_id (prop->value());
742 if ((prop = node.property ("goto-start")) != 0) {
743 goto_start_controllable->set_id (prop->value());
745 if ((prop = node.property ("goto-end")) != 0) {
746 goto_end_controllable->set_id (prop->value());
748 if ((prop = node.property ("auto-loop")) != 0) {
749 auto_loop_controllable->set_id (prop->value());
751 if ((prop = node.property ("play-selection")) != 0) {
752 play_selection_controllable->set_id (prop->value());
754 if ((prop = node.property ("rec")) != 0) {
755 rec_controllable->set_id (prop->value());
757 if ((prop = node.property ("shuttle")) != 0) {
758 shuttle_box->controllable()->set_id (prop->value());
763 ARDOUR_UI::get_transport_controllable_state ()
765 XMLNode* node = new XMLNode(X_("TransportControllables"));
768 roll_controllable->id().print (buf, sizeof (buf));
769 node->add_property (X_("roll"), buf);
770 stop_controllable->id().print (buf, sizeof (buf));
771 node->add_property (X_("stop"), buf);
772 goto_start_controllable->id().print (buf, sizeof (buf));
773 node->add_property (X_("goto_start"), buf);
774 goto_end_controllable->id().print (buf, sizeof (buf));
775 node->add_property (X_("goto_end"), buf);
776 auto_loop_controllable->id().print (buf, sizeof (buf));
777 node->add_property (X_("auto_loop"), buf);
778 play_selection_controllable->id().print (buf, sizeof (buf));
779 node->add_property (X_("play_selection"), buf);
780 rec_controllable->id().print (buf, sizeof (buf));
781 node->add_property (X_("rec"), buf);
782 shuttle_box->controllable()->id().print (buf, sizeof (buf));
783 node->add_property (X_("shuttle"), buf);
789 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
792 _session->save_state (snapshot_name);
797 ARDOUR_UI::autosave_session ()
799 if (g_main_depth() > 1) {
800 /* inside a recursive main loop,
801 give up because we may not be able to
807 if (!Config->get_periodic_safety_backups()) {
812 _session->maybe_write_autosave();
819 ARDOUR_UI::session_dirty_changed ()
826 ARDOUR_UI::update_autosave ()
828 if (_session && _session->dirty()) {
829 if (_autosave_connection.connected()) {
830 _autosave_connection.disconnect();
833 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
834 Config->get_periodic_safety_backup_interval() * 1000);
837 if (_autosave_connection.connected()) {
838 _autosave_connection.disconnect();
844 ARDOUR_UI::check_announcements ()
847 string _annc_filename;
850 _annc_filename = PROGRAM_NAME "_announcements_osx_";
851 #elif defined PLATFORM_WINDOWS
852 _annc_filename = PROGRAM_NAME "_announcements_windows_";
854 _annc_filename = PROGRAM_NAME "_announcements_linux_";
856 _annc_filename.append (VERSIONSTRING);
858 _announce_string = "";
860 std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
861 FILE* fin = g_fopen (path.c_str(), "rb");
863 while (!feof (fin)) {
866 if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
869 _announce_string.append (tmp, len);
874 pingback (VERSIONSTRING, path);
879 _hide_splash (gpointer arg)
881 ((ARDOUR_UI*)arg)->hide_splash();
886 ARDOUR_UI::starting ()
888 Application* app = Application::instance ();
890 bool brand_new_user = ArdourStartup::required ();
892 app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
893 app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::load_from_application_api));
895 if (ARDOUR_COMMAND_LINE::check_announcements) {
896 check_announcements ();
901 /* we need to create this early because it may need to set the
902 * audio backend end up.
906 audio_midi_setup.get (true);
908 std::cerr << "audio-midi engine setup failed."<< std::endl;
912 if ((nsm_url = g_getenv ("NSM_URL")) != 0) {
913 nsm = new NSM_Client;
914 if (!nsm->init (nsm_url)) {
915 /* the ardour executable may have different names:
917 * waf's obj.target for distro versions: eg ardour4, ardourvst4
918 * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
919 * argv[0] does not apply since we need the wrapper-script (not the binary itself)
921 * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
923 const char *process_name = g_getenv ("ARDOUR_SELF");
924 nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour4");
927 // wait for announce reply from nsm server
928 for ( i = 0; i < 5000; ++i) {
932 if (nsm->is_active()) {
937 error << _("NSM server did not announce itself") << endmsg;
940 // wait for open command from nsm server
941 for ( i = 0; i < 5000; ++i) {
944 if (nsm->client_id ()) {
950 error << _("NSM: no client ID provided") << endmsg;
954 if (_session && nsm) {
955 _session->set_nsm_state( nsm->is_active() );
957 error << _("NSM: no session created") << endmsg;
961 // nsm requires these actions disabled
962 vector<string> action_names;
963 action_names.push_back("SaveAs");
964 action_names.push_back("Rename");
965 action_names.push_back("New");
966 action_names.push_back("Open");
967 action_names.push_back("Recent");
968 action_names.push_back("Close");
970 for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
971 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
973 act->set_sensitive (false);
980 error << _("NSM: initialization failed") << endmsg;
986 if (brand_new_user) {
987 _initial_verbose_plugin_scan = true;
992 _initial_verbose_plugin_scan = false;
993 switch (s.response ()) {
994 case Gtk::RESPONSE_OK:
1001 #ifdef NO_PLUGIN_STATE
1003 ARDOUR::RecentSessions rs;
1004 ARDOUR::read_recent_sessions (rs);
1006 string path = Glib::build_filename (user_config_directory(), ".iknowaboutfreeversion");
1008 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS) && !rs.empty()) {
1010 /* already used Ardour, have sessions ... warn about plugin state */
1012 ArdourDialog d (_("Free/Demo Version Warning"), true);
1014 Button b (string_compose (_("Subscribe and support development of %1"), PROGRAM_NAME));
1015 CheckButton c (_("Don't warn me about this again"));
1017 l.set_markup (string_compose (_("<span weight=\"bold\" size=\"large\">%1</span>\n\n<b>%2</b>\n\n<i>%3</i>\n\n%4"),
1018 string_compose (_("This is a free/demo version of %1"), PROGRAM_NAME),
1019 _("It will not restore OR save any plugin settings"),
1020 _("If you load an existing session with plugin settings\n"
1021 "they will not be used and will be lost."),
1022 _("To get full access to updates without this limitation\n"
1023 "consider becoming a subscriber for a low cost every month.")));
1024 l.set_justify (JUSTIFY_CENTER);
1026 b.signal_clicked().connect (mem_fun(*this, &ARDOUR_UI::launch_subscribe));
1028 d.get_vbox()->pack_start (l, true, true);
1029 d.get_vbox()->pack_start (b, false, false, 12);
1030 d.get_vbox()->pack_start (c, false, false, 12);
1032 d.add_button (_("Quit now"), RESPONSE_CANCEL);
1033 d.add_button (string_compose (_("Continue using %1"), PROGRAM_NAME), RESPONSE_OK);
1037 c.signal_toggled().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (toggle_file_existence), path)));
1039 if (d.run () != RESPONSE_OK) {
1045 /* go get a session */
1047 const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
1049 if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
1050 std::cerr << "Cannot get session parameters."<< std::endl;
1057 WM::Manager::instance().show_visible ();
1059 /* We have to do this here since goto_editor_window() ends up calling show_all() on the
1060 * editor window, and we may want stuff to be hidden.
1062 _status_bar_visibility.update ();
1064 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
1066 if (splash && splash->is_visible()) {
1067 // in 1 second, hide the splash screen
1068 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
1071 /* all other dialogs are created conditionally */
1077 ARDOUR_UI::check_memory_locking ()
1079 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
1080 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
1084 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
1086 if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
1088 struct rlimit limits;
1090 long pages, page_size;
1092 size_t pages_len=sizeof(pages);
1093 if ((page_size = getpagesize()) < 0 ||
1094 sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
1096 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
1101 ram = (int64_t) pages * (int64_t) page_size;
1104 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
1108 if (limits.rlim_cur != RLIM_INFINITY) {
1110 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
1114 _("WARNING: Your system has a limit for maximum amount of locked memory. "
1115 "This might cause %1 to run out of memory before your system "
1116 "runs out of memory. \n\n"
1117 "You can view the memory limit with 'ulimit -l', "
1118 "and it is normally controlled by %2"),
1121 X_("/etc/login.conf")
1123 X_(" /etc/security/limits.conf")
1127 msg.set_default_response (RESPONSE_OK);
1129 VBox* vbox = msg.get_vbox();
1131 CheckButton cb (_("Do not show this window again"));
1132 hbox.pack_start (cb, true, false);
1133 vbox->pack_start (hbox);
1138 pop_back_splash (msg);
1142 if (cb.get_active()) {
1143 XMLNode node (X_("no-memory-warning"));
1144 Config->add_instant_xml (node);
1149 #endif // !__APPLE__
1154 ARDOUR_UI::queue_finish ()
1156 Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
1160 ARDOUR_UI::idle_finish ()
1163 return false; /* do not call again */
1170 ARDOUR_UI::instance()->video_timeline->sync_session_state();
1172 if (_session->dirty()) {
1173 vector<string> actions;
1174 actions.push_back (_("Don't quit"));
1175 actions.push_back (_("Just quit"));
1176 actions.push_back (_("Save and quit"));
1177 switch (ask_about_saving_session(actions)) {
1182 /* use the default name */
1183 if (save_state_canfail ("")) {
1184 /* failed - don't quit */
1185 MessageDialog msg (_main_window,
1186 string_compose (_("\
1187 %1 was unable to save your session.\n\n\
1188 If you still wish to quit, please use the\n\n\
1189 \"Just quit\" option."), PROGRAM_NAME));
1190 pop_back_splash(msg);
1200 second_connection.disconnect ();
1201 point_one_second_connection.disconnect ();
1202 point_zero_something_second_connection.disconnect();
1203 fps_connection.disconnect();
1206 delete ARDOUR_UI::instance()->video_timeline;
1207 ARDOUR_UI::instance()->video_timeline = NULL;
1208 stop_video_server();
1210 /* Save state before deleting the session, as that causes some
1211 windows to be destroyed before their visible state can be
1214 save_ardour_state ();
1216 close_all_dialogs ();
1219 _session->set_clean ();
1220 _session->remove_pending_capture_state ();
1225 halt_connection.disconnect ();
1226 AudioEngine::instance()->stop ();
1227 #ifdef WINDOWS_VST_SUPPORT
1228 fst_stop_threading();
1234 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1236 ArdourDialog window (_("Unsaved Session"));
1237 Gtk::HBox dhbox; // the hbox for the image and text
1238 Gtk::Label prompt_label;
1239 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
1243 assert (actions.size() >= 3);
1245 window.add_button (actions[0], RESPONSE_REJECT);
1246 window.add_button (actions[1], RESPONSE_APPLY);
1247 window.add_button (actions[2], RESPONSE_ACCEPT);
1249 window.set_default_response (RESPONSE_ACCEPT);
1251 Gtk::Button noquit_button (msg);
1252 noquit_button.set_name ("EditorGTKButton");
1256 if (_session->snap_name() == _session->name()) {
1257 prompt = string_compose(_("The session \"%1\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1258 _session->snap_name());
1260 prompt = string_compose(_("The snapshot \"%1\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
1261 _session->snap_name());
1264 prompt_label.set_text (prompt);
1265 prompt_label.set_name (X_("PrompterLabel"));
1266 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1268 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1269 dhbox.set_homogeneous (false);
1270 dhbox.pack_start (*dimage, false, false, 5);
1271 dhbox.pack_start (prompt_label, true, false, 5);
1272 window.get_vbox()->pack_start (dhbox);
1274 window.set_name (_("Prompter"));
1275 window.set_modal (true);
1276 window.set_resizable (false);
1279 prompt_label.show();
1284 ResponseType r = (ResponseType) window.run();
1289 case RESPONSE_ACCEPT: // save and get out of here
1291 case RESPONSE_APPLY: // get out of here
1302 ARDOUR_UI::every_second ()
1305 update_xrun_count ();
1306 update_buffer_load ();
1307 update_disk_space ();
1308 update_timecode_format ();
1309 update_peak_thread_work ();
1311 if (nsm && nsm->is_active ()) {
1314 if (!_was_dirty && _session->dirty ()) {
1318 else if (_was_dirty && !_session->dirty ()){
1326 ARDOUR_UI::every_point_one_seconds ()
1328 // TODO get rid of this..
1329 // ShuttleControl is updated directly via TransportStateChange signal
1333 ARDOUR_UI::every_point_zero_something_seconds ()
1335 // august 2007: actual update frequency: 25Hz (40ms), not 100Hz
1337 if (editor_meter && UIConfiguration::instance().get_show_editor_meter()) {
1338 float mpeak = editor_meter->update_meters();
1339 if (mpeak > editor_meter_max_peak) {
1340 if (mpeak >= UIConfiguration::instance().get_meter_peak()) {
1341 editor_meter_peak_display.set_active_state ( Gtkmm2ext::ExplicitActive );
1348 ARDOUR_UI::set_fps_timeout_connection ()
1350 unsigned int interval = 40;
1351 if (!_session) return;
1352 if (_session->timecode_frames_per_second() != 0) {
1353 /* ideally we'll use a select() to sleep and not accumulate
1354 * idle time to provide a regular periodic signal.
1355 * See linux_vst_gui_support.cc 'elapsed_time_ms'.
1356 * However, that'll require a dedicated thread and cross-thread
1357 * signals to the GUI Thread..
1359 interval = floor(500. /* update twice per FPS, since Glib::signal_timeout is very irregular */
1360 * _session->frame_rate() / _session->nominal_frame_rate()
1361 / _session->timecode_frames_per_second()
1363 #ifdef PLATFORM_WINDOWS
1364 // the smallest windows scheduler time-slice is ~15ms.
1365 // periodic GUI timeouts shorter than that will cause
1366 // WaitForSingleObject to spinlock (100% of one CPU Core)
1367 // and gtk never enters idle mode.
1368 // also changing timeBeginPeriod(1) does not affect that in
1369 // any beneficial way, so we just limit the max rate for now.
1370 interval = std::max(30u, interval); // at most ~33Hz.
1372 interval = std::max(8u, interval); // at most 120Hz.
1375 fps_connection.disconnect();
1376 Timers::set_fps_interval (interval);
1380 ARDOUR_UI::update_sample_rate (framecnt_t)
1384 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
1386 if (!AudioEngine::instance()->connected()) {
1388 snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1392 framecnt_t rate = AudioEngine::instance()->sample_rate();
1395 /* no sample rate available */
1396 snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1399 if (fmod (rate, 1000.0) != 0.0) {
1400 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
1401 (float) rate / 1000.0f,
1402 (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1404 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
1406 (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1410 sample_rate_label.set_markup (buf);
1414 ARDOUR_UI::update_format ()
1417 format_label.set_text ("");
1422 s << _("File:") << X_(" <span foreground=\"green\">");
1424 switch (_session->config.get_native_file_header_format ()) {
1456 switch (_session->config.get_native_file_data_format ()) {
1470 format_label.set_markup (s.str ());
1474 ARDOUR_UI::update_xrun_count ()
1478 /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1479 should also be changed.
1483 const unsigned int x = _session->get_xrun_count ();
1485 snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">>10K</span>"), X_("red"));
1487 snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">%u</span>"), x > 0 ? X_("red") : X_("green"), x);
1490 snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">?</span>"), X_("yellow"));
1492 xrun_label.set_markup (buf);
1493 set_tip (xrun_label, _("Audio dropouts. Shift+click to reset"));
1497 ARDOUR_UI::update_cpu_load ()
1501 /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1502 should also be changed.
1505 double const c = AudioEngine::instance()->get_dsp_load ();
1506 snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c);
1507 cpu_load_label.set_markup (buf);
1511 ARDOUR_UI::update_peak_thread_work ()
1514 const int c = SourceFactory::peak_work_queue_length ();
1516 snprintf (buf, sizeof (buf), _("PkBld: <span foreground=\"%s\">%d</span>"), c >= 2 ? X_("red") : X_("green"), c);
1517 peak_thread_work_label.set_markup (buf);
1519 peak_thread_work_label.set_markup (X_(""));
1524 ARDOUR_UI::update_buffer_load ()
1528 uint32_t const playback = _session ? _session->playback_load () : 100;
1529 uint32_t const capture = _session ? _session->capture_load () : 100;
1531 /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1532 should also be changed.
1538 _("Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">%" PRIu32 "%%</span> "
1539 "<span foreground=\"green\">c:</span><span foreground=\"%s\">%" PRIu32 "%%</span>"),
1540 playback <= 5 ? X_("red") : X_("green"),
1542 capture <= 5 ? X_("red") : X_("green"),
1546 buffer_load_label.set_markup (buf);
1548 buffer_load_label.set_text ("");
1553 ARDOUR_UI::count_recenabled_streams (Route& route)
1555 Track* track = dynamic_cast<Track*>(&route);
1556 if (track && track->record_enabled()) {
1557 rec_enabled_streams += track->n_inputs().n_total();
1562 ARDOUR_UI::update_disk_space()
1564 if (_session == 0) {
1568 boost::optional<framecnt_t> opt_frames = _session->available_capture_duration();
1570 framecnt_t fr = _session->frame_rate();
1573 /* skip update - no SR available */
1578 /* Available space is unknown */
1579 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
1580 } else if (opt_frames.get_value_or (0) == max_framecnt) {
1581 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">24hrs+</span>"));
1583 rec_enabled_streams = 0;
1584 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
1586 framecnt_t frames = opt_frames.get_value_or (0);
1588 if (rec_enabled_streams) {
1589 frames /= rec_enabled_streams;
1596 hrs = frames / (fr * 3600);
1599 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">>24 hrs</span>"));
1601 frames -= hrs * fr * 3600;
1602 mins = frames / (fr * 60);
1603 frames -= mins * fr * 60;
1606 bool const low = (hrs == 0 && mins <= 30);
1610 _("Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"),
1611 low ? X_("red") : X_("green"),
1617 disk_space_label.set_markup (buf);
1621 ARDOUR_UI::update_timecode_format ()
1627 TimecodeSlave* tcslave;
1628 SyncSource sync_src = Config->get_sync_source();
1630 if ((sync_src == LTC || sync_src == MTC) && (tcslave = dynamic_cast<TimecodeSlave*>(_session->slave())) != 0) {
1631 matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format());
1636 snprintf (buf, sizeof (buf), S_("Timecode|TC: <span foreground=\"%s\">%s</span>"),
1637 matching ? X_("green") : X_("red"),
1638 Timecode::timecode_format_name (_session->config.get_timecode_format()).c_str());
1640 snprintf (buf, sizeof (buf), "TC: n/a");
1643 timecode_format_label.set_markup (buf);
1647 ARDOUR_UI::update_wall_clock ()
1651 static int last_min = -1;
1654 tm_now = localtime (&now);
1655 if (last_min != tm_now->tm_min) {
1657 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1658 wall_clock_label.set_text (buf);
1659 last_min = tm_now->tm_min;
1666 ARDOUR_UI::open_recent_session ()
1668 bool can_return = (_session != 0);
1670 SessionDialog recent_session_dialog;
1674 ResponseType r = (ResponseType) recent_session_dialog.run ();
1677 case RESPONSE_ACCEPT:
1681 recent_session_dialog.hide();
1688 recent_session_dialog.hide();
1692 std::string path = recent_session_dialog.session_folder();
1693 std::string state = recent_session_dialog.session_name (should_be_new);
1695 if (should_be_new == true) {
1699 _session_is_new = false;
1701 if (load_session (path, state) == 0) {
1710 ARDOUR_UI::check_audioengine (Gtk::Window& parent)
1712 if (!AudioEngine::instance()->connected()) {
1713 MessageDialog msg (parent, string_compose (
1714 _("%1 is not connected to any audio backend.\n"
1715 "You cannot open or close sessions in this condition"),
1717 pop_back_splash (msg);
1725 ARDOUR_UI::open_session ()
1727 if (!check_audioengine (_main_window)) {
1731 /* ardour sessions are folders */
1732 Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1733 open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1734 open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1735 open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1738 string session_parent_dir = Glib::path_get_dirname(_session->path());
1739 open_session_selector.set_current_folder(session_parent_dir);
1741 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1744 Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1746 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1747 string default_session_folder = Config->get_default_session_parent_dir();
1748 open_session_selector.add_shortcut_folder (default_session_folder);
1750 catch (Glib::Error & e) {
1751 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1754 FileFilter session_filter;
1755 session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1756 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1757 open_session_selector.add_filter (session_filter);
1758 open_session_selector.set_filter (session_filter);
1760 int response = open_session_selector.run();
1761 open_session_selector.hide ();
1763 if (response == Gtk::RESPONSE_CANCEL) {
1767 string session_path = open_session_selector.get_filename();
1771 if (session_path.length() > 0) {
1772 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1773 _session_is_new = isnew;
1774 load_session (path, name);
1781 ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& output, RouteGroup* route_group,
1782 uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
1784 list<boost::shared_ptr<MidiTrack> > tracks;
1786 if (_session == 0) {
1787 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1792 tracks = _session->new_midi_track (input, output, instrument, ARDOUR::Normal, route_group, how_many, name_template);
1794 if (tracks.size() != how_many) {
1795 error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
1800 MessageDialog msg (_main_window,
1801 string_compose (_("There are insufficient ports available\n\
1802 to create a new track or bus.\n\
1803 You should save %1, exit and\n\
1804 restart with more ports."), PROGRAM_NAME));
1810 ARDOUR_UI::session_add_midi_bus (RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
1813 if (_session == 0) {
1814 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1819 RouteList routes = _session->new_midi_route (route_group, how_many, name_template, instrument);
1820 if (routes.size() != how_many) {
1821 error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
1826 MessageDialog msg (_main_window,
1827 string_compose (_("There are insufficient ports available\n\
1828 to create a new track or bus.\n\
1829 You should save %1, exit and\n\
1830 restart with more ports."), PROGRAM_NAME));
1836 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
1838 ChanCount one_midi_channel;
1839 one_midi_channel.set (DataType::MIDI, 1);
1842 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, instrument);
1844 session_add_midi_bus (route_group, how_many, name_template, instrument);
1849 ARDOUR_UI::session_add_audio_route (
1851 int32_t input_channels,
1852 int32_t output_channels,
1853 ARDOUR::TrackMode mode,
1854 RouteGroup* route_group,
1856 string const & name_template
1859 list<boost::shared_ptr<AudioTrack> > tracks;
1862 if (_session == 0) {
1863 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1869 tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
1871 if (tracks.size() != how_many) {
1872 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
1878 routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
1880 if (routes.size() != how_many) {
1881 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
1888 MessageDialog msg (_main_window,
1889 string_compose (_("There are insufficient ports available\n\
1890 to create a new track or bus.\n\
1891 You should save %1, exit and\n\
1892 restart with more ports."), PROGRAM_NAME));
1893 pop_back_splash (msg);
1899 ARDOUR_UI::transport_goto_start ()
1902 _session->goto_start();
1904 /* force displayed area in editor to start no matter
1905 what "follow playhead" setting is.
1909 editor->center_screen (_session->current_start_frame ());
1915 ARDOUR_UI::transport_goto_zero ()
1918 _session->request_locate (0);
1920 /* force displayed area in editor to start no matter
1921 what "follow playhead" setting is.
1925 editor->reset_x_origin (0);
1931 ARDOUR_UI::transport_goto_wallclock ()
1933 if (_session && editor) {
1940 localtime_r (&now, &tmnow);
1942 framecnt_t frame_rate = _session->frame_rate();
1944 if (frame_rate == 0) {
1945 /* no frame rate available */
1949 frames = tmnow.tm_hour * (60 * 60 * frame_rate);
1950 frames += tmnow.tm_min * (60 * frame_rate);
1951 frames += tmnow.tm_sec * frame_rate;
1953 _session->request_locate (frames, _session->transport_rolling ());
1955 /* force displayed area in editor to start no matter
1956 what "follow playhead" setting is.
1960 editor->center_screen (frames);
1966 ARDOUR_UI::transport_goto_end ()
1969 framepos_t const frame = _session->current_end_frame();
1970 _session->request_locate (frame);
1972 /* force displayed area in editor to start no matter
1973 what "follow playhead" setting is.
1977 editor->center_screen (frame);
1983 ARDOUR_UI::transport_stop ()
1989 if (_session->is_auditioning()) {
1990 _session->cancel_audition ();
1994 _session->request_stop (false, true);
1997 /** Check if any tracks are record enabled. If none are, record enable all of them.
1998 * @return true if track record-enabled status was changed, false otherwise.
2001 ARDOUR_UI::trx_record_enable_all_tracks ()
2007 boost::shared_ptr<RouteList> rl = _session->get_tracks ();
2008 bool none_record_enabled = true;
2010 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2011 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
2014 if (t->record_enabled()) {
2015 none_record_enabled = false;
2020 if (none_record_enabled) {
2021 _session->set_record_enabled (rl, true, Session::rt_cleanup);
2024 return none_record_enabled;
2028 ARDOUR_UI::transport_record (bool roll)
2031 switch (_session->record_status()) {
2032 case Session::Disabled:
2033 if (_session->ntracks() == 0) {
2034 MessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu."));
2038 if (Profile->get_trx()) {
2039 roll = trx_record_enable_all_tracks ();
2041 _session->maybe_enable_record ();
2046 case Session::Recording:
2048 _session->request_stop();
2050 _session->disable_record (false, true);
2054 case Session::Enabled:
2055 _session->disable_record (false, true);
2061 ARDOUR_UI::transport_roll ()
2067 if (_session->is_auditioning()) {
2072 if (_session->config.get_external_sync()) {
2073 switch (Config->get_sync_source()) {
2077 /* transport controlled by the master */
2083 bool rolling = _session->transport_rolling();
2085 if (_session->get_play_loop()) {
2087 /* If loop playback is not a mode, then we should cancel
2088 it when this action is requested. If it is a mode
2089 we just leave it in place.
2092 if (!Config->get_loop_is_mode()) {
2093 /* XXX it is not possible to just leave seamless loop and keep
2094 playing at present (nov 4th 2009)
2096 if (!Config->get_seamless_loop()) {
2097 /* stop loop playback and stop rolling */
2098 _session->request_play_loop (false, true);
2099 } else if (rolling) {
2100 /* stop loop playback but keep rolling */
2101 _session->request_play_loop (false, false);
2105 } else if (_session->get_play_range () ) {
2106 /* stop playing a range if we currently are */
2107 _session->request_play_range (0, true);
2111 _session->request_transport_speed (1.0f);
2116 ARDOUR_UI::get_smart_mode() const
2118 return ( editor->get_smart_mode() );
2123 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2129 if (_session->is_auditioning()) {
2130 _session->cancel_audition ();
2134 if (_session->config.get_external_sync()) {
2135 switch (Config->get_sync_source()) {
2139 /* transport controlled by the master */
2144 bool rolling = _session->transport_rolling();
2145 bool affect_transport = true;
2147 if (rolling && roll_out_of_bounded_mode) {
2148 /* drop out of loop/range playback but leave transport rolling */
2149 if (_session->get_play_loop()) {
2150 if (_session->actively_recording()) {
2152 /* just stop using the loop, then actually stop
2155 _session->request_play_loop (false, affect_transport);
2158 if (Config->get_seamless_loop()) {
2159 /* the disk buffers contain copies of the loop - we can't
2160 just keep playing, so stop the transport. the user
2161 can restart as they wish.
2163 affect_transport = true;
2165 /* disk buffers are normal, so we can keep playing */
2166 affect_transport = false;
2168 _session->request_play_loop (false, affect_transport);
2170 } else if (_session->get_play_range ()) {
2171 affect_transport = false;
2172 _session->request_play_range (0, true);
2176 if (affect_transport) {
2178 _session->request_stop (with_abort, true);
2180 /* the only external sync condition we can be in here
2181 * would be Engine (JACK) sync, in which case we still
2185 if (UIConfiguration::instance().get_follow_edits() && ( editor->get_selection().time.front().start == _session->transport_frame() ) ) { //if playhead is exactly at the start of a range, we can assume it was placed there by follow_edits
2186 _session->request_play_range (&editor->get_selection().time, true);
2187 _session->set_requested_return_frame( editor->get_selection().time.front().start ); //force an auto-return here
2189 _session->request_transport_speed (1.0f);
2195 ARDOUR_UI::toggle_session_auto_loop ()
2201 Location * looploc = _session->locations()->auto_loop_location();
2207 if (_session->get_play_loop()) {
2209 /* looping enabled, our job is to disable it */
2211 _session->request_play_loop (false);
2215 /* looping not enabled, our job is to enable it.
2217 loop-is-NOT-mode: this action always starts the transport rolling.
2218 loop-IS-mode: this action simply sets the loop play mechanism, but
2219 does not start transport.
2221 if (Config->get_loop_is_mode()) {
2222 _session->request_play_loop (true, false);
2224 _session->request_play_loop (true, true);
2228 //show the loop markers
2229 looploc->set_hidden (false, this);
2233 ARDOUR_UI::transport_play_selection ()
2239 editor->play_selection ();
2243 ARDOUR_UI::transport_play_preroll ()
2248 editor->play_with_preroll ();
2252 ARDOUR_UI::transport_rewind (int option)
2254 float current_transport_speed;
2257 current_transport_speed = _session->transport_speed();
2259 if (current_transport_speed >= 0.0f) {
2262 _session->request_transport_speed (-1.0f);
2265 _session->request_transport_speed (-4.0f);
2268 _session->request_transport_speed (-0.5f);
2273 _session->request_transport_speed (current_transport_speed * 1.5f);
2279 ARDOUR_UI::transport_forward (int option)
2285 float current_transport_speed = _session->transport_speed();
2287 if (current_transport_speed <= 0.0f) {
2290 _session->request_transport_speed (1.0f);
2293 _session->request_transport_speed (4.0f);
2296 _session->request_transport_speed (0.5f);
2301 _session->request_transport_speed (current_transport_speed * 1.5f);
2306 ARDOUR_UI::toggle_record_enable (uint32_t rid)
2312 boost::shared_ptr<Route> r;
2314 if ((r = _session->route_by_remote_id (rid)) != 0) {
2316 boost::shared_ptr<Track> t;
2318 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2319 t->set_record_enabled (!t->record_enabled(), Controllable::UseGroup);
2325 ARDOUR_UI::map_transport_state ()
2328 auto_loop_button.unset_active_state ();
2329 play_selection_button.unset_active_state ();
2330 roll_button.unset_active_state ();
2331 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2335 shuttle_box->map_transport_state ();
2337 float sp = _session->transport_speed();
2343 if (_session->get_play_range()) {
2345 play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2346 roll_button.unset_active_state ();
2347 auto_loop_button.unset_active_state ();
2349 } else if (_session->get_play_loop ()) {
2351 auto_loop_button.set_active (true);
2352 play_selection_button.set_active (false);
2353 if (Config->get_loop_is_mode()) {
2354 roll_button.set_active (true);
2356 roll_button.set_active (false);
2361 roll_button.set_active (true);
2362 play_selection_button.set_active (false);
2363 auto_loop_button.set_active (false);
2366 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2367 /* light up both roll and play-selection if they are joined */
2368 roll_button.set_active (true);
2369 play_selection_button.set_active (true);
2372 stop_button.set_active (false);
2376 stop_button.set_active (true);
2377 roll_button.set_active (false);
2378 play_selection_button.set_active (false);
2379 if (Config->get_loop_is_mode ()) {
2380 auto_loop_button.set_active (_session->get_play_loop());
2382 auto_loop_button.set_active (false);
2384 update_disk_space ();
2389 ARDOUR_UI::blink_handler (bool blink_on)
2391 transport_rec_enable_blink (blink_on);
2392 solo_blink (blink_on);
2393 sync_blink (blink_on);
2394 audition_blink (blink_on);
2395 feedback_blink (blink_on);
2396 error_blink (blink_on);
2400 ARDOUR_UI::update_clocks ()
2402 if (!_session) return;
2404 if (editor && !editor->dragging_playhead()) {
2405 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2410 ARDOUR_UI::start_clocking ()
2412 if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2413 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2415 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2420 ARDOUR_UI::stop_clocking ()
2422 clock_signal_connection.disconnect ();
2426 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2430 snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2432 label->set_text (buf);
2433 bar->set_fraction (fraction);
2435 /* process events, redraws, etc. */
2437 while (gtk_events_pending()) {
2438 gtk_main_iteration ();
2441 return true; /* continue with save-as */
2445 ARDOUR_UI::save_session_as ()
2451 if (!save_as_dialog) {
2452 save_as_dialog = new SaveAsDialog;
2455 save_as_dialog->set_name (_session->name());
2457 int response = save_as_dialog->run ();
2459 save_as_dialog->hide ();
2462 case Gtk::RESPONSE_OK:
2471 sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2472 sa.new_name = save_as_dialog->new_name ();
2473 sa.switch_to = save_as_dialog->switch_to();
2474 sa.copy_media = save_as_dialog->copy_media();
2475 sa.copy_external = save_as_dialog->copy_external();
2476 sa.include_media = save_as_dialog->include_media ();
2478 /* Only bother with a progress dialog if we're going to copy
2479 media into the save-as target. Without that choice, this
2480 will be very fast because we're only talking about a few kB's to
2481 perhaps a couple of MB's of data.
2484 ArdourDialog progress_dialog (_("Save As"), true);
2486 if (sa.include_media && sa.copy_media) {
2489 Gtk::ProgressBar progress_bar;
2491 progress_dialog.get_vbox()->pack_start (label);
2492 progress_dialog.get_vbox()->pack_start (progress_bar);
2494 progress_bar.show ();
2496 /* this signal will be emitted from within this, the calling thread,
2497 * after every file is copied. It provides information on percentage
2498 * complete (in terms of total data to copy), the number of files
2499 * copied so far, and the total number to copy.
2504 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
2506 progress_dialog.show_all ();
2507 progress_dialog.present ();
2510 if (_session->save_as (sa)) {
2512 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2516 if (!sa.include_media) {
2517 unload_session (false);
2518 load_session (sa.final_session_folder_name, sa.new_name);
2523 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2527 struct tm local_time;
2530 localtime_r (&n, &local_time);
2531 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2533 save_state (timebuf, switch_to_it);
2538 ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
2542 prompter.get_result (snapname);
2544 bool do_save = (snapname.length() != 0);
2547 char illegal = Session::session_name_is_legal(snapname);
2549 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2550 "snapshot names may not contain a '%1' character"), illegal));
2556 vector<std::string> p;
2557 get_state_files_in_directory (_session->session_directory().root_path(), p);
2558 vector<string> n = get_file_names_no_extension (p);
2560 if (find (n.begin(), n.end(), snapname) != n.end()) {
2562 do_save = overwrite_file_dialog (prompter,
2563 _("Confirm Snapshot Overwrite"),
2564 _("A snapshot already exists with that name. Do you want to overwrite it?"));
2568 save_state (snapname, switch_to_it);
2578 /** Ask the user for the name of a new snapshot and then take it.
2582 ARDOUR_UI::snapshot_session (bool switch_to_it)
2584 ArdourPrompter prompter (true);
2586 prompter.set_name ("Prompter");
2587 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2589 prompter.set_title (_("Save as..."));
2590 prompter.set_prompt (_("New session name"));
2592 prompter.set_title (_("Take Snapshot"));
2593 prompter.set_prompt (_("Name of new snapshot"));
2597 prompter.set_initial_text (_session->snap_name());
2601 struct tm local_time;
2604 localtime_r (&n, &local_time);
2605 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2606 prompter.set_initial_text (timebuf);
2609 bool finished = false;
2611 switch (prompter.run()) {
2612 case RESPONSE_ACCEPT:
2614 finished = process_snapshot_session_prompter (prompter, switch_to_it);
2625 /** Ask the user for a new session name and then rename the session to it.
2629 ARDOUR_UI::rename_session ()
2635 ArdourPrompter prompter (true);
2638 prompter.set_name ("Prompter");
2639 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2640 prompter.set_title (_("Rename Session"));
2641 prompter.set_prompt (_("New session name"));
2644 switch (prompter.run()) {
2645 case RESPONSE_ACCEPT:
2647 prompter.get_result (name);
2649 bool do_rename = (name.length() != 0);
2652 char illegal = Session::session_name_is_legal (name);
2655 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2656 "session names may not contain a '%1' character"), illegal));
2661 switch (_session->rename (name)) {
2663 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2664 msg.set_position (WIN_POS_MOUSE);
2672 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2673 msg.set_position (WIN_POS_MOUSE);
2689 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2691 if (!_session || _session->deletion_in_progress()) {
2695 XMLNode* node = new XMLNode (X_("UI"));
2697 WM::Manager::instance().add_state (*node);
2699 node->add_child_nocopy (gui_object_state->get_state());
2701 _session->add_extra_xml (*node);
2703 if (export_video_dialog) {
2704 _session->add_extra_xml (export_video_dialog->get_state());
2707 save_state_canfail (name, switch_to_it);
2711 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2716 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2721 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2726 ARDOUR_UI::primary_clock_value_changed ()
2729 _session->request_locate (primary_clock->current_time ());
2734 ARDOUR_UI::big_clock_value_changed ()
2737 _session->request_locate (big_clock->current_time ());
2742 ARDOUR_UI::secondary_clock_value_changed ()
2745 _session->request_locate (secondary_clock->current_time ());
2750 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2752 if (_session == 0) {
2756 if (_session->step_editing()) {
2760 Session::RecordState const r = _session->record_status ();
2761 bool const h = _session->have_rec_enabled_track ();
2763 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2765 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2767 rec_button.set_active_state (Gtkmm2ext::Off);
2769 } else if (r == Session::Recording && h) {
2770 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2772 rec_button.unset_active_state ();
2777 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2781 prompter.get_result (name);
2783 if (name.length()) {
2784 int failed = _session->save_template (name);
2786 if (failed == -2) { /* file already exists. */
2787 bool overwrite = overwrite_file_dialog (prompter,
2788 _("Confirm Template Overwrite"),
2789 _("A template already exists with that name. Do you want to overwrite it?"));
2792 _session->save_template (name, true);
2804 ARDOUR_UI::save_template ()
2806 ArdourPrompter prompter (true);
2808 if (!check_audioengine (_main_window)) {
2812 prompter.set_name (X_("Prompter"));
2813 prompter.set_title (_("Save Template"));
2814 prompter.set_prompt (_("Name for template:"));
2815 prompter.set_initial_text(_session->name() + _("-template"));
2816 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2818 bool finished = false;
2820 switch (prompter.run()) {
2821 case RESPONSE_ACCEPT:
2822 finished = process_save_template_prompter (prompter);
2833 ARDOUR_UI::edit_metadata ()
2835 SessionMetadataEditor dialog;
2836 dialog.set_session (_session);
2837 dialog.grab_focus ();
2842 ARDOUR_UI::import_metadata ()
2844 SessionMetadataImporter dialog;
2845 dialog.set_session (_session);
2850 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2852 std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2854 MessageDialog msg (str,
2856 Gtk::MESSAGE_WARNING,
2857 Gtk::BUTTONS_YES_NO,
2861 msg.set_name (X_("OpenExistingDialog"));
2862 msg.set_title (_("Open Existing Session"));
2863 msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2864 msg.set_position (Gtk::WIN_POS_CENTER);
2865 pop_back_splash (msg);
2867 switch (msg.run()) {
2876 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
2878 BusProfile bus_profile;
2882 bus_profile.master_out_channels = 2;
2883 bus_profile.input_ac = AutoConnectPhysical;
2884 bus_profile.output_ac = AutoConnectMaster;
2885 bus_profile.requested_physical_in = 0; // use all available
2886 bus_profile.requested_physical_out = 0; // use all available
2890 /* get settings from advanced section of NSD */
2892 if (sd.create_master_bus()) {
2893 bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
2895 bus_profile.master_out_channels = 0;
2898 if (sd.connect_inputs()) {
2899 bus_profile.input_ac = AutoConnectPhysical;
2901 bus_profile.input_ac = AutoConnectOption (0);
2904 bus_profile.output_ac = AutoConnectOption (0);
2906 if (sd.connect_outputs ()) {
2907 if (sd.connect_outs_to_master()) {
2908 bus_profile.output_ac = AutoConnectMaster;
2909 } else if (sd.connect_outs_to_physical()) {
2910 bus_profile.output_ac = AutoConnectPhysical;
2914 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
2915 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
2918 if (build_session (session_path, session_name, bus_profile)) {
2926 ARDOUR_UI::load_from_application_api (const std::string& path)
2928 ARDOUR_COMMAND_LINE::session_name = path;
2929 /* Cancel SessionDialog if it's visible to make OSX delegates work.
2931 * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
2933 * - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
2934 * -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
2935 * - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
2936 * -> SessionDialog is not displayed
2939 if (_session_dialog) {
2940 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
2941 std::string session_path = path;
2942 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
2943 session_path = Glib::path_get_dirname (session_path);
2945 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
2946 _session_dialog->set_provided_session (session_name, session_path);
2947 _session_dialog->response (RESPONSE_NONE);
2948 _session_dialog->hide();
2953 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2954 /* /path/to/foo => /path/to/foo, foo */
2955 rv = load_session (path, basename_nosuffix (path));
2957 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2958 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2961 // if load_session fails -> pop up SessionDialog.
2963 ARDOUR_COMMAND_LINE::session_name = "";
2965 if (get_session_parameters (true, false)) {
2971 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2973 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2975 string session_name;
2976 string session_path;
2977 string template_name;
2979 bool likely_new = false;
2980 bool cancel_not_quit;
2982 /* deal with any existing DIRTY session now, rather than later. don't
2983 * treat a non-dirty session this way, so that it stays visible
2984 * as we bring up the new session dialog.
2987 if (_session && ARDOUR_UI::instance()->video_timeline) {
2988 ARDOUR_UI::instance()->video_timeline->sync_session_state();
2991 /* if there is already a session, relabel the button
2992 on the SessionDialog so that we don't Quit directly
2994 cancel_not_quit = (_session != 0);
2996 if (_session && _session->dirty()) {
2997 if (unload_session (false)) {
2998 /* unload cancelled by user */
3001 ARDOUR_COMMAND_LINE::session_name = "";
3004 if (!load_template.empty()) {
3005 should_be_new = true;
3006 template_name = load_template;
3009 session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3010 session_path = ARDOUR_COMMAND_LINE::session_name;
3012 if (!session_path.empty()) {
3013 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3014 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3015 /* session/snapshot file, change path to be dir */
3016 session_path = Glib::path_get_dirname (session_path);
3021 SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3023 _session_dialog = &session_dialog;
3026 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3028 /* if they named a specific statefile, use it, otherwise they are
3029 just giving a session folder, and we want to use it as is
3030 to find the session.
3033 string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3035 if (suffix != string::npos) {
3036 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3037 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3038 session_name = Glib::path_get_basename (session_name);
3040 session_path = ARDOUR_COMMAND_LINE::session_name;
3041 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3046 session_dialog.clear_given ();
3049 if (should_be_new || session_name.empty()) {
3050 /* need the dialog to get info from user */
3052 cerr << "run dialog\n";
3054 switch (session_dialog.run()) {
3055 case RESPONSE_ACCEPT:
3058 /* this is used for async * app->ShouldLoad(). */
3059 continue; // while loop
3062 if (quit_on_cancel) {
3063 // JE - Currently (July 2014) this section can only get reached if the
3064 // user quits from the main 'Session Setup' dialog (i.e. reaching this
3065 // point does NOT indicate an abnormal termination). Therefore, let's
3066 // behave gracefully (i.e. let's do some cleanup) before we call exit()
3068 pthread_cancel_all ();
3076 session_dialog.hide ();
3079 /* if we run the startup dialog again, offer more than just "new session" */
3081 should_be_new = false;
3083 session_name = session_dialog.session_name (likely_new);
3084 session_path = session_dialog.session_folder ();
3090 string::size_type suffix = session_name.find (statefile_suffix);
3092 if (suffix != string::npos) {
3093 session_name = session_name.substr (0, suffix);
3096 /* this shouldn't happen, but we catch it just in case it does */
3098 if (session_name.empty()) {
3102 if (session_dialog.use_session_template()) {
3103 template_name = session_dialog.session_template_name();
3104 _session_is_new = true;
3107 if (session_name[0] == G_DIR_SEPARATOR ||
3108 #ifdef PLATFORM_WINDOWS
3109 (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3111 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3112 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3117 /* absolute path or cwd-relative path specified for session name: infer session folder
3118 from what was given.
3121 session_path = Glib::path_get_dirname (session_name);
3122 session_name = Glib::path_get_basename (session_name);
3126 session_path = session_dialog.session_folder();
3128 char illegal = Session::session_name_is_legal (session_name);
3131 MessageDialog msg (session_dialog,
3132 string_compose (_("To ensure compatibility with various systems\n"
3133 "session names may not contain a '%1' character"),
3136 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3141 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3144 if (likely_new && !nsm) {
3146 std::string existing = Glib::build_filename (session_path, session_name);
3148 if (!ask_about_loading_existing_session (existing)) {
3149 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3154 _session_is_new = false;
3159 pop_back_splash (session_dialog);
3160 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3162 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3166 char illegal = Session::session_name_is_legal(session_name);
3169 pop_back_splash (session_dialog);
3170 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3171 "session names may not contain a '%1' character"), illegal));
3173 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3177 _session_is_new = true;
3180 if (likely_new && template_name.empty()) {
3182 ret = build_session_from_dialog (session_dialog, session_path, session_name);
3186 ret = load_session (session_path, session_name, template_name);
3189 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3193 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3194 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3198 /* clear this to avoid endless attempts to load the
3202 ARDOUR_COMMAND_LINE::session_name = "";
3206 _session_dialog = NULL;
3212 ARDOUR_UI::close_session()
3214 if (!check_audioengine (_main_window)) {
3218 if (unload_session (true)) {
3222 ARDOUR_COMMAND_LINE::session_name = "";
3224 if (get_session_parameters (true, false)) {
3229 /** @param snap_name Snapshot name (without .ardour suffix).
3230 * @return -2 if the load failed because we are not connected to the AudioEngine.
3233 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3235 Session *new_session;
3240 unload_status = unload_session ();
3242 if (unload_status < 0) {
3244 } else if (unload_status > 0) {
3250 session_loaded = false;
3252 loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3255 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3258 /* this one is special */
3260 catch (AudioEngine::PortRegistrationFailure& err) {
3262 MessageDialog msg (err.what(),
3265 Gtk::BUTTONS_CLOSE);
3267 msg.set_title (_("Port Registration Error"));
3268 msg.set_secondary_text (_("Click the Close button to try again."));
3269 msg.set_position (Gtk::WIN_POS_CENTER);
3270 pop_back_splash (msg);
3273 int response = msg.run ();
3278 case RESPONSE_CANCEL:
3285 catch (SessionException e) {
3286 MessageDialog msg (string_compose(
3287 _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3288 path, snap_name, e.what()),
3293 msg.set_title (_("Loading Error"));
3294 msg.set_position (Gtk::WIN_POS_CENTER);
3295 pop_back_splash (msg);
3307 MessageDialog msg (string_compose(
3308 _("Session \"%1 (snapshot %2)\" did not load successfully"),
3314 msg.set_title (_("Loading Error"));
3315 msg.set_position (Gtk::WIN_POS_CENTER);
3316 pop_back_splash (msg);
3328 list<string> const u = new_session->unknown_processors ();
3330 MissingPluginDialog d (_session, u);
3335 if (!new_session->writable()) {
3336 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3341 msg.set_title (_("Read-only Session"));
3342 msg.set_position (Gtk::WIN_POS_CENTER);
3343 pop_back_splash (msg);
3350 /* Now the session been created, add the transport controls */
3351 new_session->add_controllable(roll_controllable);
3352 new_session->add_controllable(stop_controllable);
3353 new_session->add_controllable(goto_start_controllable);
3354 new_session->add_controllable(goto_end_controllable);
3355 new_session->add_controllable(auto_loop_controllable);
3356 new_session->add_controllable(play_selection_controllable);
3357 new_session->add_controllable(rec_controllable);
3359 set_session (new_session);
3361 session_loaded = true;
3364 _session->set_clean ();
3367 #ifdef WINDOWS_VST_SUPPORT
3368 fst_stop_threading();
3372 Timers::TimerSuspender t;
3376 #ifdef WINDOWS_VST_SUPPORT
3377 fst_start_threading();
3386 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3388 Session *new_session;
3391 session_loaded = false;
3392 x = unload_session ();
3400 _session_is_new = true;
3403 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3406 catch (SessionException e) {
3408 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3409 msg.set_title (_("Loading Error"));
3410 msg.set_position (Gtk::WIN_POS_CENTER);
3411 pop_back_splash (msg);
3417 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3418 msg.set_title (_("Loading Error"));
3419 msg.set_position (Gtk::WIN_POS_CENTER);
3420 pop_back_splash (msg);
3425 /* Give the new session the default GUI state, if such things exist */
3428 n = Config->instant_xml (X_("Editor"));
3430 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3431 new_session->add_instant_xml (*n, false);
3433 n = Config->instant_xml (X_("Mixer"));
3435 new_session->add_instant_xml (*n, false);
3438 /* Put the playhead at 0 and scroll fully left */
3439 n = new_session->instant_xml (X_("Editor"));
3441 n->add_property (X_("playhead"), X_("0"));
3442 n->add_property (X_("left-frame"), X_("0"));
3445 set_session (new_session);
3447 session_loaded = true;
3449 new_session->save_state(new_session->name());
3455 ARDOUR_UI::launch_chat ()
3457 MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3459 dialog.set_title (_("About the Chat"));
3460 dialog.set_secondary_text (_("When you're inside the chat just ask your question and wait for an answer. The chat is occupied by real people with real lives so many of them are passively online and might not read your question before minutes or hours later.\nSo please be patient and wait for an answer.\n\nYou should just leave the chat window open and check back regularly until someone has answered your question."));
3462 switch (dialog.run()) {
3465 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3466 #elif defined PLATFORM_WINDOWS
3467 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3469 open_uri("http://webchat.freenode.net/?channels=ardour");
3478 ARDOUR_UI::launch_manual ()
3480 PBD::open_uri (Config->get_tutorial_manual_url());
3484 ARDOUR_UI::launch_reference ()
3486 PBD::open_uri (Config->get_reference_manual_url());
3490 ARDOUR_UI::launch_tracker ()
3492 PBD::open_uri ("http://tracker.ardour.org");
3496 ARDOUR_UI::launch_subscribe ()
3498 PBD::open_uri ("https://community.ardour.org/s/subscribe");
3502 ARDOUR_UI::launch_cheat_sheet ()
3505 PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3507 PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3512 ARDOUR_UI::launch_website ()
3514 PBD::open_uri ("http://ardour.org");
3518 ARDOUR_UI::launch_website_dev ()
3520 PBD::open_uri ("http://ardour.org/development.html");
3524 ARDOUR_UI::launch_forums ()
3526 PBD::open_uri ("https://community.ardour.org/forums");
3530 ARDOUR_UI::launch_howto_report ()
3532 PBD::open_uri ("http://ardour.org/reporting_bugs");
3536 ARDOUR_UI::loading_message (const std::string& msg)
3538 if (ARDOUR_COMMAND_LINE::no_splash) {
3546 splash->message (msg);
3550 ARDOUR_UI::show_splash ()
3554 splash = new Splash;
3564 ARDOUR_UI::hide_splash ()
3571 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3575 removed = rep.paths.size();
3578 MessageDialog msgd (_main_window,
3579 _("No files were ready for clean-up"),
3583 msgd.set_title (_("Clean-up"));
3584 msgd.set_secondary_text (_("If this seems suprising, \n\
3585 check for any existing snapshots.\n\
3586 These may still include regions that\n\
3587 require some unused files to continue to exist."));
3593 ArdourDialog results (_("Clean-up"), true, false);
3595 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3596 CleanupResultsModelColumns() {
3600 Gtk::TreeModelColumn<std::string> visible_name;
3601 Gtk::TreeModelColumn<std::string> fullpath;
3605 CleanupResultsModelColumns results_columns;
3606 Glib::RefPtr<Gtk::ListStore> results_model;
3607 Gtk::TreeView results_display;
3609 results_model = ListStore::create (results_columns);
3610 results_display.set_model (results_model);
3611 results_display.append_column (list_title, results_columns.visible_name);
3613 results_display.set_name ("CleanupResultsList");
3614 results_display.set_headers_visible (true);
3615 results_display.set_headers_clickable (false);
3616 results_display.set_reorderable (false);
3618 Gtk::ScrolledWindow list_scroller;
3621 Gtk::HBox dhbox; // the hbox for the image and text
3622 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3623 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
3625 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3627 const string dead_directory = _session->session_directory().dead_path();
3630 %1 - number of files removed
3631 %2 - location of "dead"
3632 %3 - size of files affected
3633 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3636 const char* bprefix;
3637 double space_adjusted = 0;
3639 if (rep.space < 1000) {
3641 space_adjusted = rep.space;
3642 } else if (rep.space < 1000000) {
3643 bprefix = _("kilo");
3644 space_adjusted = floorf((float)rep.space / 1000.0);
3645 } else if (rep.space < 1000000 * 1000) {
3646 bprefix = _("mega");
3647 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3649 bprefix = _("giga");
3650 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3654 txt.set_markup (string_compose (P_("\
3655 The following file was deleted from %2,\n\
3656 releasing %3 %4bytes of disk space", "\
3657 The following %1 files were deleted from %2,\n\
3658 releasing %3 %4bytes of disk space", removed),
3659 removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3661 txt.set_markup (string_compose (P_("\
3662 The following file was not in use and \n\
3663 has been moved to: %2\n\n\
3664 After a restart of %5\n\n\
3665 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3666 will release an additional %3 %4bytes of disk space.\n", "\
3667 The following %1 files were not in use and \n\
3668 have been moved to: %2\n\n\
3669 After a restart of %5\n\n\
3670 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3671 will release an additional %3 %4bytes of disk space.\n", removed),
3672 removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3675 dhbox.pack_start (*dimage, true, false, 5);
3676 dhbox.pack_start (txt, true, false, 5);
3678 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3679 TreeModel::Row row = *(results_model->append());
3680 row[results_columns.visible_name] = *i;
3681 row[results_columns.fullpath] = *i;
3684 list_scroller.add (results_display);
3685 list_scroller.set_size_request (-1, 150);
3686 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3688 dvbox.pack_start (dhbox, true, false, 5);
3689 dvbox.pack_start (list_scroller, true, false, 5);
3690 ddhbox.pack_start (dvbox, true, false, 5);
3692 results.get_vbox()->pack_start (ddhbox, true, false, 5);
3693 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3694 results.set_default_response (RESPONSE_CLOSE);
3695 results.set_position (Gtk::WIN_POS_MOUSE);
3697 results_display.show();
3698 list_scroller.show();
3705 //results.get_vbox()->show();
3706 results.set_resizable (false);
3713 ARDOUR_UI::cleanup ()
3715 if (_session == 0) {
3716 /* shouldn't happen: menu item is insensitive */
3721 MessageDialog checker (_("Are you sure you want to clean-up?"),
3723 Gtk::MESSAGE_QUESTION,
3726 checker.set_title (_("Clean-up"));
3728 checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3729 ALL undo/redo information will be lost if you clean-up.\n\
3730 Clean-up will move all unused files to a \"dead\" location."));
3732 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3733 checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3734 checker.set_default_response (RESPONSE_CANCEL);
3736 checker.set_name (_("CleanupDialog"));
3737 checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3738 checker.set_position (Gtk::WIN_POS_MOUSE);
3740 switch (checker.run()) {
3741 case RESPONSE_ACCEPT:
3747 ARDOUR::CleanupReport rep;
3749 editor->prepare_for_cleanup ();
3751 /* do not allow flush until a session is reloaded */
3753 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3755 act->set_sensitive (false);
3758 if (_session->cleanup_sources (rep)) {
3759 editor->finish_cleanup ();
3763 editor->finish_cleanup ();
3766 display_cleanup_results (rep, _("Cleaned Files"), false);
3770 ARDOUR_UI::flush_trash ()
3772 if (_session == 0) {
3773 /* shouldn't happen: menu item is insensitive */
3777 ARDOUR::CleanupReport rep;
3779 if (_session->cleanup_trash_sources (rep)) {
3783 display_cleanup_results (rep, _("deleted file"), true);
3787 ARDOUR_UI::cleanup_peakfiles ()
3789 if (_session == 0) {
3790 /* shouldn't happen: menu item is insensitive */
3794 if (! _session->can_cleanup_peakfiles ()) {
3798 // get all region-views in this session
3800 TrackViewList empty;
3802 editor->get_regions_after(rs, (framepos_t) 0, empty);
3803 std::list<RegionView*> views = rs.by_layer();
3805 // remove displayed audio-region-views waveforms
3806 for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3807 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3808 if (!arv) { continue ; }
3809 arv->delete_waves();
3812 // cleanup peak files:
3813 // - stop pending peakfile threads
3814 // - close peakfiles if any
3815 // - remove peak dir in session
3816 // - setup peakfiles (background thread)
3817 _session->cleanup_peakfiles ();
3819 // re-add waves to ARV
3820 for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3821 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3822 if (!arv) { continue ; }
3823 arv->create_waves();
3828 ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
3830 uint32_t order_hint = UINT32_MAX;
3832 if (editor->get_selection().tracks.empty()) {
3837 we want the new routes to have their order keys set starting from
3838 the highest order key in the selection + 1 (if available).
3841 if (place == AddRouteDialog::AfterSelection) {
3842 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
3844 order_hint = rtav->route()->order_key();
3847 } else if (place == AddRouteDialog::BeforeSelection) {
3848 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
3850 order_hint = rtav->route()->order_key();
3852 } else if (place == AddRouteDialog::First) {
3855 /* leave order_hint at UINT32_MAX */
3858 if (order_hint == UINT32_MAX) {
3859 /** AddRouteDialog::Last or selection with first/last not a RouteTimeAxisView
3860 * not setting an order hint will place new routes last.
3865 _session->set_order_hint (order_hint);
3867 /* create a gap in the existing route order keys to accomodate new routes.*/
3868 boost::shared_ptr <RouteList> rd = _session->get_routes();
3869 for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
3870 boost::shared_ptr<Route> rt (*ri);
3872 if (rt->is_monitor()) {
3876 if (rt->order_key () >= order_hint) {
3877 rt->set_order_key (rt->order_key () + add_route_dialog->count());
3883 ARDOUR_UI::start_duplicate_routes ()
3885 if (!duplicate_routes_dialog) {
3886 duplicate_routes_dialog = new DuplicateRouteDialog;
3889 if (duplicate_routes_dialog->restart (_session)) {
3893 duplicate_routes_dialog->present ();
3897 ARDOUR_UI::add_route (Gtk::Window* /* ignored */)
3905 if (add_route_dialog->is_visible()) {
3906 /* we're already doing this */
3910 ResponseType r = (ResponseType) add_route_dialog->run ();
3912 add_route_dialog->hide();
3915 case RESPONSE_ACCEPT:
3922 if ((count = add_route_dialog->count()) <= 0) {
3926 setup_order_hint(add_route_dialog->insert_at());
3928 string template_path = add_route_dialog->track_template();
3929 DisplaySuspender ds;
3931 if (!template_path.empty()) {
3932 if (add_route_dialog->name_template_is_default()) {
3933 _session->new_route_from_template (count, template_path, string());
3935 _session->new_route_from_template (count, template_path, add_route_dialog->name_template());
3940 ChanCount input_chan= add_route_dialog->channels ();
3941 ChanCount output_chan;
3942 string name_template = add_route_dialog->name_template ();
3943 PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
3944 RouteGroup* route_group = add_route_dialog->route_group ();
3945 AutoConnectOption oac = Config->get_output_auto_connect();
3947 if (oac & AutoConnectMaster) {
3948 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
3949 output_chan.set (DataType::MIDI, 0);
3951 output_chan = input_chan;
3954 /* XXX do something with name template */
3956 switch (add_route_dialog->type_wanted()) {
3957 case AddRouteDialog::AudioTrack:
3958 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template);
3960 case AddRouteDialog::MidiTrack:
3961 session_add_midi_track (route_group, count, name_template, instrument);
3963 case AddRouteDialog::MixedTrack:
3964 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, instrument);
3966 case AddRouteDialog::AudioBus:
3967 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template);
3969 case AddRouteDialog::MidiBus:
3970 session_add_midi_bus (route_group, count, name_template, instrument);
3976 ARDOUR_UI::add_lua_script ()
3982 LuaScriptInfoPtr spi;
3983 ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
3984 switch (ss.run ()) {
3985 case Gtk::RESPONSE_ACCEPT:
3993 std::string script = "";
3996 script = Glib::file_get_contents (spi->path);
3997 } catch (Glib::FileError e) {
3998 string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
3999 MessageDialog am (msg);
4004 LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
4005 std::vector<std::string> reg = _session->registered_lua_functions ();
4007 ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
4008 switch (spd.run ()) {
4009 case Gtk::RESPONSE_ACCEPT:
4016 _session->register_lua_function (spd.name(), script, lsp);
4017 } catch (luabridge::LuaException const& e) {
4018 string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
4019 MessageDialog am (msg);
4021 } catch (SessionException e) {
4022 string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
4023 MessageDialog am (msg);
4029 ARDOUR_UI::remove_lua_script ()
4034 if (_session->registered_lua_function_count () == 0) {
4035 string msg = _("There are no active Lua session scripts present in this session.");
4036 MessageDialog am (msg);
4041 std::vector<std::string> reg = _session->registered_lua_functions ();
4042 SessionScriptManager sm ("Remove Lua Session Script", reg);
4043 switch (sm.run ()) {
4044 case Gtk::RESPONSE_ACCEPT:
4050 _session->unregister_lua_function (sm.name());
4051 } catch (luabridge::LuaException const& e) {
4052 string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
4053 MessageDialog am (msg);
4059 ARDOUR_UI::stop_video_server (bool ask_confirm)
4061 if (!video_server_process && ask_confirm) {
4062 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4064 if (video_server_process) {
4066 ArdourDialog confirm (_("Stop Video-Server"), true);
4067 Label m (_("Do you really want to stop the Video Server?"));
4068 confirm.get_vbox()->pack_start (m, true, true);
4069 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4070 confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4071 confirm.show_all ();
4072 if (confirm.run() == RESPONSE_CANCEL) {
4076 delete video_server_process;
4077 video_server_process =0;
4082 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4084 ARDOUR_UI::start_video_server( float_window, true);
4088 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4094 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4095 if (video_server_process) {
4096 popup_error(_("The Video Server is already started."));
4098 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4104 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4106 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4108 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4110 video_server_dialog->set_transient_for (*float_window);
4113 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4114 video_server_dialog->hide();
4116 ResponseType r = (ResponseType) video_server_dialog->run ();
4117 video_server_dialog->hide();
4118 if (r != RESPONSE_ACCEPT) { return false; }
4119 if (video_server_dialog->show_again()) {
4120 Config->set_show_video_server_dialog(false);
4124 std::string icsd_exec = video_server_dialog->get_exec_path();
4125 std::string icsd_docroot = video_server_dialog->get_docroot();
4126 if (icsd_docroot.empty()) {
4127 #ifndef PLATFORM_WINDOWS
4128 icsd_docroot = X_("/");
4130 icsd_docroot = X_("C:\\");
4135 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4136 warning << _("Specified docroot is not an existing directory.") << endmsg;
4139 #ifndef PLATFORM_WINDOWS
4140 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4141 || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4142 warning << _("Given Video Server is not an executable file.") << endmsg;
4146 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4147 || (sb.st_mode & (S_IXUSR)) == 0 ) {
4148 warning << _("Given Video Server is not an executable file.") << endmsg;
4154 argp=(char**) calloc(9,sizeof(char*));
4155 argp[0] = strdup(icsd_exec.c_str());
4156 argp[1] = strdup("-P");
4157 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4158 argp[3] = strdup("-p");
4159 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4160 argp[5] = strdup("-C");
4161 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4162 argp[7] = strdup(icsd_docroot.c_str());
4164 stop_video_server();
4166 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4167 Config->set_video_advanced_setup(false);
4169 std::ostringstream osstream;
4170 osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4171 Config->set_video_server_url(osstream.str());
4172 Config->set_video_server_docroot(icsd_docroot);
4173 Config->set_video_advanced_setup(true);
4176 if (video_server_process) {
4177 delete video_server_process;
4180 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4181 if (video_server_process->start()) {
4182 warning << _("Cannot launch the video-server") << endmsg;
4185 int timeout = 120; // 6 sec
4186 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4187 Glib::usleep (50000);
4189 if (--timeout <= 0 || !video_server_process->is_running()) break;
4192 warning << _("Video-server was started but does not respond to requests...") << endmsg;
4194 if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4195 delete video_server_process;
4196 video_server_process = 0;
4204 ARDOUR_UI::add_video (Gtk::Window* float_window)
4210 if (!start_video_server(float_window, false)) {
4211 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4216 add_video_dialog->set_transient_for (*float_window);
4219 if (add_video_dialog->is_visible()) {
4220 /* we're already doing this */
4224 ResponseType r = (ResponseType) add_video_dialog->run ();
4225 add_video_dialog->hide();
4226 if (r != RESPONSE_ACCEPT) { return; }
4228 bool local_file, orig_local_file;
4229 std::string path = add_video_dialog->file_name(local_file);
4231 std::string orig_path = path;
4232 orig_local_file = local_file;
4234 bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4236 if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4237 warning << string_compose(_("could not open %1"), path) << endmsg;
4240 if (!local_file && path.length() == 0) {
4241 warning << _("no video-file selected") << endmsg;
4245 std::string audio_from_video;
4246 bool detect_ltc = false;
4248 switch (add_video_dialog->import_option()) {
4249 case VTL_IMPORT_TRANSCODE:
4251 TranscodeVideoDialog *transcode_video_dialog;
4252 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4253 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4254 transcode_video_dialog->hide();
4255 if (r != RESPONSE_ACCEPT) {
4256 delete transcode_video_dialog;
4260 audio_from_video = transcode_video_dialog->get_audiofile();
4262 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4265 else if (!audio_from_video.empty()) {
4266 editor->embed_audio_from_video(
4268 video_timeline->get_offset(),
4269 (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4272 switch (transcode_video_dialog->import_option()) {
4273 case VTL_IMPORT_TRANSCODED:
4274 path = transcode_video_dialog->get_filename();
4277 case VTL_IMPORT_REFERENCE:
4280 delete transcode_video_dialog;
4283 delete transcode_video_dialog;
4287 case VTL_IMPORT_NONE:
4291 /* strip _session->session_directory().video_path() from video file if possible */
4292 if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4293 path=path.substr(_session->session_directory().video_path().size());
4294 if (path.at(0) == G_DIR_SEPARATOR) {
4295 path=path.substr(1);
4299 video_timeline->set_update_session_fps(auto_set_session_fps);
4301 if (video_timeline->video_file_info(path, local_file)) {
4302 XMLNode* node = new XMLNode(X_("Videotimeline"));
4303 node->add_property (X_("Filename"), path);
4304 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4305 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4306 if (orig_local_file) {
4307 node->add_property (X_("OriginalVideoFile"), orig_path);
4309 node->remove_property (X_("OriginalVideoFile"));
4311 _session->add_extra_xml (*node);
4312 _session->set_dirty ();
4314 if (!audio_from_video.empty() && detect_ltc) {
4315 std::vector<LTCFileReader::LTCMap> ltc_seq;
4318 /* TODO ask user about TV standard (LTC alignment if any) */
4319 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4320 /* TODO ASK user which channel: 0 .. ltcr->channels() - 1 */
4322 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4324 /* TODO seek near end of file, and read LTC until end.
4325 * if it fails to find any LTC frames, scan complete file
4327 * calculate drift of LTC compared to video-duration,
4328 * ask user for reference (timecode from start/mid/end)
4331 // LTCFileReader will have written error messages
4334 ::g_unlink(audio_from_video.c_str());
4336 if (ltc_seq.size() == 0) {
4337 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4339 /* the very first TC in the file is somteimes not aligned properly */
4340 int i = ltc_seq.size() -1;
4341 ARDOUR::frameoffset_t video_start_offset =
4342 _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4343 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4344 video_timeline->set_offset(video_start_offset);
4348 _session->maybe_update_session_range(
4349 std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4350 std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4353 if (add_video_dialog->launch_xjadeo() && local_file) {
4354 editor->set_xjadeo_sensitive(true);
4355 editor->toggle_xjadeo_proc(1);
4357 editor->toggle_xjadeo_proc(0);
4359 editor->toggle_ruler_video(true);
4364 ARDOUR_UI::remove_video ()
4366 video_timeline->close_session();
4367 editor->toggle_ruler_video(false);
4370 video_timeline->set_offset_locked(false);
4371 video_timeline->set_offset(0);
4373 /* delete session state */
4374 XMLNode* node = new XMLNode(X_("Videotimeline"));
4375 _session->add_extra_xml(*node);
4376 node = new XMLNode(X_("Videomonitor"));
4377 _session->add_extra_xml(*node);
4378 node = new XMLNode(X_("Videoexport"));
4379 _session->add_extra_xml(*node);
4380 stop_video_server();
4384 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4386 if (localcacheonly) {
4387 video_timeline->vmon_update();
4389 video_timeline->flush_cache();
4391 editor->queue_visual_videotimeline_update();
4395 ARDOUR_UI::export_video (bool range)
4397 if (ARDOUR::Config->get_show_video_export_info()) {
4398 ExportVideoInfobox infobox (_session);
4399 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4400 if (infobox.show_again()) {
4401 ARDOUR::Config->set_show_video_export_info(false);
4404 case GTK_RESPONSE_YES:
4405 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4411 export_video_dialog->set_session (_session);
4412 export_video_dialog->apply_state(editor->get_selection().time, range);
4413 export_video_dialog->run ();
4414 export_video_dialog->hide ();
4418 ARDOUR_UI::mixer_settings () const
4423 node = _session->instant_xml(X_("Mixer"));
4425 node = Config->instant_xml(X_("Mixer"));
4429 node = new XMLNode (X_("Mixer"));
4436 ARDOUR_UI::main_window_settings () const
4441 node = _session->instant_xml(X_("Main"));
4443 node = Config->instant_xml(X_("Main"));
4447 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4448 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4453 node = new XMLNode (X_("Main"));
4460 ARDOUR_UI::editor_settings () const
4465 node = _session->instant_xml(X_("Editor"));
4467 node = Config->instant_xml(X_("Editor"));
4471 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4472 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4477 node = new XMLNode (X_("Editor"));
4484 ARDOUR_UI::keyboard_settings () const
4488 node = Config->extra_xml(X_("Keyboard"));
4491 node = new XMLNode (X_("Keyboard"));
4498 ARDOUR_UI::create_xrun_marker (framepos_t where)
4501 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
4502 _session->locations()->add (location);
4507 ARDOUR_UI::halt_on_xrun_message ()
4509 cerr << "HALT on xrun\n";
4510 MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4515 ARDOUR_UI::xrun_handler (framepos_t where)
4521 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4523 if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4524 create_xrun_marker(where);
4527 if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4528 halt_on_xrun_message ();
4533 ARDOUR_UI::disk_overrun_handler ()
4535 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4537 if (!have_disk_speed_dialog_displayed) {
4538 have_disk_speed_dialog_displayed = true;
4539 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4540 The disk system on your computer\n\
4541 was not able to keep up with %1.\n\
4543 Specifically, it failed to write data to disk\n\
4544 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4545 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4551 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4552 static MessageDialog *scan_dlg = NULL;
4553 static ProgressBar *scan_pbar = NULL;
4554 static HBox *scan_tbox = NULL;
4555 static Gtk::Button *scan_timeout_button;
4558 ARDOUR_UI::cancel_plugin_scan ()
4560 PluginManager::instance().cancel_plugin_scan();
4564 ARDOUR_UI::cancel_plugin_timeout ()
4566 PluginManager::instance().cancel_plugin_timeout();
4567 scan_timeout_button->set_sensitive (false);
4571 ARDOUR_UI::plugin_scan_timeout (int timeout)
4573 if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4577 scan_pbar->set_sensitive (false);
4578 scan_timeout_button->set_sensitive (true);
4579 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4582 scan_pbar->set_sensitive (false);
4583 scan_timeout_button->set_sensitive (false);
4589 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4591 if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4595 const bool cancelled = PluginManager::instance().cancelled();
4596 if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4597 if (cancelled && scan_dlg->is_mapped()) {
4602 if (cancelled || !can_cancel) {
4607 static Gtk::Button *cancel_button;
4609 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4610 VBox* vbox = scan_dlg->get_vbox();
4611 vbox->set_size_request(400,-1);
4612 scan_dlg->set_title (_("Scanning for plugins"));
4614 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4615 cancel_button->set_name ("EditorGTKButton");
4616 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4617 cancel_button->show();
4619 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4621 scan_tbox = manage( new HBox() );
4623 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4624 scan_timeout_button->set_name ("EditorGTKButton");
4625 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4626 scan_timeout_button->show();
4628 scan_pbar = manage(new ProgressBar());
4629 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4630 scan_pbar->set_text(_("Scan Timeout"));
4633 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4634 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4636 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4639 assert(scan_dlg && scan_tbox && cancel_button);
4641 if (type == X_("closeme")) {
4645 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4648 if (!can_cancel || !cancelled) {
4649 scan_timeout_button->set_sensitive(false);
4651 cancel_button->set_sensitive(can_cancel && !cancelled);
4657 ARDOUR_UI::gui_idle_handler ()
4660 /* due to idle calls, gtk_events_pending() may always return true */
4661 while (gtk_events_pending() && --timeout) {
4662 gtk_main_iteration ();
4667 ARDOUR_UI::disk_underrun_handler ()
4669 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4671 if (!have_disk_speed_dialog_displayed) {
4672 have_disk_speed_dialog_displayed = true;
4673 MessageDialog* msg = new MessageDialog (
4674 _main_window, string_compose (_("The disk system on your computer\n\
4675 was not able to keep up with %1.\n\
4677 Specifically, it failed to read data from disk\n\
4678 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4679 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4685 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4687 have_disk_speed_dialog_displayed = false;
4692 ARDOUR_UI::session_dialog (std::string msg)
4694 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4698 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4705 ARDOUR_UI::pending_state_dialog ()
4707 HBox* hbox = manage (new HBox());
4708 Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4709 ArdourDialog dialog (_("Crash Recovery"), true);
4710 Label message (string_compose (_("\
4711 This session appears to have been in the\n\
4712 middle of recording when %1 or\n\
4713 the computer was shutdown.\n\
4715 %1 can recover any captured audio for\n\
4716 you, or it can ignore it. Please decide\n\
4717 what you would like to do.\n"), PROGRAM_NAME));
4718 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4719 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4720 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4721 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4722 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
4723 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
4724 dialog.set_default_response (RESPONSE_ACCEPT);
4725 dialog.set_position (WIN_POS_CENTER);
4730 switch (dialog.run ()) {
4731 case RESPONSE_ACCEPT:
4739 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4741 HBox* hbox = new HBox();
4742 Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4743 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4744 Label message (string_compose (_("\
4745 This session was created with a sample rate of %1 Hz, but\n\
4746 %2 is currently running at %3 Hz. If you load this session,\n\
4747 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4749 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4750 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4751 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4752 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4753 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4754 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4755 dialog.set_default_response (RESPONSE_ACCEPT);
4756 dialog.set_position (WIN_POS_CENTER);
4761 switch (dialog.run()) {
4762 case RESPONSE_ACCEPT:
4772 ARDOUR_UI::use_config ()
4774 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
4776 set_transport_controllable_state (*node);
4781 ARDOUR_UI::update_transport_clocks (framepos_t pos)
4783 if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
4784 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4786 primary_clock->set (pos);
4789 if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
4790 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4792 secondary_clock->set (pos);
4795 if (big_clock_window) {
4796 big_clock->set (pos);
4798 ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
4802 ARDOUR_UI::step_edit_status_change (bool yn)
4804 // XXX should really store pre-step edit status of things
4805 // we make insensitive
4808 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
4809 rec_button.set_sensitive (false);
4811 rec_button.unset_active_state ();;
4812 rec_button.set_sensitive (true);
4817 ARDOUR_UI::record_state_changed ()
4819 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
4821 if (!_session || !big_clock_window) {
4822 /* why bother - the clock isn't visible */
4826 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
4827 big_clock->set_active (true);
4829 big_clock->set_active (false);
4834 ARDOUR_UI::first_idle ()
4837 _session->allow_auto_play (true);
4841 editor->first_idle();
4844 Keyboard::set_can_save_keybindings (true);
4849 ARDOUR_UI::store_clock_modes ()
4851 XMLNode* node = new XMLNode(X_("ClockModes"));
4853 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
4854 XMLNode* child = new XMLNode (X_("Clock"));
4856 child->add_property (X_("name"), (*x)->name());
4857 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
4858 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
4860 node->add_child_nocopy (*child);
4863 _session->add_extra_xml (*node);
4864 _session->set_dirty ();
4867 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
4868 : Controllable (name), ui (u), type(tp)
4874 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
4877 /* do nothing: these are radio-style actions */
4881 const char *action = 0;
4885 action = X_("Roll");
4888 action = X_("Stop");
4891 action = X_("GotoStart");
4894 action = X_("GotoEnd");
4897 action = X_("Loop");
4900 action = X_("PlaySelection");
4903 action = X_("Record");
4913 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
4921 ARDOUR_UI::TransportControllable::get_value (void) const
4948 ARDOUR_UI::setup_profile ()
4950 if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
4951 Profile->set_small_screen ();
4954 if (g_getenv ("TRX")) {
4955 Profile->set_trx ();
4958 if (g_getenv ("MIXBUS")) {
4959 Profile->set_mixbus ();
4964 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
4966 MissingFileDialog dialog (s, str, type);
4971 int result = dialog.run ();
4978 return 1; // quit entire session load
4981 result = dialog.get_action ();
4987 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
4989 AmbiguousFileDialog dialog (file, hits);
4996 return dialog.get_which ();
4999 /** Allocate our thread-local buffers */
5001 ARDOUR_UI::get_process_buffers ()
5003 _process_thread->get_buffers ();
5006 /** Drop our thread-local buffers */
5008 ARDOUR_UI::drop_process_buffers ()
5010 _process_thread->drop_buffers ();
5014 ARDOUR_UI::feedback_detected ()
5016 _feedback_exists = true;
5020 ARDOUR_UI::successful_graph_sort ()
5022 _feedback_exists = false;
5026 ARDOUR_UI::midi_panic ()
5029 _session->midi_panic();
5034 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5036 const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5037 const char* end_big = "</span>";
5038 const char* start_mono = "<tt>";
5039 const char* end_mono = "</tt>";
5041 MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5042 "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5043 "From now on, use the -2000 version with older versions of %3"),
5044 xml_path, backup_path, PROGRAM_NAME,
5046 start_mono, end_mono), true);
5053 ARDOUR_UI::reset_peak_display ()
5055 if (!_session || !_session->master_out() || !editor_meter) return;
5056 editor_meter->clear_meters();
5057 editor_meter_max_peak = -INFINITY;
5058 editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5062 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5064 if (!_session || !_session->master_out()) return;
5065 if (group == _session->master_out()->route_group()) {
5066 reset_peak_display ();
5071 ARDOUR_UI::reset_route_peak_display (Route* route)
5073 if (!_session || !_session->master_out()) return;
5074 if (_session->master_out().get() == route) {
5075 reset_peak_display ();
5080 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5082 audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5083 audio_midi_setup->set_position (WIN_POS_CENTER);
5088 response = audio_midi_setup->run();
5090 case Gtk::RESPONSE_OK:
5091 if (!AudioEngine::instance()->running()) {
5105 ARDOUR_UI::transport_numpad_timeout ()
5107 _numpad_locate_happening = false;
5108 if (_numpad_timeout_connection.connected() )
5109 _numpad_timeout_connection.disconnect();
5114 ARDOUR_UI::transport_numpad_decimal ()
5116 _numpad_timeout_connection.disconnect();
5118 if (_numpad_locate_happening) {
5119 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5120 _numpad_locate_happening = false;
5122 _pending_locate_num = 0;
5123 _numpad_locate_happening = true;
5124 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5129 ARDOUR_UI::transport_numpad_event (int num)
5131 if ( _numpad_locate_happening ) {
5132 _pending_locate_num = _pending_locate_num*10 + num;
5135 case 0: toggle_roll(false, false); break;
5136 case 1: transport_rewind(1); break;
5137 case 2: transport_forward(1); break;
5138 case 3: transport_record(true); break;
5139 case 4: toggle_session_auto_loop(); break;
5140 case 5: transport_record(false); toggle_session_auto_loop(); break;
5141 case 6: toggle_punch(); break;
5142 case 7: toggle_click(); break;
5143 case 8: toggle_auto_return(); break;
5144 case 9: toggle_follow_edits(); break;
5150 ARDOUR_UI::set_flat_buttons ()
5152 CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5156 ARDOUR_UI::audioengine_became_silent ()
5158 MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5160 Gtk::MESSAGE_WARNING,
5164 msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5166 Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5167 Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5168 Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5169 Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5170 Gtk::HBox pay_button_box;
5171 Gtk::HBox subscribe_button_box;
5173 pay_button_box.pack_start (pay_button, true, false);
5174 subscribe_button_box.pack_start (subscribe_button, true, false);
5176 bool (*openuri)(const char*) = PBD::open_uri; /* this forces selection of the const char* variant of PBD::open_uri(), which we need to avoid ambiguity below */
5178 pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5179 subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5181 msg.get_vbox()->pack_start (pay_label);
5182 msg.get_vbox()->pack_start (pay_button_box);
5183 msg.get_vbox()->pack_start (subscribe_label);
5184 msg.get_vbox()->pack_start (subscribe_button_box);
5186 msg.get_vbox()->show_all ();
5188 msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5189 msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5190 msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5195 case Gtk::RESPONSE_YES:
5196 AudioEngine::instance()->reset_silence_countdown ();
5199 case Gtk::RESPONSE_NO:
5201 save_state_canfail ("");
5205 case Gtk::RESPONSE_CANCEL:
5207 /* don't reset, save session and exit */
5213 ARDOUR_UI::hide_application ()
5215 Application::instance ()-> hide ();
5219 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5221 /* icons, titles, WM stuff */
5223 static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5225 if (window_icons.empty()) {
5226 Glib::RefPtr<Gdk::Pixbuf> icon;
5227 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
5228 window_icons.push_back (icon);
5230 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
5231 window_icons.push_back (icon);
5233 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
5234 window_icons.push_back (icon);
5236 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
5237 window_icons.push_back (icon);
5241 if (!window_icons.empty()) {
5242 window.set_default_icon_list (window_icons);
5245 Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5247 if (!name.empty()) {
5251 window.set_title (title.get_string());
5252 window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
5254 window.set_flags (CAN_FOCUS);
5255 window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5257 /* This is a hack to ensure that GTK-accelerators continue to
5258 * work. Once we switch over to entirely native bindings, this will be
5259 * unnecessary and should be removed
5261 window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5263 window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5264 window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5265 window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5266 window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5270 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5272 Gtkmm2ext::Bindings* bindings = 0;
5273 Gtk::Window* window = 0;
5275 /* until we get ardour bindings working, we are not handling key
5279 if (ev->type != GDK_KEY_PRESS) {
5283 if (event_window == &_main_window) {
5285 window = event_window;
5287 /* find current tab contents */
5289 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5291 /* see if it uses the ardour binding system */
5294 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5297 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5301 window = event_window;
5303 /* see if window uses ardour binding system */
5305 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5308 /* An empty binding set is treated as if it doesn't exist */
5310 if (bindings && bindings->empty()) {
5314 return key_press_focus_accelerator_handler (*window, ev, bindings);
5317 static Gtkmm2ext::Bindings*
5318 get_bindings_from_widget_heirarchy (GtkWidget* w)
5323 if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) {
5326 w = gtk_widget_get_parent (w);
5329 return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5333 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5335 GtkWindow* win = window.gobj();
5336 GtkWidget* focus = gtk_window_get_focus (win);
5337 bool special_handling_of_unmodified_accelerators = false;
5338 const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5342 /* some widget has keyboard focus */
5344 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5346 /* A particular kind of focusable widget currently has keyboard
5347 * focus. All unmodified key events should go to that widget
5348 * first and not be used as an accelerator by default
5351 special_handling_of_unmodified_accelerators = true;
5355 Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus);
5356 if (focus_bindings) {
5357 bindings = focus_bindings;
5358 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5363 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n",
5366 show_gdk_event_state (ev->state),
5367 special_handling_of_unmodified_accelerators,
5368 Keyboard::some_magic_widget_has_focus(),
5370 (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5371 ((ev->state & mask) ? "yes" : "no")));
5373 /* This exists to allow us to override the way GTK handles
5374 key events. The normal sequence is:
5376 a) event is delivered to a GtkWindow
5377 b) accelerators/mnemonics are activated
5378 c) if (b) didn't handle the event, propagate to
5379 the focus widget and/or focus chain
5381 The problem with this is that if the accelerators include
5382 keys without modifiers, such as the space bar or the
5383 letter "e", then pressing the key while typing into
5384 a text entry widget results in the accelerator being
5385 activated, instead of the desired letter appearing
5388 There is no good way of fixing this, but this
5389 represents a compromise. The idea is that
5390 key events involving modifiers (not Shift)
5391 get routed into the activation pathway first, then
5392 get propagated to the focus widget if necessary.
5394 If the key event doesn't involve modifiers,
5395 we deliver to the focus widget first, thus allowing
5396 it to get "normal text" without interference
5399 Of course, this can also be problematic: if there
5400 is a widget with focus, then it will swallow
5401 all "normal text" accelerators.
5405 if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5407 /* no special handling or there are modifiers in effect: accelerate first */
5409 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5410 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5411 ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5413 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5414 KeyboardKey k (ev->state, ev->keyval);
5418 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5420 if (bindings->activate (k, Bindings::Press)) {
5421 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5426 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5428 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5429 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5433 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5435 if (gtk_window_propagate_key_event (win, ev)) {
5436 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5442 /* no modifiers, propagate first */
5444 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5446 if (gtk_window_propagate_key_event (win, ev)) {
5447 DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5451 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5452 KeyboardKey k (ev->state, ev->keyval);
5456 DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5459 if (bindings->activate (k, Bindings::Press)) {
5460 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5466 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5468 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5469 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5474 DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5479 ARDOUR_UI::load_bindings ()
5481 if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5482 error << _("Global keybindings are missing") << endmsg;
5487 ARDOUR_UI::cancel_solo ()
5490 if (_session->soloing()) {
5491 _session->set_solo (_session->get_routes(), false);
5492 } else if (_session->listening()) {
5493 _session->set_listen (_session->get_routes(), false);
5496 _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window