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/failed_constructor.h"
52 #include "pbd/enumwriter.h"
53 #include "pbd/memento_command.h"
54 #include "pbd/openuri.h"
55 #include "pbd/stl_delete.h"
56 #include "pbd/file_utils.h"
57 #include "pbd/localtime_r.h"
58 #include "pbd/pthread_utils.h"
59 #include "pbd/replace_all.h"
60 #include "pbd/xml++.h"
62 #include "gtkmm2ext/application.h"
63 #include "gtkmm2ext/bindings.h"
64 #include "gtkmm2ext/gtk_ui.h"
65 #include "gtkmm2ext/utils.h"
66 #include "gtkmm2ext/click_box.h"
67 #include "gtkmm2ext/fastmeter.h"
68 #include "gtkmm2ext/popup.h"
69 #include "gtkmm2ext/window_title.h"
71 #include "ardour/ardour.h"
72 #include "ardour/audio_backend.h"
73 #include "ardour/audioengine.h"
74 #include "ardour/audiofilesource.h"
75 #include "ardour/automation_watch.h"
76 #include "ardour/diskstream.h"
77 #include "ardour/filename_extensions.h"
78 #include "ardour/filesystem_paths.h"
79 #include "ardour/ltc_file_reader.h"
80 #include "ardour/port.h"
81 #include "ardour/plugin_manager.h"
82 #include "ardour/process_thread.h"
83 #include "ardour/profile.h"
84 #include "ardour/recent_sessions.h"
85 #include "ardour/session_directory.h"
86 #include "ardour/session_route.h"
87 #include "ardour/session_state_utils.h"
88 #include "ardour/session_utils.h"
89 #include "ardour/source_factory.h"
90 #include "ardour/slave.h"
91 #include "ardour/system_exec.h"
93 #ifdef WINDOWS_VST_SUPPORT
96 #ifdef AUDIOUNIT_SUPPORT
97 #include "ardour/audio_unit.h"
100 #include "timecode/time.h"
102 typedef uint64_t microseconds_t;
107 #include "add_route_dialog.h"
108 #include "ambiguous_file_dialog.h"
109 #include "ardour_ui.h"
110 #include "audio_clock.h"
111 #include "audio_region_view.h"
112 #include "big_clock_window.h"
113 #include "bundle_manager.h"
114 #include "duplicate_routes_dialog.h"
115 #include "engine_dialog.h"
116 #include "export_video_dialog.h"
117 #include "export_video_infobox.h"
118 #include "gain_meter.h"
119 #include "global_port_matrix.h"
120 #include "gui_object.h"
121 #include "gui_thread.h"
122 #include "keyboard.h"
123 #include "keyeditor.h"
124 #include "location_ui.h"
125 #include "main_clock.h"
126 #include "missing_file_dialog.h"
127 #include "missing_plugin_dialog.h"
128 #include "mixer_ui.h"
129 #include "meterbridge.h"
130 #include "mouse_cursors.h"
133 #include "pingback.h"
134 #include "processor_box.h"
135 #include "prompter.h"
136 #include "public_editor.h"
137 #include "rc_option_editor.h"
138 #include "route_time_axis.h"
139 #include "route_params_ui.h"
140 #include "save_as_dialog.h"
141 #include "session_dialog.h"
142 #include "session_metadata_dialog.h"
143 #include "session_option_editor.h"
144 #include "shuttle_control.h"
145 #include "speaker_dialog.h"
148 #include "theme_manager.h"
149 #include "time_axis_view_item.h"
152 #include "video_server_dialog.h"
153 #include "add_video_dialog.h"
154 #include "transcode_video_dialog.h"
158 using namespace ARDOUR;
159 using namespace ARDOUR_UI_UTILS;
161 using namespace Gtkmm2ext;
164 using namespace Editing;
166 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
168 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
169 sigc::signal<void> ARDOUR_UI::CloseAllDialogs;
172 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
174 MessageDialog msg (string_compose (_("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
175 "Would you like these files to be copied and used for %1 %2.x?\n\n"
176 "(This will require you to restart %1.)"),
177 PROGRAM_NAME, PROGRAM_VERSION, version),
178 false, /* no markup */
181 true /* modal, though it hardly matters since it is the only window */
184 msg.set_default_response (Gtk::RESPONSE_YES);
187 return (msg.run() == Gtk::RESPONSE_YES);
191 libxml_generic_error_func (void* /* parsing_context*/,
199 vsnprintf (buf, sizeof (buf), msg, ap);
200 error << buf << endmsg;
205 libxml_structured_error_func (void* /* parsing_context*/,
213 replace_all (msg, "\n", "");
215 if (err->file && err->line) {
216 error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
219 error << ':' << err->int2;
226 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
228 : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
229 , session_loaded (false)
230 , gui_object_state (new GUIObjectState)
231 , primary_clock (new MainClock (X_("primary"), X_("transport"), true ))
232 , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
233 , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
235 , ignore_dual_punch (false)
240 , _mixer_on_top (false)
241 , _initial_verbose_plugin_scan (false)
242 , first_time_engine_run (true)
243 , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
244 , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
245 , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
246 , goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd))
247 , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
248 , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
249 , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
250 , auto_return_button (ArdourButton::led_default_elements)
251 , follow_edits_button (ArdourButton::led_default_elements)
252 , auto_input_button (ArdourButton::led_default_elements)
253 , auditioning_alert_button (_("Audition"))
254 , solo_alert_button (_("Solo"))
255 , feedback_alert_button (_("Feedback"))
256 , error_alert_button ( ArdourButton::just_led_default_elements )
258 , editor_meter_peak_display()
259 , _numpad_locate_happening (false)
260 , _session_is_new (false)
261 , last_key_press_time (0)
264 , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
265 , key_editor (X_("key-editor"), _("Key Bindings"))
266 , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
267 , about (X_("about"), _("About"))
268 , location_ui (X_("locations"), _("Locations"))
269 , route_params (X_("inspector"), _("Tracks and Busses"))
270 , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
271 , export_video_dialog (X_("video-export"), _("Video Export Dialog"))
272 , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
273 , add_video_dialog (X_("add-video"), _("Add Tracks/Busses"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
274 , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
275 , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
276 , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
277 , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
278 , video_server_process (0)
280 , have_configure_timeout (false)
281 , last_configure_time (0)
283 , have_disk_speed_dialog_displayed (false)
284 , _status_bar_visibility (X_("status-bar"))
285 , _feedback_exists (false)
286 , _log_not_acknowledged (LogLevelNone)
287 , duplicate_routes_dialog (0)
289 Gtkmm2ext::init (localedir);
291 UIConfiguration::instance().post_gui_init ();
293 if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
294 MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
296 /* configuration was modified, exit immediately */
300 if (theArdourUI == 0) {
304 /* stop libxml from spewing to stdout/stderr */
306 xmlSetGenericErrorFunc (this, libxml_generic_error_func);
307 xmlSetStructuredErrorFunc (this, libxml_structured_error_func);
309 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
310 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
311 UIConfiguration::instance().map_parameters (pc);
313 roll_button.set_controllable (roll_controllable);
314 stop_button.set_controllable (stop_controllable);
315 goto_start_button.set_controllable (goto_start_controllable);
316 goto_end_button.set_controllable (goto_end_controllable);
317 auto_loop_button.set_controllable (auto_loop_controllable);
318 play_selection_button.set_controllable (play_selection_controllable);
319 rec_button.set_controllable (rec_controllable);
321 roll_button.set_name ("transport button");
322 stop_button.set_name ("transport button");
323 goto_start_button.set_name ("transport button");
324 goto_end_button.set_name ("transport button");
325 auto_loop_button.set_name ("transport button");
326 play_selection_button.set_name ("transport button");
327 rec_button.set_name ("transport recenable button");
328 midi_panic_button.set_name ("transport button");
330 ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
331 ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
333 ARDOUR::Session::VersionMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_format_mismatch, this, _1, _2), gui_context());
335 /* handle dialog requests */
337 ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
339 /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
341 ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
343 /* handle Audio/MIDI setup when session requires it */
345 ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1));
347 /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
349 ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
351 /* handle requests to quit (coming from JACK session) */
353 ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::finish, this), gui_context ());
355 /* tell the user about feedback */
357 ARDOUR::Session::FeedbackDetected.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::feedback_detected, this), gui_context ());
358 ARDOUR::Session::SuccessfulGraphSort.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::successful_graph_sort, this), gui_context ());
360 /* handle requests to deal with missing files */
362 ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
364 /* and ambiguous files */
366 ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
368 /* also plugin scan messages */
369 ARDOUR::PluginScanMessage.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_dialog, this, _1, _2, _3), gui_context());
370 ARDOUR::PluginScanTimeout.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_timeout, this, _1), gui_context());
372 ARDOUR::GUIIdle.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::gui_idle_handler, this), gui_context());
374 Config->ParameterChanged.connect ( forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::set_flat_buttons, this), gui_context() );
377 /* lets get this party started */
379 setup_gtk_ardour_enums ();
382 SessionEvent::create_per_thread_pool ("GUI", 4096);
384 /* we like keyboards */
386 keyboard = new ArdourKeyboard(*this);
388 XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
390 keyboard->set_state (*node, Stateful::loading_state_version);
393 /* we don't like certain modifiers */
394 Bindings::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK);
396 UIConfiguration::instance().reset_dpi ();
398 TimeAxisViewItem::set_constant_heights ();
400 /* Set this up so that our window proxies can register actions */
402 ActionManager::init ();
404 /* The following must happen after ARDOUR::init() so that Config is set up */
406 const XMLNode* ui_xml = Config->extra_xml (X_("UI"));
409 key_editor.set_state (*ui_xml);
410 // rc_option_editor.set_state (*ui_xml);
411 session_option_editor.set_state (*ui_xml);
412 speaker_config_window.set_state (*ui_xml);
413 about.set_state (*ui_xml);
414 add_route_dialog.set_state (*ui_xml);
415 add_video_dialog.set_state (*ui_xml);
416 route_params.set_state (*ui_xml);
417 bundle_manager.set_state (*ui_xml);
418 location_ui.set_state (*ui_xml);
419 big_clock_window.set_state (*ui_xml);
420 audio_port_matrix.set_state (*ui_xml);
421 midi_port_matrix.set_state (*ui_xml);
422 export_video_dialog.set_state (*ui_xml);
425 WM::Manager::instance().register_window (&key_editor);
426 // WM::Manager::instance().register_window (&rc_option_editor);
427 WM::Manager::instance().register_window (&session_option_editor);
428 WM::Manager::instance().register_window (&speaker_config_window);
429 WM::Manager::instance().register_window (&about);
430 WM::Manager::instance().register_window (&add_route_dialog);
431 WM::Manager::instance().register_window (&add_video_dialog);
432 WM::Manager::instance().register_window (&route_params);
433 WM::Manager::instance().register_window (&audio_midi_setup);
434 WM::Manager::instance().register_window (&export_video_dialog);
435 WM::Manager::instance().register_window (&bundle_manager);
436 WM::Manager::instance().register_window (&location_ui);
437 WM::Manager::instance().register_window (&big_clock_window);
438 WM::Manager::instance().register_window (&audio_port_matrix);
439 WM::Manager::instance().register_window (&midi_port_matrix);
441 /* Trigger setting up the color scheme and loading the GTK RC file */
443 UIConfiguration::instance().load_rc_file (false);
445 _process_thread = new ProcessThread ();
446 _process_thread->init ();
448 UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets));
453 GlobalPortMatrixWindow*
454 ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
459 return new GlobalPortMatrixWindow (_session, type);
463 ARDOUR_UI::attach_to_engine ()
465 AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
466 ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
470 ARDOUR_UI::engine_stopped ()
472 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
473 ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
474 ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
475 update_sample_rate (0);
480 ARDOUR_UI::engine_running ()
482 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
483 if (first_time_engine_run) {
485 first_time_engine_run = false;
489 _session->reset_xrun_count ();
491 update_disk_space ();
493 update_xrun_count ();
494 update_sample_rate (AudioEngine::instance()->sample_rate());
495 update_timecode_format ();
496 update_peak_thread_work ();
497 ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true);
498 ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false);
502 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
504 if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
505 /* we can't rely on the original string continuing to exist when we are called
506 again in the GUI thread, so make a copy and note that we need to
509 char *copy = strdup (reason);
510 Gtkmm2ext::UI::instance()->call_slot (MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
514 ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
515 ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
517 update_sample_rate (0);
521 /* if the reason is a non-empty string, it means that the backend was shutdown
522 rather than just Ardour.
525 if (strlen (reason)) {
526 msgstr = string_compose (_("The audio backend was shutdown because:\n\n%1"), reason);
528 msgstr = string_compose (_("\
529 The audio backend has either been shutdown or it\n\
530 disconnected %1 because %1\n\
531 was not fast enough. Try to restart\n\
532 the audio backend and save the session."), PROGRAM_NAME);
535 MessageDialog msg (*editor, msgstr);
536 pop_back_splash (msg);
540 free (const_cast<char*> (reason));
545 ARDOUR_UI::post_engine ()
547 /* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine
549 #ifdef AUDIOUNIT_SUPPORT
551 if (AUPluginInfo::au_get_crashlog(au_msg)) {
552 popup_error(_("Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see the log window for further details."));
553 error << _("Audio Unit Plugin Scan Failed:") << endmsg;
554 info << au_msg << endmsg;
558 ARDOUR::init_post_engine ();
560 /* connect to important signals */
562 AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
563 AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
564 AudioEngine::instance()->BufferSizeChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
565 AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
566 AudioEngine::instance()->BecameSilent.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::audioengine_became_silent, this), gui_context());
568 if (setup_windows ()) {
569 throw failed_constructor ();
572 /* Do this after setup_windows (), as that's when the _status_bar_visibility is created */
573 XMLNode* n = Config->extra_xml (X_("UI"));
575 _status_bar_visibility.set_state (*n);
578 check_memory_locking();
580 /* this is the first point at which all the keybindings are available */
582 if (ARDOUR_COMMAND_LINE::show_key_actions) {
583 vector<string> names;
584 vector<string> paths;
585 vector<string> tooltips;
587 vector<AccelKey> bindings;
589 ActionManager::get_all_actions (names, paths, tooltips, keys, bindings);
591 vector<string>::iterator n;
592 vector<string>::iterator k;
593 vector<string>::iterator p;
594 for (n = names.begin(), k = keys.begin(), p = paths.begin(); n != names.end(); ++n, ++k, ++p) {
595 cout << "Action: '" << (*n) << "' bound to '" << (*k) << "' Path: '" << (*p) << "'" << endl;
598 halt_connection.disconnect ();
599 AudioEngine::instance()->stop ();
603 /* this being a GUI and all, we want peakfiles */
605 AudioFileSource::set_build_peakfiles (true);
606 AudioFileSource::set_build_missing_peakfiles (true);
608 /* set default clock modes */
610 if (Profile->get_sae()) {
611 primary_clock->set_mode (AudioClock::BBT);
612 secondary_clock->set_mode (AudioClock::MinSec);
614 primary_clock->set_mode (AudioClock::Timecode);
615 secondary_clock->set_mode (AudioClock::BBT);
618 /* start the time-of-day-clock */
621 /* OS X provides a nearly-always visible wallclock, so don't be stupid */
622 update_wall_clock ();
623 Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1);
628 Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
629 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
630 Config->map_parameters (pc);
632 UIConfiguration::instance().map_parameters (pc);
636 ARDOUR_UI::~ARDOUR_UI ()
638 UIConfiguration::instance().save_state();
642 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
643 // don't bother at 'real' exit. the OS cleans up for us.
645 delete primary_clock;
646 delete secondary_clock;
647 delete _process_thread;
652 delete gui_object_state;
653 FastMeter::flush_pattern_cache ();
654 PixFader::flush_pattern_cache ();
658 /* Small trick to flush main-thread event pool.
659 * Other thread-pools are destroyed at pthread_exit(),
660 * but tmain thread termination is too late to trigger Pool::~Pool()
662 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.
663 delete ev->event_pool();
668 ARDOUR_UI::pop_back_splash (Gtk::Window& win)
670 if (Splash::instance()) {
671 Splash::instance()->pop_back_for (win);
676 ARDOUR_UI::configure_timeout ()
678 if (last_configure_time == 0) {
679 /* no configure events yet */
683 /* force a gap of 0.5 seconds since the last configure event
686 if (get_microseconds() - last_configure_time < 500000) {
689 have_configure_timeout = false;
690 save_ardour_state ();
696 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
698 if (have_configure_timeout) {
699 last_configure_time = get_microseconds();
701 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
702 have_configure_timeout = true;
709 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
711 const XMLProperty* prop;
713 if ((prop = node.property ("roll")) != 0) {
714 roll_controllable->set_id (prop->value());
716 if ((prop = node.property ("stop")) != 0) {
717 stop_controllable->set_id (prop->value());
719 if ((prop = node.property ("goto-start")) != 0) {
720 goto_start_controllable->set_id (prop->value());
722 if ((prop = node.property ("goto-end")) != 0) {
723 goto_end_controllable->set_id (prop->value());
725 if ((prop = node.property ("auto-loop")) != 0) {
726 auto_loop_controllable->set_id (prop->value());
728 if ((prop = node.property ("play-selection")) != 0) {
729 play_selection_controllable->set_id (prop->value());
731 if ((prop = node.property ("rec")) != 0) {
732 rec_controllable->set_id (prop->value());
734 if ((prop = node.property ("shuttle")) != 0) {
735 shuttle_box->controllable()->set_id (prop->value());
740 ARDOUR_UI::get_transport_controllable_state ()
742 XMLNode* node = new XMLNode(X_("TransportControllables"));
745 roll_controllable->id().print (buf, sizeof (buf));
746 node->add_property (X_("roll"), buf);
747 stop_controllable->id().print (buf, sizeof (buf));
748 node->add_property (X_("stop"), buf);
749 goto_start_controllable->id().print (buf, sizeof (buf));
750 node->add_property (X_("goto_start"), buf);
751 goto_end_controllable->id().print (buf, sizeof (buf));
752 node->add_property (X_("goto_end"), buf);
753 auto_loop_controllable->id().print (buf, sizeof (buf));
754 node->add_property (X_("auto_loop"), buf);
755 play_selection_controllable->id().print (buf, sizeof (buf));
756 node->add_property (X_("play_selection"), buf);
757 rec_controllable->id().print (buf, sizeof (buf));
758 node->add_property (X_("rec"), buf);
759 shuttle_box->controllable()->id().print (buf, sizeof (buf));
760 node->add_property (X_("shuttle"), buf);
766 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
769 _session->save_state (snapshot_name);
774 ARDOUR_UI::autosave_session ()
776 if (g_main_depth() > 1) {
777 /* inside a recursive main loop,
778 give up because we may not be able to
784 if (!Config->get_periodic_safety_backups()) {
789 _session->maybe_write_autosave();
796 ARDOUR_UI::update_autosave ()
798 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_autosave)
800 if (_session && _session->dirty()) {
801 if (_autosave_connection.connected()) {
802 _autosave_connection.disconnect();
805 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
806 Config->get_periodic_safety_backup_interval() * 1000);
809 if (_autosave_connection.connected()) {
810 _autosave_connection.disconnect();
816 ARDOUR_UI::check_announcements ()
819 string _annc_filename;
822 _annc_filename = PROGRAM_NAME "_announcements_osx_";
823 #elif defined PLATFORM_WINDOWS
824 _annc_filename = PROGRAM_NAME "_announcements_windows_";
826 _annc_filename = PROGRAM_NAME "_announcements_linux_";
828 _annc_filename.append (VERSIONSTRING);
830 _announce_string = "";
832 std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
833 FILE* fin = g_fopen (path.c_str(), "rb");
835 while (!feof (fin)) {
838 if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
841 _announce_string.append (tmp, len);
846 pingback (VERSIONSTRING, path);
851 ARDOUR_UI::starting ()
853 Application* app = Application::instance ();
855 bool brand_new_user = ArdourStartup::required ();
857 app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
858 app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::load_from_application_api));
860 if (ARDOUR_COMMAND_LINE::check_announcements) {
861 check_announcements ();
866 /* we need to create this early because it may need to set the
867 * audio backend end up.
871 audio_midi_setup.get (true);
873 std::cerr << "audio-midi engine setup failed."<< std::endl;
877 if ((nsm_url = g_getenv ("NSM_URL")) != 0) {
878 nsm = new NSM_Client;
879 if (!nsm->init (nsm_url)) {
880 /* the ardour executable may have different names:
882 * waf's obj.target for distro versions: eg ardour4, ardourvst4
883 * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
884 * argv[0] does not apply since we need the wrapper-script (not the binary itself)
886 * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
888 const char *process_name = g_getenv ("ARDOUR_SELF");
889 nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour4");
892 // wait for announce reply from nsm server
893 for ( i = 0; i < 5000; ++i) {
897 if (nsm->is_active()) {
902 error << _("NSM server did not announce itself") << endmsg;
905 // wait for open command from nsm server
906 for ( i = 0; i < 5000; ++i) {
909 if (nsm->client_id ()) {
915 error << _("NSM: no client ID provided") << endmsg;
919 if (_session && nsm) {
920 _session->set_nsm_state( nsm->is_active() );
922 error << _("NSM: no session created") << endmsg;
926 // nsm requires these actions disabled
927 vector<string> action_names;
928 action_names.push_back("SaveAs");
929 action_names.push_back("Rename");
930 action_names.push_back("New");
931 action_names.push_back("Open");
932 action_names.push_back("Recent");
933 action_names.push_back("Close");
935 for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
936 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
938 act->set_sensitive (false);
945 error << _("NSM: initialization failed") << endmsg;
951 if (brand_new_user) {
952 _initial_verbose_plugin_scan = true;
957 _initial_verbose_plugin_scan = false;
958 switch (s.response ()) {
959 case Gtk::RESPONSE_OK:
966 #ifdef NO_PLUGIN_STATE
968 ARDOUR::RecentSessions rs;
969 ARDOUR::read_recent_sessions (rs);
971 string path = Glib::build_filename (user_config_directory(), ".iknowaboutfreeversion");
973 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS) && !rs.empty()) {
975 /* already used Ardour, have sessions ... warn about plugin state */
977 ArdourDialog d (_("Free/Demo Version Warning"), true);
979 Button b (string_compose (_("Subscribe and support development of %1"), PROGRAM_NAME));
980 CheckButton c (_("Don't warn me about this again"));
982 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"),
983 string_compose (_("This is a free/demo version of %1"), PROGRAM_NAME),
984 _("It will not restore OR save any plugin settings"),
985 _("If you load an existing session with plugin settings\n"
986 "they will not be used and will be lost."),
987 _("To get full access to updates without this limitation\n"
988 "consider becoming a subscriber for a low cost every month.")));
989 l.set_justify (JUSTIFY_CENTER);
991 b.signal_clicked().connect (mem_fun(*this, &ARDOUR_UI::launch_subscribe));
993 d.get_vbox()->pack_start (l, true, true);
994 d.get_vbox()->pack_start (b, false, false, 12);
995 d.get_vbox()->pack_start (c, false, false, 12);
997 d.add_button (_("Quit now"), RESPONSE_CANCEL);
998 d.add_button (string_compose (_("Continue using %1"), PROGRAM_NAME), RESPONSE_OK);
1002 c.signal_toggled().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (toggle_file_existence), path)));
1004 if (d.run () != RESPONSE_OK) {
1010 /* go get a session */
1012 const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
1014 if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
1015 std::cerr << "Cannot get session parameters."<< std::endl;
1022 goto_editor_window ();
1024 WM::Manager::instance().show_visible ();
1026 /* We have to do this here since goto_editor_window() ends up calling show_all() on the
1027 * editor window, and we may want stuff to be hidden.
1029 _status_bar_visibility.update ();
1031 BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
1036 ARDOUR_UI::check_memory_locking ()
1038 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
1039 /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
1043 XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
1045 if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
1047 struct rlimit limits;
1049 long pages, page_size;
1051 size_t pages_len=sizeof(pages);
1052 if ((page_size = getpagesize()) < 0 ||
1053 sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
1055 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
1060 ram = (int64_t) pages * (int64_t) page_size;
1063 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
1067 if (limits.rlim_cur != RLIM_INFINITY) {
1069 if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
1073 _("WARNING: Your system has a limit for maximum amount of locked memory. "
1074 "This might cause %1 to run out of memory before your system "
1075 "runs out of memory. \n\n"
1076 "You can view the memory limit with 'ulimit -l', "
1077 "and it is normally controlled by %2"),
1080 X_("/etc/login.conf")
1082 X_(" /etc/security/limits.conf")
1086 msg.set_default_response (RESPONSE_OK);
1088 VBox* vbox = msg.get_vbox();
1090 CheckButton cb (_("Do not show this window again"));
1091 hbox.pack_start (cb, true, false);
1092 vbox->pack_start (hbox);
1097 pop_back_splash (msg);
1099 editor->ensure_float (msg);
1102 if (cb.get_active()) {
1103 XMLNode node (X_("no-memory-warning"));
1104 Config->add_instant_xml (node);
1109 #endif // !__APPLE__
1114 ARDOUR_UI::queue_finish ()
1116 Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
1120 ARDOUR_UI::idle_finish ()
1123 return false; /* do not call again */
1130 ARDOUR_UI::instance()->video_timeline->sync_session_state();
1132 if (_session->dirty()) {
1133 vector<string> actions;
1134 actions.push_back (_("Don't quit"));
1135 actions.push_back (_("Just quit"));
1136 actions.push_back (_("Save and quit"));
1137 switch (ask_about_saving_session(actions)) {
1142 /* use the default name */
1143 if (save_state_canfail ("")) {
1144 /* failed - don't quit */
1145 MessageDialog msg (*editor,
1146 string_compose (_("\
1147 %1 was unable to save your session.\n\n\
1148 If you still wish to quit, please use the\n\n\
1149 \"Just quit\" option."), PROGRAM_NAME));
1150 pop_back_splash(msg);
1160 second_connection.disconnect ();
1161 point_one_second_connection.disconnect ();
1162 point_zero_something_second_connection.disconnect();
1163 fps_connection.disconnect();
1166 delete ARDOUR_UI::instance()->video_timeline;
1167 ARDOUR_UI::instance()->video_timeline = NULL;
1168 stop_video_server();
1170 /* Save state before deleting the session, as that causes some
1171 windows to be destroyed before their visible state can be
1174 save_ardour_state ();
1176 close_all_dialogs ();
1179 _session->set_clean ();
1180 _session->remove_pending_capture_state ();
1185 halt_connection.disconnect ();
1186 AudioEngine::instance()->stop ();
1187 #ifdef WINDOWS_VST_SUPPORT
1188 fst_stop_threading();
1194 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1196 ArdourDialog window (_("Unsaved Session"));
1197 Gtk::HBox dhbox; // the hbox for the image and text
1198 Gtk::Label prompt_label;
1199 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
1203 assert (actions.size() >= 3);
1205 window.add_button (actions[0], RESPONSE_REJECT);
1206 window.add_button (actions[1], RESPONSE_APPLY);
1207 window.add_button (actions[2], RESPONSE_ACCEPT);
1209 window.set_default_response (RESPONSE_ACCEPT);
1211 Gtk::Button noquit_button (msg);
1212 noquit_button.set_name ("EditorGTKButton");
1216 if (_session->snap_name() == _session->name()) {
1217 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?"),
1218 _session->snap_name());
1220 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?"),
1221 _session->snap_name());
1224 prompt_label.set_text (prompt);
1225 prompt_label.set_name (X_("PrompterLabel"));
1226 prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1228 dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1229 dhbox.set_homogeneous (false);
1230 dhbox.pack_start (*dimage, false, false, 5);
1231 dhbox.pack_start (prompt_label, true, false, 5);
1232 window.get_vbox()->pack_start (dhbox);
1234 window.set_name (_("Prompter"));
1235 window.set_modal (true);
1236 window.set_resizable (false);
1239 prompt_label.show();
1244 ResponseType r = (ResponseType) window.run();
1249 case RESPONSE_ACCEPT: // save and get out of here
1251 case RESPONSE_APPLY: // get out of here
1262 ARDOUR_UI::every_second ()
1265 update_xrun_count ();
1266 update_buffer_load ();
1267 update_disk_space ();
1268 update_timecode_format ();
1269 update_peak_thread_work ();
1271 if (nsm && nsm->is_active ()) {
1274 if (!_was_dirty && _session->dirty ()) {
1278 else if (_was_dirty && !_session->dirty ()){
1286 ARDOUR_UI::every_point_one_seconds ()
1288 // TODO get rid of this..
1289 // ShuttleControl is updated directly via TransportStateChange signal
1293 ARDOUR_UI::every_point_zero_something_seconds ()
1295 // august 2007: actual update frequency: 25Hz (40ms), not 100Hz
1297 if (editor_meter && UIConfiguration::instance().get_show_editor_meter()) {
1298 float mpeak = editor_meter->update_meters();
1299 if (mpeak > editor_meter_max_peak) {
1300 if (mpeak >= UIConfiguration::instance().get_meter_peak()) {
1301 editor_meter_peak_display.set_active_state ( Gtkmm2ext::ExplicitActive );
1308 ARDOUR_UI::set_fps_timeout_connection ()
1310 unsigned int interval = 40;
1311 if (!_session) return;
1312 if (_session->timecode_frames_per_second() != 0) {
1313 /* ideally we'll use a select() to sleep and not accumulate
1314 * idle time to provide a regular periodic signal.
1315 * See linux_vst_gui_support.cc 'elapsed_time_ms'.
1316 * However, that'll require a dedicated thread and cross-thread
1317 * signals to the GUI Thread..
1319 interval = floor(500. /* update twice per FPS, since Glib::signal_timeout is very irregular */
1320 * _session->frame_rate() / _session->nominal_frame_rate()
1321 / _session->timecode_frames_per_second()
1323 #ifdef PLATFORM_WINDOWS
1324 // the smallest windows scheduler time-slice is ~15ms.
1325 // periodic GUI timeouts shorter than that will cause
1326 // WaitForSingleObject to spinlock (100% of one CPU Core)
1327 // and gtk never enters idle mode.
1328 // also changing timeBeginPeriod(1) does not affect that in
1329 // any beneficial way, so we just limit the max rate for now.
1330 interval = std::max(30u, interval); // at most ~33Hz.
1332 interval = std::max(8u, interval); // at most 120Hz.
1335 fps_connection.disconnect();
1336 Timers::set_fps_interval (interval);
1340 ARDOUR_UI::update_sample_rate (framecnt_t)
1344 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
1346 if (!AudioEngine::instance()->connected()) {
1348 snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1352 framecnt_t rate = AudioEngine::instance()->sample_rate();
1355 /* no sample rate available */
1356 snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1359 if (fmod (rate, 1000.0) != 0.0) {
1360 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
1361 (float) rate / 1000.0f,
1362 (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1364 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
1366 (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1370 sample_rate_label.set_markup (buf);
1374 ARDOUR_UI::update_format ()
1377 format_label.set_text ("");
1382 s << _("File:") << X_(" <span foreground=\"green\">");
1384 switch (_session->config.get_native_file_header_format ()) {
1416 switch (_session->config.get_native_file_data_format ()) {
1430 format_label.set_markup (s.str ());
1434 ARDOUR_UI::update_xrun_count ()
1438 /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1439 should also be changed.
1443 const unsigned int x = _session->get_xrun_count ();
1445 snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">>10K</span>"), X_("red"));
1447 snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">%u</span>"), x > 0 ? X_("red") : X_("green"), x);
1450 snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">?</span>"), X_("yellow"));
1452 xrun_label.set_markup (buf);
1453 set_tip (xrun_label, _("Audio dropouts. Shift+click to reset"));
1457 ARDOUR_UI::update_cpu_load ()
1461 /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1462 should also be changed.
1465 double const c = AudioEngine::instance()->get_dsp_load ();
1466 snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c);
1467 cpu_load_label.set_markup (buf);
1471 ARDOUR_UI::update_peak_thread_work ()
1474 const int c = SourceFactory::peak_work_queue_length ();
1476 snprintf (buf, sizeof (buf), _("PkBld: <span foreground=\"%s\">%d</span>"), c >= 2 ? X_("red") : X_("green"), c);
1477 peak_thread_work_label.set_markup (buf);
1479 peak_thread_work_label.set_markup (X_(""));
1484 ARDOUR_UI::update_buffer_load ()
1488 uint32_t const playback = _session ? _session->playback_load () : 100;
1489 uint32_t const capture = _session ? _session->capture_load () : 100;
1491 /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1492 should also be changed.
1498 _("Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">%" PRIu32 "%%</span> "
1499 "<span foreground=\"green\">c:</span><span foreground=\"%s\">%" PRIu32 "%%</span>"),
1500 playback <= 5 ? X_("red") : X_("green"),
1502 capture <= 5 ? X_("red") : X_("green"),
1506 buffer_load_label.set_markup (buf);
1508 buffer_load_label.set_text ("");
1513 ARDOUR_UI::count_recenabled_streams (Route& route)
1515 Track* track = dynamic_cast<Track*>(&route);
1516 if (track && track->record_enabled()) {
1517 rec_enabled_streams += track->n_inputs().n_total();
1522 ARDOUR_UI::update_disk_space()
1524 if (_session == 0) {
1528 boost::optional<framecnt_t> opt_frames = _session->available_capture_duration();
1530 framecnt_t fr = _session->frame_rate();
1533 /* skip update - no SR available */
1538 /* Available space is unknown */
1539 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
1540 } else if (opt_frames.get_value_or (0) == max_framecnt) {
1541 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">24hrs+</span>"));
1543 rec_enabled_streams = 0;
1544 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
1546 framecnt_t frames = opt_frames.get_value_or (0);
1548 if (rec_enabled_streams) {
1549 frames /= rec_enabled_streams;
1556 hrs = frames / (fr * 3600);
1559 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">>24 hrs</span>"));
1561 frames -= hrs * fr * 3600;
1562 mins = frames / (fr * 60);
1563 frames -= mins * fr * 60;
1566 bool const low = (hrs == 0 && mins <= 30);
1570 _("Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"),
1571 low ? X_("red") : X_("green"),
1577 disk_space_label.set_markup (buf);
1581 ARDOUR_UI::update_timecode_format ()
1587 TimecodeSlave* tcslave;
1588 SyncSource sync_src = Config->get_sync_source();
1590 if ((sync_src == LTC || sync_src == MTC) && (tcslave = dynamic_cast<TimecodeSlave*>(_session->slave())) != 0) {
1591 matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format());
1596 snprintf (buf, sizeof (buf), S_("Timecode|TC: <span foreground=\"%s\">%s</span>"),
1597 matching ? X_("green") : X_("red"),
1598 Timecode::timecode_format_name (_session->config.get_timecode_format()).c_str());
1600 snprintf (buf, sizeof (buf), "TC: n/a");
1603 timecode_format_label.set_markup (buf);
1607 ARDOUR_UI::update_wall_clock ()
1611 static int last_min = -1;
1614 tm_now = localtime (&now);
1615 if (last_min != tm_now->tm_min) {
1617 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1618 wall_clock_label.set_text (buf);
1619 last_min = tm_now->tm_min;
1626 ARDOUR_UI::open_recent_session ()
1628 bool can_return = (_session != 0);
1630 SessionDialog recent_session_dialog;
1634 ResponseType r = (ResponseType) recent_session_dialog.run ();
1637 case RESPONSE_ACCEPT:
1641 recent_session_dialog.hide();
1648 recent_session_dialog.hide();
1652 std::string path = recent_session_dialog.session_folder();
1653 std::string state = recent_session_dialog.session_name (should_be_new);
1655 if (should_be_new == true) {
1659 _session_is_new = false;
1661 if (load_session (path, state) == 0) {
1670 ARDOUR_UI::check_audioengine (Gtk::Window& parent)
1672 if (!AudioEngine::instance()->connected()) {
1673 MessageDialog msg (parent, string_compose (
1674 _("%1 is not connected to any audio backend.\n"
1675 "You cannot open or close sessions in this condition"),
1677 pop_back_splash (msg);
1685 ARDOUR_UI::open_session ()
1687 if (!check_audioengine(*editor)) {
1691 /* ardour sessions are folders */
1692 Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1693 open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1694 open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1695 open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1698 string session_parent_dir = Glib::path_get_dirname(_session->path());
1699 open_session_selector.set_current_folder(session_parent_dir);
1701 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1704 Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1706 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1707 string default_session_folder = Config->get_default_session_parent_dir();
1708 open_session_selector.add_shortcut_folder (default_session_folder);
1710 catch (Glib::Error & e) {
1711 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1714 FileFilter session_filter;
1715 session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1716 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1717 open_session_selector.add_filter (session_filter);
1718 open_session_selector.set_filter (session_filter);
1720 int response = open_session_selector.run();
1721 open_session_selector.hide ();
1723 if (response == Gtk::RESPONSE_CANCEL) {
1727 string session_path = open_session_selector.get_filename();
1731 if (session_path.length() > 0) {
1732 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1733 _session_is_new = isnew;
1734 load_session (path, name);
1741 ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& output, RouteGroup* route_group,
1742 uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
1744 list<boost::shared_ptr<MidiTrack> > tracks;
1746 if (_session == 0) {
1747 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1752 tracks = _session->new_midi_track (input, output, instrument, ARDOUR::Normal, route_group, how_many, name_template);
1754 if (tracks.size() != how_many) {
1755 error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
1760 MessageDialog msg (*editor,
1761 string_compose (_("There are insufficient ports available\n\
1762 to create a new track or bus.\n\
1763 You should save %1, exit and\n\
1764 restart with more ports."), PROGRAM_NAME));
1771 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
1773 ChanCount one_midi_channel;
1774 one_midi_channel.set (DataType::MIDI, 1);
1777 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, instrument);
1782 ARDOUR_UI::session_add_audio_route (
1784 int32_t input_channels,
1785 int32_t output_channels,
1786 ARDOUR::TrackMode mode,
1787 RouteGroup* route_group,
1789 string const & name_template
1792 list<boost::shared_ptr<AudioTrack> > tracks;
1795 if (_session == 0) {
1796 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1802 tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
1804 if (tracks.size() != how_many) {
1805 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
1811 routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
1813 if (routes.size() != how_many) {
1814 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
1821 MessageDialog msg (*editor,
1822 string_compose (_("There are insufficient ports available\n\
1823 to create a new track or bus.\n\
1824 You should save %1, exit and\n\
1825 restart with more ports."), PROGRAM_NAME));
1826 pop_back_splash (msg);
1832 ARDOUR_UI::transport_goto_start ()
1835 _session->goto_start();
1837 /* force displayed area in editor to start no matter
1838 what "follow playhead" setting is.
1842 editor->center_screen (_session->current_start_frame ());
1848 ARDOUR_UI::transport_goto_zero ()
1851 _session->request_locate (0);
1853 /* force displayed area in editor to start no matter
1854 what "follow playhead" setting is.
1858 editor->reset_x_origin (0);
1864 ARDOUR_UI::transport_goto_wallclock ()
1866 if (_session && editor) {
1873 localtime_r (&now, &tmnow);
1875 framecnt_t frame_rate = _session->frame_rate();
1877 if (frame_rate == 0) {
1878 /* no frame rate available */
1882 frames = tmnow.tm_hour * (60 * 60 * frame_rate);
1883 frames += tmnow.tm_min * (60 * frame_rate);
1884 frames += tmnow.tm_sec * frame_rate;
1886 _session->request_locate (frames, _session->transport_rolling ());
1888 /* force displayed area in editor to start no matter
1889 what "follow playhead" setting is.
1893 editor->center_screen (frames);
1899 ARDOUR_UI::transport_goto_end ()
1902 framepos_t const frame = _session->current_end_frame();
1903 _session->request_locate (frame);
1905 /* force displayed area in editor to start no matter
1906 what "follow playhead" setting is.
1910 editor->center_screen (frame);
1916 ARDOUR_UI::transport_stop ()
1922 if (_session->is_auditioning()) {
1923 _session->cancel_audition ();
1927 _session->request_stop (false, true);
1930 /** Check if any tracks are record enabled. If none are, record enable all of them.
1931 * @return true if track record-enabled status was changed, false otherwise.
1934 ARDOUR_UI::trx_record_enable_all_tracks ()
1940 boost::shared_ptr<RouteList> rl = _session->get_tracks ();
1941 bool none_record_enabled = true;
1943 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
1944 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
1947 if (t->record_enabled()) {
1948 none_record_enabled = false;
1953 if (none_record_enabled) {
1954 _session->set_record_enabled (rl, true, Session::rt_cleanup);
1957 return none_record_enabled;
1961 ARDOUR_UI::transport_record (bool roll)
1964 switch (_session->record_status()) {
1965 case Session::Disabled:
1966 if (_session->ntracks() == 0) {
1967 MessageDialog msg (*editor, _("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."));
1971 if (Profile->get_trx()) {
1972 roll = trx_record_enable_all_tracks ();
1974 _session->maybe_enable_record ();
1979 case Session::Recording:
1981 _session->request_stop();
1983 _session->disable_record (false, true);
1987 case Session::Enabled:
1988 _session->disable_record (false, true);
1994 ARDOUR_UI::transport_roll ()
2000 if (_session->is_auditioning()) {
2005 if (_session->config.get_external_sync()) {
2006 switch (Config->get_sync_source()) {
2010 /* transport controlled by the master */
2016 bool rolling = _session->transport_rolling();
2018 if (_session->get_play_loop()) {
2020 /* If loop playback is not a mode, then we should cancel
2021 it when this action is requested. If it is a mode
2022 we just leave it in place.
2025 if (!Config->get_loop_is_mode()) {
2026 /* XXX it is not possible to just leave seamless loop and keep
2027 playing at present (nov 4th 2009)
2029 if (!Config->get_seamless_loop()) {
2030 /* stop loop playback and stop rolling */
2031 _session->request_play_loop (false, true);
2032 } else if (rolling) {
2033 /* stop loop playback but keep rolling */
2034 _session->request_play_loop (false, false);
2038 } else if (_session->get_play_range () ) {
2039 /* stop playing a range if we currently are */
2040 _session->request_play_range (0, true);
2044 _session->request_transport_speed (1.0f);
2049 ARDOUR_UI::get_smart_mode() const
2051 return ( editor->get_smart_mode() );
2056 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2062 if (_session->is_auditioning()) {
2063 _session->cancel_audition ();
2067 if (_session->config.get_external_sync()) {
2068 switch (Config->get_sync_source()) {
2072 /* transport controlled by the master */
2077 bool rolling = _session->transport_rolling();
2078 bool affect_transport = true;
2080 if (rolling && roll_out_of_bounded_mode) {
2081 /* drop out of loop/range playback but leave transport rolling */
2082 if (_session->get_play_loop()) {
2083 if (_session->actively_recording()) {
2085 /* just stop using the loop, then actually stop
2088 _session->request_play_loop (false, affect_transport);
2091 if (Config->get_seamless_loop()) {
2092 /* the disk buffers contain copies of the loop - we can't
2093 just keep playing, so stop the transport. the user
2094 can restart as they wish.
2096 affect_transport = true;
2098 /* disk buffers are normal, so we can keep playing */
2099 affect_transport = false;
2101 _session->request_play_loop (false, affect_transport);
2103 } else if (_session->get_play_range ()) {
2104 affect_transport = false;
2105 _session->request_play_range (0, true);
2109 if (affect_transport) {
2111 _session->request_stop (with_abort, true);
2113 /* the only external sync condition we can be in here
2114 * would be Engine (JACK) sync, in which case we still
2118 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
2119 _session->request_play_range (&editor->get_selection().time, true);
2120 _session->set_requested_return_frame( editor->get_selection().time.front().start ); //force an auto-return here
2122 _session->request_transport_speed (1.0f);
2128 ARDOUR_UI::toggle_session_auto_loop ()
2134 Location * looploc = _session->locations()->auto_loop_location();
2140 if (_session->get_play_loop()) {
2142 /* looping enabled, our job is to disable it */
2144 _session->request_play_loop (false);
2148 /* looping not enabled, our job is to enable it.
2150 loop-is-NOT-mode: this action always starts the transport rolling.
2151 loop-IS-mode: this action simply sets the loop play mechanism, but
2152 does not start transport.
2154 if (Config->get_loop_is_mode()) {
2155 _session->request_play_loop (true, false);
2157 _session->request_play_loop (true, true);
2161 //show the loop markers
2162 looploc->set_hidden (false, this);
2166 ARDOUR_UI::transport_play_selection ()
2172 editor->play_selection ();
2176 ARDOUR_UI::transport_play_preroll ()
2181 editor->play_with_preroll ();
2185 ARDOUR_UI::transport_rewind (int option)
2187 float current_transport_speed;
2190 current_transport_speed = _session->transport_speed();
2192 if (current_transport_speed >= 0.0f) {
2195 _session->request_transport_speed (-1.0f);
2198 _session->request_transport_speed (-4.0f);
2201 _session->request_transport_speed (-0.5f);
2206 _session->request_transport_speed (current_transport_speed * 1.5f);
2212 ARDOUR_UI::transport_forward (int option)
2218 float current_transport_speed = _session->transport_speed();
2220 if (current_transport_speed <= 0.0f) {
2223 _session->request_transport_speed (1.0f);
2226 _session->request_transport_speed (4.0f);
2229 _session->request_transport_speed (0.5f);
2234 _session->request_transport_speed (current_transport_speed * 1.5f);
2239 ARDOUR_UI::toggle_record_enable (uint32_t rid)
2245 boost::shared_ptr<Route> r;
2247 if ((r = _session->route_by_remote_id (rid)) != 0) {
2249 boost::shared_ptr<Track> t;
2251 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2252 t->set_record_enabled (!t->record_enabled(), Controllable::UseGroup);
2258 ARDOUR_UI::map_transport_state ()
2261 auto_loop_button.unset_active_state ();
2262 play_selection_button.unset_active_state ();
2263 roll_button.unset_active_state ();
2264 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2268 shuttle_box->map_transport_state ();
2270 float sp = _session->transport_speed();
2276 if (_session->get_play_range()) {
2278 play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2279 roll_button.unset_active_state ();
2280 auto_loop_button.unset_active_state ();
2282 } else if (_session->get_play_loop ()) {
2284 auto_loop_button.set_active (true);
2285 play_selection_button.set_active (false);
2286 if (Config->get_loop_is_mode()) {
2287 roll_button.set_active (true);
2289 roll_button.set_active (false);
2294 roll_button.set_active (true);
2295 play_selection_button.set_active (false);
2296 auto_loop_button.set_active (false);
2299 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2300 /* light up both roll and play-selection if they are joined */
2301 roll_button.set_active (true);
2302 play_selection_button.set_active (true);
2305 stop_button.set_active (false);
2309 stop_button.set_active (true);
2310 roll_button.set_active (false);
2311 play_selection_button.set_active (false);
2312 if (Config->get_loop_is_mode ()) {
2313 auto_loop_button.set_active (_session->get_play_loop());
2315 auto_loop_button.set_active (false);
2317 update_disk_space ();
2322 ARDOUR_UI::blink_handler (bool blink_on)
2324 transport_rec_enable_blink (blink_on);
2325 solo_blink (blink_on);
2326 sync_blink (blink_on);
2327 audition_blink (blink_on);
2328 feedback_blink (blink_on);
2329 error_blink (blink_on);
2333 ARDOUR_UI::update_clocks ()
2335 if (!_session) return;
2337 if (editor && !editor->dragging_playhead()) {
2338 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2343 ARDOUR_UI::start_clocking ()
2345 if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2346 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2348 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2353 ARDOUR_UI::stop_clocking ()
2355 clock_signal_connection.disconnect ();
2359 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2363 snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2365 label->set_text (buf);
2366 bar->set_fraction (fraction);
2368 /* process events, redraws, etc. */
2370 while (gtk_events_pending()) {
2371 gtk_main_iteration ();
2374 return true; /* continue with save-as */
2378 ARDOUR_UI::save_session_as ()
2384 if (!save_as_dialog) {
2385 save_as_dialog = new SaveAsDialog;
2388 save_as_dialog->set_name (_session->name());
2390 int response = save_as_dialog->run ();
2392 save_as_dialog->hide ();
2395 case Gtk::RESPONSE_OK:
2404 sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2405 sa.new_name = save_as_dialog->new_name ();
2406 sa.switch_to = save_as_dialog->switch_to();
2407 sa.copy_media = save_as_dialog->copy_media();
2408 sa.copy_external = save_as_dialog->copy_external();
2409 sa.include_media = save_as_dialog->include_media ();
2411 /* Only bother with a progress dialog if we're going to copy
2412 media into the save-as target. Without that choice, this
2413 will be very fast because we're only talking about a few kB's to
2414 perhaps a couple of MB's of data.
2417 ArdourDialog progress_dialog (_("Save As"), true);
2419 if (sa.include_media && sa.copy_media) {
2422 Gtk::ProgressBar progress_bar;
2424 progress_dialog.get_vbox()->pack_start (label);
2425 progress_dialog.get_vbox()->pack_start (progress_bar);
2427 progress_bar.show ();
2429 /* this signal will be emitted from within this, the calling thread,
2430 * after every file is copied. It provides information on percentage
2431 * complete (in terms of total data to copy), the number of files
2432 * copied so far, and the total number to copy.
2437 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
2439 progress_dialog.show_all ();
2440 progress_dialog.present ();
2443 if (_session->save_as (sa)) {
2445 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2449 if (!sa.include_media) {
2450 unload_session (false);
2451 load_session (sa.final_session_folder_name, sa.new_name);
2456 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2460 struct tm local_time;
2463 localtime_r (&n, &local_time);
2464 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2466 save_state (timebuf, switch_to_it);
2471 ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
2475 prompter.get_result (snapname);
2477 bool do_save = (snapname.length() != 0);
2480 char illegal = Session::session_name_is_legal(snapname);
2482 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2483 "snapshot names may not contain a '%1' character"), illegal));
2489 vector<std::string> p;
2490 get_state_files_in_directory (_session->session_directory().root_path(), p);
2491 vector<string> n = get_file_names_no_extension (p);
2493 if (find (n.begin(), n.end(), snapname) != n.end()) {
2495 do_save = overwrite_file_dialog (prompter,
2496 _("Confirm Snapshot Overwrite"),
2497 _("A snapshot already exists with that name. Do you want to overwrite it?"));
2501 save_state (snapname, switch_to_it);
2511 /** Ask the user for the name of a new snapshot and then take it.
2515 ARDOUR_UI::snapshot_session (bool switch_to_it)
2517 ArdourPrompter prompter (true);
2519 prompter.set_name ("Prompter");
2520 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2522 prompter.set_title (_("Save as..."));
2523 prompter.set_prompt (_("New session name"));
2525 prompter.set_title (_("Take Snapshot"));
2526 prompter.set_prompt (_("Name of new snapshot"));
2530 prompter.set_initial_text (_session->snap_name());
2534 struct tm local_time;
2537 localtime_r (&n, &local_time);
2538 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2539 prompter.set_initial_text (timebuf);
2542 bool finished = false;
2544 switch (prompter.run()) {
2545 case RESPONSE_ACCEPT:
2547 finished = process_snapshot_session_prompter (prompter, switch_to_it);
2558 /** Ask the user for a new session name and then rename the session to it.
2562 ARDOUR_UI::rename_session ()
2568 ArdourPrompter prompter (true);
2571 prompter.set_name ("Prompter");
2572 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2573 prompter.set_title (_("Rename Session"));
2574 prompter.set_prompt (_("New session name"));
2577 switch (prompter.run()) {
2578 case RESPONSE_ACCEPT:
2580 prompter.get_result (name);
2582 bool do_rename = (name.length() != 0);
2585 char illegal = Session::session_name_is_legal (name);
2588 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2589 "session names may not contain a '%1' character"), illegal));
2594 switch (_session->rename (name)) {
2596 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2597 msg.set_position (WIN_POS_MOUSE);
2605 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2606 msg.set_position (WIN_POS_MOUSE);
2622 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2624 if (!_session || _session->deletion_in_progress()) {
2628 XMLNode* node = new XMLNode (X_("UI"));
2630 WM::Manager::instance().add_state (*node);
2632 node->add_child_nocopy (gui_object_state->get_state());
2634 _session->add_extra_xml (*node);
2636 if (export_video_dialog) {
2637 _session->add_extra_xml (export_video_dialog->get_state());
2640 save_state_canfail (name, switch_to_it);
2644 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2649 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2654 save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2659 ARDOUR_UI::primary_clock_value_changed ()
2662 _session->request_locate (primary_clock->current_time ());
2667 ARDOUR_UI::big_clock_value_changed ()
2670 _session->request_locate (big_clock->current_time ());
2675 ARDOUR_UI::secondary_clock_value_changed ()
2678 _session->request_locate (secondary_clock->current_time ());
2683 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2685 if (_session == 0) {
2689 if (_session->step_editing()) {
2693 Session::RecordState const r = _session->record_status ();
2694 bool const h = _session->have_rec_enabled_track ();
2696 if (r == Session::Enabled || (r == Session::Recording && !h)) {
2698 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2700 rec_button.set_active_state (Gtkmm2ext::Off);
2702 } else if (r == Session::Recording && h) {
2703 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2705 rec_button.unset_active_state ();
2710 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2714 prompter.get_result (name);
2716 if (name.length()) {
2717 int failed = _session->save_template (name);
2719 if (failed == -2) { /* file already exists. */
2720 bool overwrite = overwrite_file_dialog (prompter,
2721 _("Confirm Template Overwrite"),
2722 _("A template already exists with that name. Do you want to overwrite it?"));
2725 _session->save_template (name, true);
2737 ARDOUR_UI::save_template ()
2739 ArdourPrompter prompter (true);
2741 if (!check_audioengine(*editor)) {
2745 prompter.set_name (X_("Prompter"));
2746 prompter.set_title (_("Save Template"));
2747 prompter.set_prompt (_("Name for template:"));
2748 prompter.set_initial_text(_session->name() + _("-template"));
2749 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2751 bool finished = false;
2753 switch (prompter.run()) {
2754 case RESPONSE_ACCEPT:
2755 finished = process_save_template_prompter (prompter);
2766 ARDOUR_UI::edit_metadata ()
2768 SessionMetadataEditor dialog;
2769 dialog.set_session (_session);
2770 dialog.grab_focus ();
2775 ARDOUR_UI::import_metadata ()
2777 SessionMetadataImporter dialog;
2778 dialog.set_session (_session);
2783 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2785 std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2787 MessageDialog msg (str,
2789 Gtk::MESSAGE_WARNING,
2790 Gtk::BUTTONS_YES_NO,
2794 msg.set_name (X_("OpenExistingDialog"));
2795 msg.set_title (_("Open Existing Session"));
2796 msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2797 msg.set_position (Gtk::WIN_POS_CENTER);
2798 pop_back_splash (msg);
2800 switch (msg.run()) {
2809 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
2811 BusProfile bus_profile;
2813 if (nsm || Profile->get_sae()) {
2815 bus_profile.master_out_channels = 2;
2816 bus_profile.input_ac = AutoConnectPhysical;
2817 bus_profile.output_ac = AutoConnectMaster;
2818 bus_profile.requested_physical_in = 0; // use all available
2819 bus_profile.requested_physical_out = 0; // use all available
2823 /* get settings from advanced section of NSD */
2825 if (sd.create_master_bus()) {
2826 bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
2828 bus_profile.master_out_channels = 0;
2831 if (sd.connect_inputs()) {
2832 bus_profile.input_ac = AutoConnectPhysical;
2834 bus_profile.input_ac = AutoConnectOption (0);
2837 bus_profile.output_ac = AutoConnectOption (0);
2839 if (sd.connect_outputs ()) {
2840 if (sd.connect_outs_to_master()) {
2841 bus_profile.output_ac = AutoConnectMaster;
2842 } else if (sd.connect_outs_to_physical()) {
2843 bus_profile.output_ac = AutoConnectPhysical;
2847 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
2848 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
2851 if (build_session (session_path, session_name, bus_profile)) {
2859 ARDOUR_UI::load_from_application_api (const std::string& path)
2861 ARDOUR_COMMAND_LINE::session_name = path;
2862 /* Cancel SessionDialog if it's visible to make OSX delegates work.
2864 * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
2866 * - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
2867 * -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
2868 * - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
2869 * -> SessionDialog is not displayed
2872 if (_session_dialog) {
2873 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
2874 std::string session_path = path;
2875 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
2876 session_path = Glib::path_get_dirname (session_path);
2878 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
2879 _session_dialog->set_provided_session (session_name, session_path);
2880 _session_dialog->response (RESPONSE_NONE);
2881 _session_dialog->hide();
2886 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2887 /* /path/to/foo => /path/to/foo, foo */
2888 rv = load_session (path, basename_nosuffix (path));
2890 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2891 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2894 // if load_session fails -> pop up SessionDialog.
2896 ARDOUR_COMMAND_LINE::session_name = "";
2898 if (get_session_parameters (true, false)) {
2902 goto_editor_window ();
2906 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2908 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2910 string session_name;
2911 string session_path;
2912 string template_name;
2914 bool likely_new = false;
2915 bool cancel_not_quit;
2917 /* deal with any existing DIRTY session now, rather than later. don't
2918 * treat a non-dirty session this way, so that it stays visible
2919 * as we bring up the new session dialog.
2922 if (_session && ARDOUR_UI::instance()->video_timeline) {
2923 ARDOUR_UI::instance()->video_timeline->sync_session_state();
2926 /* if there is already a session, relabel the button
2927 on the SessionDialog so that we don't Quit directly
2929 cancel_not_quit = (_session != 0);
2931 if (_session && _session->dirty()) {
2932 if (unload_session (false)) {
2933 /* unload cancelled by user */
2936 ARDOUR_COMMAND_LINE::session_name = "";
2939 if (!load_template.empty()) {
2940 should_be_new = true;
2941 template_name = load_template;
2944 session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
2945 session_path = ARDOUR_COMMAND_LINE::session_name;
2947 if (!session_path.empty()) {
2948 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
2949 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
2950 /* session/snapshot file, change path to be dir */
2951 session_path = Glib::path_get_dirname (session_path);
2956 SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
2958 _session_dialog = &session_dialog;
2961 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2963 /* if they named a specific statefile, use it, otherwise they are
2964 just giving a session folder, and we want to use it as is
2965 to find the session.
2968 string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
2970 if (suffix != string::npos) {
2971 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2972 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
2973 session_name = Glib::path_get_basename (session_name);
2975 session_path = ARDOUR_COMMAND_LINE::session_name;
2976 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2981 session_dialog.clear_given ();
2984 if (should_be_new || session_name.empty()) {
2985 /* need the dialog to get info from user */
2987 cerr << "run dialog\n";
2989 switch (session_dialog.run()) {
2990 case RESPONSE_ACCEPT:
2993 /* this is used for async * app->ShouldLoad(). */
2994 continue; // while loop
2997 if (quit_on_cancel) {
2998 // JE - Currently (July 2014) this section can only get reached if the
2999 // user quits from the main 'Session Setup' dialog (i.e. reaching this
3000 // point does NOT indicate an abnormal termination). Therefore, let's
3001 // behave gracefully (i.e. let's do some cleanup) before we call exit()
3003 pthread_cancel_all ();
3011 session_dialog.hide ();
3014 /* if we run the startup dialog again, offer more than just "new session" */
3016 should_be_new = false;
3018 session_name = session_dialog.session_name (likely_new);
3019 session_path = session_dialog.session_folder ();
3025 string::size_type suffix = session_name.find (statefile_suffix);
3027 if (suffix != string::npos) {
3028 session_name = session_name.substr (0, suffix);
3031 /* this shouldn't happen, but we catch it just in case it does */
3033 if (session_name.empty()) {
3037 if (session_dialog.use_session_template()) {
3038 template_name = session_dialog.session_template_name();
3039 _session_is_new = true;
3042 if (session_name[0] == G_DIR_SEPARATOR ||
3043 #ifdef PLATFORM_WINDOWS
3044 (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3046 (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3047 (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3052 /* absolute path or cwd-relative path specified for session name: infer session folder
3053 from what was given.
3056 session_path = Glib::path_get_dirname (session_name);
3057 session_name = Glib::path_get_basename (session_name);
3061 session_path = session_dialog.session_folder();
3063 char illegal = Session::session_name_is_legal (session_name);
3066 MessageDialog msg (session_dialog,
3067 string_compose (_("To ensure compatibility with various systems\n"
3068 "session names may not contain a '%1' character"),
3071 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3076 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3079 if (likely_new && !nsm) {
3081 std::string existing = Glib::build_filename (session_path, session_name);
3083 if (!ask_about_loading_existing_session (existing)) {
3084 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3089 _session_is_new = false;
3094 pop_back_splash (session_dialog);
3095 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3097 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3101 char illegal = Session::session_name_is_legal(session_name);
3104 pop_back_splash (session_dialog);
3105 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3106 "session names may not contain a '%1' character"), illegal));
3108 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3112 _session_is_new = true;
3115 if (likely_new && template_name.empty()) {
3117 ret = build_session_from_dialog (session_dialog, session_path, session_name);
3121 ret = load_session (session_path, session_name, template_name);
3124 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3128 if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3129 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3133 /* clear this to avoid endless attempts to load the
3137 ARDOUR_COMMAND_LINE::session_name = "";
3141 _session_dialog = NULL;
3147 ARDOUR_UI::close_session()
3149 if (!check_audioengine(*editor)) {
3153 if (unload_session (true)) {
3157 ARDOUR_COMMAND_LINE::session_name = "";
3159 if (get_session_parameters (true, false)) {
3163 goto_editor_window ();
3166 /** @param snap_name Snapshot name (without .ardour suffix).
3167 * @return -2 if the load failed because we are not connected to the AudioEngine.
3170 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3172 Session *new_session;
3177 unload_status = unload_session ();
3179 if (unload_status < 0) {
3181 } else if (unload_status > 0) {
3187 session_loaded = false;
3189 loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3192 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3195 /* this one is special */
3197 catch (AudioEngine::PortRegistrationFailure& err) {
3199 MessageDialog msg (err.what(),
3202 Gtk::BUTTONS_CLOSE);
3204 msg.set_title (_("Port Registration Error"));
3205 msg.set_secondary_text (_("Click the Close button to try again."));
3206 msg.set_position (Gtk::WIN_POS_CENTER);
3207 pop_back_splash (msg);
3210 int response = msg.run ();
3215 case RESPONSE_CANCEL:
3222 catch (SessionException e) {
3223 MessageDialog msg (string_compose(
3224 _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3225 path, snap_name, e.what()),
3230 msg.set_title (_("Loading Error"));
3231 msg.set_position (Gtk::WIN_POS_CENTER);
3232 pop_back_splash (msg);
3244 MessageDialog msg (string_compose(
3245 _("Session \"%1 (snapshot %2)\" did not load successfully"),
3251 msg.set_title (_("Loading Error"));
3252 msg.set_position (Gtk::WIN_POS_CENTER);
3253 pop_back_splash (msg);
3265 list<string> const u = new_session->unknown_processors ();
3267 MissingPluginDialog d (_session, u);
3272 if (!new_session->writable()) {
3273 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3278 msg.set_title (_("Read-only Session"));
3279 msg.set_position (Gtk::WIN_POS_CENTER);
3280 pop_back_splash (msg);
3287 /* Now the session been created, add the transport controls */
3288 new_session->add_controllable(roll_controllable);
3289 new_session->add_controllable(stop_controllable);
3290 new_session->add_controllable(goto_start_controllable);
3291 new_session->add_controllable(goto_end_controllable);
3292 new_session->add_controllable(auto_loop_controllable);
3293 new_session->add_controllable(play_selection_controllable);
3294 new_session->add_controllable(rec_controllable);
3296 set_session (new_session);
3298 session_loaded = true;
3300 goto_editor_window ();
3303 _session->set_clean ();
3306 #ifdef WINDOWS_VST_SUPPORT
3307 fst_stop_threading();
3311 Timers::TimerSuspender t;
3315 #ifdef WINDOWS_VST_SUPPORT
3316 fst_start_threading();
3325 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3327 Session *new_session;
3330 session_loaded = false;
3331 x = unload_session ();
3339 _session_is_new = true;
3342 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3345 catch (SessionException e) {
3347 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3348 msg.set_title (_("Loading Error"));
3349 msg.set_position (Gtk::WIN_POS_CENTER);
3350 pop_back_splash (msg);
3356 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3357 msg.set_title (_("Loading Error"));
3358 msg.set_position (Gtk::WIN_POS_CENTER);
3359 pop_back_splash (msg);
3364 /* Give the new session the default GUI state, if such things exist */
3367 n = Config->instant_xml (X_("Editor"));
3369 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3370 new_session->add_instant_xml (*n, false);
3372 n = Config->instant_xml (X_("Mixer"));
3374 new_session->add_instant_xml (*n, false);
3377 /* Put the playhead at 0 and scroll fully left */
3378 n = new_session->instant_xml (X_("Editor"));
3380 n->add_property (X_("playhead"), X_("0"));
3381 n->add_property (X_("left-frame"), X_("0"));
3384 set_session (new_session);
3386 session_loaded = true;
3388 new_session->save_state(new_session->name());
3394 ARDOUR_UI::launch_chat ()
3396 MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3398 dialog.set_title (_("About the Chat"));
3399 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."));
3401 switch (dialog.run()) {
3404 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3405 #elif defined PLATFORM_WINDOWS
3406 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3408 open_uri("http://webchat.freenode.net/?channels=ardour");
3417 ARDOUR_UI::launch_manual ()
3419 PBD::open_uri (Config->get_tutorial_manual_url());
3423 ARDOUR_UI::launch_reference ()
3425 PBD::open_uri (Config->get_reference_manual_url());
3429 ARDOUR_UI::launch_tracker ()
3431 PBD::open_uri ("http://tracker.ardour.org");
3435 ARDOUR_UI::launch_subscribe ()
3437 PBD::open_uri ("https://community.ardour.org/s/subscribe");
3441 ARDOUR_UI::launch_cheat_sheet ()
3444 PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3446 PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3451 ARDOUR_UI::launch_website ()
3453 PBD::open_uri ("http://ardour.org");
3457 ARDOUR_UI::launch_website_dev ()
3459 PBD::open_uri ("http://ardour.org/development.html");
3463 ARDOUR_UI::launch_forums ()
3465 PBD::open_uri ("https://community.ardour.org/forums");
3469 ARDOUR_UI::launch_howto_report ()
3471 PBD::open_uri ("http://ardour.org/reporting_bugs");
3475 ARDOUR_UI::loading_message (const std::string& msg)
3477 if (ARDOUR_COMMAND_LINE::no_splash) {
3485 splash->message (msg);
3489 ARDOUR_UI::show_splash ()
3493 splash = new Splash;
3503 ARDOUR_UI::hide_splash ()
3510 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3514 removed = rep.paths.size();
3517 MessageDialog msgd (*editor,
3518 _("No files were ready for clean-up"),
3522 msgd.set_title (_("Clean-up"));
3523 msgd.set_secondary_text (_("If this seems suprising, \n\
3524 check for any existing snapshots.\n\
3525 These may still include regions that\n\
3526 require some unused files to continue to exist."));
3532 ArdourDialog results (_("Clean-up"), true, false);
3534 struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3535 CleanupResultsModelColumns() {
3539 Gtk::TreeModelColumn<std::string> visible_name;
3540 Gtk::TreeModelColumn<std::string> fullpath;
3544 CleanupResultsModelColumns results_columns;
3545 Glib::RefPtr<Gtk::ListStore> results_model;
3546 Gtk::TreeView results_display;
3548 results_model = ListStore::create (results_columns);
3549 results_display.set_model (results_model);
3550 results_display.append_column (list_title, results_columns.visible_name);
3552 results_display.set_name ("CleanupResultsList");
3553 results_display.set_headers_visible (true);
3554 results_display.set_headers_clickable (false);
3555 results_display.set_reorderable (false);
3557 Gtk::ScrolledWindow list_scroller;
3560 Gtk::HBox dhbox; // the hbox for the image and text
3561 Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3562 Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO, Gtk::ICON_SIZE_DIALOG));
3564 dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3566 const string dead_directory = _session->session_directory().dead_path();
3569 %1 - number of files removed
3570 %2 - location of "dead"
3571 %3 - size of files affected
3572 %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3575 const char* bprefix;
3576 double space_adjusted = 0;
3578 if (rep.space < 1000) {
3580 space_adjusted = rep.space;
3581 } else if (rep.space < 1000000) {
3582 bprefix = _("kilo");
3583 space_adjusted = floorf((float)rep.space / 1000.0);
3584 } else if (rep.space < 1000000 * 1000) {
3585 bprefix = _("mega");
3586 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3588 bprefix = _("giga");
3589 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3593 txt.set_markup (string_compose (P_("\
3594 The following file was deleted from %2,\n\
3595 releasing %3 %4bytes of disk space", "\
3596 The following %1 files were deleted from %2,\n\
3597 releasing %3 %4bytes of disk space", removed),
3598 removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3600 txt.set_markup (string_compose (P_("\
3601 The following file was not in use and \n\
3602 has been moved to: %2\n\n\
3603 After a restart of %5\n\n\
3604 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3605 will release an additional %3 %4bytes of disk space.\n", "\
3606 The following %1 files were not in use and \n\
3607 have been moved to: %2\n\n\
3608 After a restart of %5\n\n\
3609 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3610 will release an additional %3 %4bytes of disk space.\n", removed),
3611 removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3614 dhbox.pack_start (*dimage, true, false, 5);
3615 dhbox.pack_start (txt, true, false, 5);
3617 for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3618 TreeModel::Row row = *(results_model->append());
3619 row[results_columns.visible_name] = *i;
3620 row[results_columns.fullpath] = *i;
3623 list_scroller.add (results_display);
3624 list_scroller.set_size_request (-1, 150);
3625 list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3627 dvbox.pack_start (dhbox, true, false, 5);
3628 dvbox.pack_start (list_scroller, true, false, 5);
3629 ddhbox.pack_start (dvbox, true, false, 5);
3631 results.get_vbox()->pack_start (ddhbox, true, false, 5);
3632 results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3633 results.set_default_response (RESPONSE_CLOSE);
3634 results.set_position (Gtk::WIN_POS_MOUSE);
3636 results_display.show();
3637 list_scroller.show();
3644 //results.get_vbox()->show();
3645 results.set_resizable (false);
3652 ARDOUR_UI::cleanup ()
3654 if (_session == 0) {
3655 /* shouldn't happen: menu item is insensitive */
3660 MessageDialog checker (_("Are you sure you want to clean-up?"),
3662 Gtk::MESSAGE_QUESTION,
3665 checker.set_title (_("Clean-up"));
3667 checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3668 ALL undo/redo information will be lost if you clean-up.\n\
3669 Clean-up will move all unused files to a \"dead\" location."));
3671 checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3672 checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3673 checker.set_default_response (RESPONSE_CANCEL);
3675 checker.set_name (_("CleanupDialog"));
3676 checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3677 checker.set_position (Gtk::WIN_POS_MOUSE);
3679 switch (checker.run()) {
3680 case RESPONSE_ACCEPT:
3686 ARDOUR::CleanupReport rep;
3688 editor->prepare_for_cleanup ();
3690 /* do not allow flush until a session is reloaded */
3692 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3694 act->set_sensitive (false);
3697 if (_session->cleanup_sources (rep)) {
3698 editor->finish_cleanup ();
3702 editor->finish_cleanup ();
3705 display_cleanup_results (rep, _("Cleaned Files"), false);
3709 ARDOUR_UI::flush_trash ()
3711 if (_session == 0) {
3712 /* shouldn't happen: menu item is insensitive */
3716 ARDOUR::CleanupReport rep;
3718 if (_session->cleanup_trash_sources (rep)) {
3722 display_cleanup_results (rep, _("deleted file"), true);
3726 ARDOUR_UI::cleanup_peakfiles ()
3728 if (_session == 0) {
3729 /* shouldn't happen: menu item is insensitive */
3733 if (! _session->can_cleanup_peakfiles ()) {
3737 // get all region-views in this session
3739 TrackViewList empty;
3741 editor->get_regions_after(rs, (framepos_t) 0, empty);
3742 std::list<RegionView*> views = rs.by_layer();
3744 // remove displayed audio-region-views waveforms
3745 for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3746 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3747 if (!arv) { continue ; }
3748 arv->delete_waves();
3751 // cleanup peak files:
3752 // - stop pending peakfile threads
3753 // - close peakfiles if any
3754 // - remove peak dir in session
3755 // - setup peakfiles (background thread)
3756 _session->cleanup_peakfiles ();
3758 // re-add waves to ARV
3759 for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3760 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3761 if (!arv) { continue ; }
3762 arv->create_waves();
3767 ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
3769 uint32_t order_hint = UINT32_MAX;
3771 if (editor->get_selection().tracks.empty()) {
3776 we want the new routes to have their order keys set starting from
3777 the highest order key in the selection + 1 (if available).
3780 if (place == AddRouteDialog::AfterSelection) {
3781 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
3783 order_hint = rtav->route()->order_key();
3786 } else if (place == AddRouteDialog::BeforeSelection) {
3787 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
3789 order_hint = rtav->route()->order_key();
3791 } else if (place == AddRouteDialog::First) {
3794 /* leave order_hint at UINT32_MAX */
3797 if (order_hint == UINT32_MAX) {
3798 /** AddRouteDialog::Last or selection with first/last not a RouteTimeAxisView
3799 * not setting an order hint will place new routes last.
3804 _session->set_order_hint (order_hint);
3806 /* create a gap in the existing route order keys to accomodate new routes.*/
3807 boost::shared_ptr <RouteList> rd = _session->get_routes();
3808 for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
3809 boost::shared_ptr<Route> rt (*ri);
3811 if (rt->is_monitor()) {
3815 if (rt->order_key () >= order_hint) {
3816 rt->set_order_key (rt->order_key () + add_route_dialog->count());
3822 ARDOUR_UI::start_duplicate_routes ()
3824 if (!duplicate_routes_dialog) {
3825 duplicate_routes_dialog = new DuplicateRouteDialog;
3828 if (duplicate_routes_dialog->restart (_session)) {
3832 duplicate_routes_dialog->present ();
3836 ARDOUR_UI::add_route (Gtk::Window* /* ignored */)
3844 if (add_route_dialog->is_visible()) {
3845 /* we're already doing this */
3849 ResponseType r = (ResponseType) add_route_dialog->run ();
3851 add_route_dialog->hide();
3854 case RESPONSE_ACCEPT:
3861 if ((count = add_route_dialog->count()) <= 0) {
3865 setup_order_hint(add_route_dialog->insert_at());
3867 string template_path = add_route_dialog->track_template();
3868 DisplaySuspender ds;
3870 if (!template_path.empty()) {
3871 if (add_route_dialog->name_template_is_default()) {
3872 _session->new_route_from_template (count, template_path, string());
3874 _session->new_route_from_template (count, template_path, add_route_dialog->name_template());
3879 ChanCount input_chan= add_route_dialog->channels ();
3880 ChanCount output_chan;
3881 string name_template = add_route_dialog->name_template ();
3882 PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
3883 RouteGroup* route_group = add_route_dialog->route_group ();
3884 AutoConnectOption oac = Config->get_output_auto_connect();
3886 if (oac & AutoConnectMaster) {
3887 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
3888 output_chan.set (DataType::MIDI, 0);
3890 output_chan = input_chan;
3893 /* XXX do something with name template */
3895 switch (add_route_dialog->type_wanted()) {
3896 case AddRouteDialog::AudioTrack:
3897 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template);
3899 case AddRouteDialog::MidiTrack:
3900 session_add_midi_track (route_group, count, name_template, instrument);
3902 case AddRouteDialog::MixedTrack:
3903 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, instrument);
3905 case AddRouteDialog::AudioBus:
3906 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template);
3912 ARDOUR_UI::stop_video_server (bool ask_confirm)
3914 if (!video_server_process && ask_confirm) {
3915 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
3917 if (video_server_process) {
3919 ArdourDialog confirm (_("Stop Video-Server"), true);
3920 Label m (_("Do you really want to stop the Video Server?"));
3921 confirm.get_vbox()->pack_start (m, true, true);
3922 confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
3923 confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
3924 confirm.show_all ();
3925 if (confirm.run() == RESPONSE_CANCEL) {
3929 delete video_server_process;
3930 video_server_process =0;
3935 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
3937 ARDOUR_UI::start_video_server( float_window, true);
3941 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
3947 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
3948 if (video_server_process) {
3949 popup_error(_("The Video Server is already started."));
3951 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
3957 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
3959 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
3961 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
3963 video_server_dialog->set_transient_for (*float_window);
3966 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
3967 video_server_dialog->hide();
3969 ResponseType r = (ResponseType) video_server_dialog->run ();
3970 video_server_dialog->hide();
3971 if (r != RESPONSE_ACCEPT) { return false; }
3972 if (video_server_dialog->show_again()) {
3973 Config->set_show_video_server_dialog(false);
3977 std::string icsd_exec = video_server_dialog->get_exec_path();
3978 std::string icsd_docroot = video_server_dialog->get_docroot();
3979 if (icsd_docroot.empty()) {
3980 #ifndef PLATFORM_WINDOWS
3981 icsd_docroot = X_("/");
3983 icsd_docroot = X_("C:\\");
3988 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
3989 warning << _("Specified docroot is not an existing directory.") << endmsg;
3992 #ifndef PLATFORM_WINDOWS
3993 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
3994 || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
3995 warning << _("Given Video Server is not an executable file.") << endmsg;
3999 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4000 || (sb.st_mode & (S_IXUSR)) == 0 ) {
4001 warning << _("Given Video Server is not an executable file.") << endmsg;
4007 argp=(char**) calloc(9,sizeof(char*));
4008 argp[0] = strdup(icsd_exec.c_str());
4009 argp[1] = strdup("-P");
4010 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4011 argp[3] = strdup("-p");
4012 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4013 argp[5] = strdup("-C");
4014 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4015 argp[7] = strdup(icsd_docroot.c_str());
4017 stop_video_server();
4019 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4020 Config->set_video_advanced_setup(false);
4022 std::ostringstream osstream;
4023 osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4024 Config->set_video_server_url(osstream.str());
4025 Config->set_video_server_docroot(icsd_docroot);
4026 Config->set_video_advanced_setup(true);
4029 if (video_server_process) {
4030 delete video_server_process;
4033 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4034 if (video_server_process->start()) {
4035 warning << _("Cannot launch the video-server") << endmsg;
4038 int timeout = 120; // 6 sec
4039 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4040 Glib::usleep (50000);
4042 if (--timeout <= 0 || !video_server_process->is_running()) break;
4045 warning << _("Video-server was started but does not respond to requests...") << endmsg;
4047 if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4048 delete video_server_process;
4049 video_server_process = 0;
4057 ARDOUR_UI::add_video (Gtk::Window* float_window)
4063 if (!start_video_server(float_window, false)) {
4064 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4069 add_video_dialog->set_transient_for (*float_window);
4072 if (add_video_dialog->is_visible()) {
4073 /* we're already doing this */
4077 ResponseType r = (ResponseType) add_video_dialog->run ();
4078 add_video_dialog->hide();
4079 if (r != RESPONSE_ACCEPT) { return; }
4081 bool local_file, orig_local_file;
4082 std::string path = add_video_dialog->file_name(local_file);
4084 std::string orig_path = path;
4085 orig_local_file = local_file;
4087 bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4089 if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4090 warning << string_compose(_("could not open %1"), path) << endmsg;
4093 if (!local_file && path.length() == 0) {
4094 warning << _("no video-file selected") << endmsg;
4098 std::string audio_from_video;
4099 bool detect_ltc = false;
4101 switch (add_video_dialog->import_option()) {
4102 case VTL_IMPORT_TRANSCODE:
4104 TranscodeVideoDialog *transcode_video_dialog;
4105 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4106 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4107 transcode_video_dialog->hide();
4108 if (r != RESPONSE_ACCEPT) {
4109 delete transcode_video_dialog;
4113 audio_from_video = transcode_video_dialog->get_audiofile();
4115 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4118 else if (!audio_from_video.empty()) {
4119 editor->embed_audio_from_video(
4121 video_timeline->get_offset(),
4122 (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4125 switch (transcode_video_dialog->import_option()) {
4126 case VTL_IMPORT_TRANSCODED:
4127 path = transcode_video_dialog->get_filename();
4130 case VTL_IMPORT_REFERENCE:
4133 delete transcode_video_dialog;
4136 delete transcode_video_dialog;
4140 case VTL_IMPORT_NONE:
4144 /* strip _session->session_directory().video_path() from video file if possible */
4145 if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4146 path=path.substr(_session->session_directory().video_path().size());
4147 if (path.at(0) == G_DIR_SEPARATOR) {
4148 path=path.substr(1);
4152 video_timeline->set_update_session_fps(auto_set_session_fps);
4154 if (video_timeline->video_file_info(path, local_file)) {
4155 XMLNode* node = new XMLNode(X_("Videotimeline"));
4156 node->add_property (X_("Filename"), path);
4157 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4158 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4159 if (orig_local_file) {
4160 node->add_property (X_("OriginalVideoFile"), orig_path);
4162 node->remove_property (X_("OriginalVideoFile"));
4164 _session->add_extra_xml (*node);
4165 _session->set_dirty ();
4167 if (!audio_from_video.empty() && detect_ltc) {
4168 std::vector<LTCFileReader::LTCMap> ltc_seq;
4171 /* TODO ask user about TV standard (LTC alignment if any) */
4172 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4173 /* TODO ASK user which channel: 0 .. ltcr->channels() - 1 */
4175 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4177 /* TODO seek near end of file, and read LTC until end.
4178 * if it fails to find any LTC frames, scan complete file
4180 * calculate drift of LTC compared to video-duration,
4181 * ask user for reference (timecode from start/mid/end)
4184 // LTCFileReader will have written error messages
4187 ::g_unlink(audio_from_video.c_str());
4189 if (ltc_seq.size() == 0) {
4190 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4192 /* the very first TC in the file is somteimes not aligned properly */
4193 int i = ltc_seq.size() -1;
4194 ARDOUR::frameoffset_t video_start_offset =
4195 _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4196 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4197 video_timeline->set_offset(video_start_offset);
4201 _session->maybe_update_session_range(
4202 std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4203 std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4206 if (add_video_dialog->launch_xjadeo() && local_file) {
4207 editor->set_xjadeo_sensitive(true);
4208 editor->toggle_xjadeo_proc(1);
4210 editor->toggle_xjadeo_proc(0);
4212 editor->toggle_ruler_video(true);
4217 ARDOUR_UI::remove_video ()
4219 video_timeline->close_session();
4220 editor->toggle_ruler_video(false);
4223 video_timeline->set_offset_locked(false);
4224 video_timeline->set_offset(0);
4226 /* delete session state */
4227 XMLNode* node = new XMLNode(X_("Videotimeline"));
4228 _session->add_extra_xml(*node);
4229 node = new XMLNode(X_("Videomonitor"));
4230 _session->add_extra_xml(*node);
4231 node = new XMLNode(X_("Videoexport"));
4232 _session->add_extra_xml(*node);
4233 stop_video_server();
4237 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4239 if (localcacheonly) {
4240 video_timeline->vmon_update();
4242 video_timeline->flush_cache();
4244 editor->queue_visual_videotimeline_update();
4248 ARDOUR_UI::export_video (bool range)
4250 if (ARDOUR::Config->get_show_video_export_info()) {
4251 ExportVideoInfobox infobox (_session);
4252 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4253 if (infobox.show_again()) {
4254 ARDOUR::Config->set_show_video_export_info(false);
4257 case GTK_RESPONSE_YES:
4258 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4264 export_video_dialog->set_session (_session);
4265 export_video_dialog->apply_state(editor->get_selection().time, range);
4266 export_video_dialog->run ();
4267 export_video_dialog->hide ();
4271 ARDOUR_UI::mixer_settings () const
4276 node = _session->instant_xml(X_("Mixer"));
4278 node = Config->instant_xml(X_("Mixer"));
4282 node = new XMLNode (X_("Mixer"));
4289 ARDOUR_UI::editor_settings () const
4294 node = _session->instant_xml(X_("Editor"));
4296 node = Config->instant_xml(X_("Editor"));
4300 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4301 node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4306 node = new XMLNode (X_("Editor"));
4313 ARDOUR_UI::keyboard_settings () const
4317 node = Config->extra_xml(X_("Keyboard"));
4320 node = new XMLNode (X_("Keyboard"));
4327 ARDOUR_UI::create_xrun_marker (framepos_t where)
4330 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
4331 _session->locations()->add (location);
4336 ARDOUR_UI::halt_on_xrun_message ()
4338 cerr << "HALT on xrun\n";
4339 MessageDialog msg (*editor, _("Recording was stopped because your system could not keep up."));
4344 ARDOUR_UI::xrun_handler (framepos_t where)
4350 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4352 if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4353 create_xrun_marker(where);
4356 if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4357 halt_on_xrun_message ();
4362 ARDOUR_UI::disk_overrun_handler ()
4364 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4366 if (!have_disk_speed_dialog_displayed) {
4367 have_disk_speed_dialog_displayed = true;
4368 MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\
4369 The disk system on your computer\n\
4370 was not able to keep up with %1.\n\
4372 Specifically, it failed to write data to disk\n\
4373 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4374 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4380 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4381 static MessageDialog *scan_dlg = NULL;
4382 static ProgressBar *scan_pbar = NULL;
4383 static HBox *scan_tbox = NULL;
4384 static Gtk::Button *scan_timeout_button;
4387 ARDOUR_UI::cancel_plugin_scan ()
4389 PluginManager::instance().cancel_plugin_scan();
4393 ARDOUR_UI::cancel_plugin_timeout ()
4395 PluginManager::instance().cancel_plugin_timeout();
4396 scan_timeout_button->set_sensitive (false);
4400 ARDOUR_UI::plugin_scan_timeout (int timeout)
4402 if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4406 scan_pbar->set_sensitive (false);
4407 scan_timeout_button->set_sensitive (true);
4408 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4411 scan_pbar->set_sensitive (false);
4412 scan_timeout_button->set_sensitive (false);
4418 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4420 if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4424 const bool cancelled = PluginManager::instance().cancelled();
4425 if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4426 if (cancelled && scan_dlg->is_mapped()) {
4431 if (cancelled || !can_cancel) {
4436 static Gtk::Button *cancel_button;
4438 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4439 VBox* vbox = scan_dlg->get_vbox();
4440 vbox->set_size_request(400,-1);
4441 scan_dlg->set_title (_("Scanning for plugins"));
4443 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4444 cancel_button->set_name ("EditorGTKButton");
4445 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4446 cancel_button->show();
4448 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4450 scan_tbox = manage( new HBox() );
4452 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4453 scan_timeout_button->set_name ("EditorGTKButton");
4454 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4455 scan_timeout_button->show();
4457 scan_pbar = manage(new ProgressBar());
4458 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4459 scan_pbar->set_text(_("Scan Timeout"));
4462 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4463 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4465 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4468 assert(scan_dlg && scan_tbox && cancel_button);
4470 if (type == X_("closeme")) {
4474 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4477 if (!can_cancel || !cancelled) {
4478 scan_timeout_button->set_sensitive(false);
4480 cancel_button->set_sensitive(can_cancel && !cancelled);
4486 ARDOUR_UI::gui_idle_handler ()
4489 /* due to idle calls, gtk_events_pending() may always return true */
4490 while (gtk_events_pending() && --timeout) {
4491 gtk_main_iteration ();
4496 ARDOUR_UI::disk_underrun_handler ()
4498 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4500 if (!have_disk_speed_dialog_displayed) {
4501 have_disk_speed_dialog_displayed = true;
4502 MessageDialog* msg = new MessageDialog (
4503 *editor, string_compose (_("The disk system on your computer\n\
4504 was not able to keep up with %1.\n\
4506 Specifically, it failed to read data from disk\n\
4507 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4508 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4514 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4516 have_disk_speed_dialog_displayed = false;
4521 ARDOUR_UI::session_dialog (std::string msg)
4523 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4528 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4530 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4539 ARDOUR_UI::pending_state_dialog ()
4541 HBox* hbox = manage (new HBox());
4542 Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4543 ArdourDialog dialog (_("Crash Recovery"), true);
4544 Label message (string_compose (_("\
4545 This session appears to have been in the\n\
4546 middle of recording when %1 or\n\
4547 the computer was shutdown.\n\
4549 %1 can recover any captured audio for\n\
4550 you, or it can ignore it. Please decide\n\
4551 what you would like to do.\n"), PROGRAM_NAME));
4552 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4553 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4554 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4555 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4556 dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
4557 dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
4558 dialog.set_default_response (RESPONSE_ACCEPT);
4559 dialog.set_position (WIN_POS_CENTER);
4564 switch (dialog.run ()) {
4565 case RESPONSE_ACCEPT:
4573 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4575 HBox* hbox = new HBox();
4576 Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4577 ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4578 Label message (string_compose (_("\
4579 This session was created with a sample rate of %1 Hz, but\n\
4580 %2 is currently running at %3 Hz. If you load this session,\n\
4581 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4583 image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4584 hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4585 hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4586 dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4587 dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4588 dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4589 dialog.set_default_response (RESPONSE_ACCEPT);
4590 dialog.set_position (WIN_POS_CENTER);
4595 switch (dialog.run()) {
4596 case RESPONSE_ACCEPT:
4606 ARDOUR_UI::use_config ()
4608 XMLNode* node = Config->extra_xml (X_("TransportControllables"));
4610 set_transport_controllable_state (*node);
4615 ARDOUR_UI::update_transport_clocks (framepos_t pos)
4617 if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
4618 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4620 primary_clock->set (pos);
4623 if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
4624 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4626 secondary_clock->set (pos);
4629 if (big_clock_window) {
4630 big_clock->set (pos);
4632 ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
4636 ARDOUR_UI::step_edit_status_change (bool yn)
4638 // XXX should really store pre-step edit status of things
4639 // we make insensitive
4642 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
4643 rec_button.set_sensitive (false);
4645 rec_button.unset_active_state ();;
4646 rec_button.set_sensitive (true);
4651 ARDOUR_UI::record_state_changed ()
4653 ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
4655 if (!_session || !big_clock_window) {
4656 /* why bother - the clock isn't visible */
4660 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
4661 big_clock->set_active (true);
4663 big_clock->set_active (false);
4668 ARDOUR_UI::first_idle ()
4671 _session->allow_auto_play (true);
4675 editor->first_idle();
4678 Keyboard::set_can_save_keybindings (true);
4683 ARDOUR_UI::store_clock_modes ()
4685 XMLNode* node = new XMLNode(X_("ClockModes"));
4687 for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
4688 XMLNode* child = new XMLNode (X_("Clock"));
4690 child->add_property (X_("name"), (*x)->name());
4691 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
4692 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
4694 node->add_child_nocopy (*child);
4697 _session->add_extra_xml (*node);
4698 _session->set_dirty ();
4701 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
4702 : Controllable (name), ui (u), type(tp)
4708 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
4711 /* do nothing: these are radio-style actions */
4715 const char *action = 0;
4719 action = X_("Roll");
4722 action = X_("Stop");
4725 action = X_("GotoStart");
4728 action = X_("GotoEnd");
4731 action = X_("Loop");
4734 action = X_("PlaySelection");
4737 action = X_("Record");
4747 Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
4755 ARDOUR_UI::TransportControllable::get_value (void) const
4782 ARDOUR_UI::setup_profile ()
4784 if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
4785 Profile->set_small_screen ();
4788 if (g_getenv ("ARDOUR_SAE")) {
4789 Profile->set_sae ();
4790 Profile->set_single_package ();
4793 if (g_getenv ("TRX")) {
4794 Profile->set_trx ();
4797 if (g_getenv ("MIXBUS")) {
4798 Profile->set_mixbus ();
4803 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
4805 MissingFileDialog dialog (s, str, type);
4810 int result = dialog.run ();
4817 return 1; // quit entire session load
4820 result = dialog.get_action ();
4826 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
4828 AmbiguousFileDialog dialog (file, hits);
4835 return dialog.get_which ();
4838 /** Allocate our thread-local buffers */
4840 ARDOUR_UI::get_process_buffers ()
4842 _process_thread->get_buffers ();
4845 /** Drop our thread-local buffers */
4847 ARDOUR_UI::drop_process_buffers ()
4849 _process_thread->drop_buffers ();
4853 ARDOUR_UI::feedback_detected ()
4855 _feedback_exists = true;
4859 ARDOUR_UI::successful_graph_sort ()
4861 _feedback_exists = false;
4865 ARDOUR_UI::midi_panic ()
4868 _session->midi_panic();
4873 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
4875 const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
4876 const char* end_big = "</span>";
4877 const char* start_mono = "<tt>";
4878 const char* end_mono = "</tt>";
4880 MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
4881 "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
4882 "From now on, use the -2000 version with older versions of %3"),
4883 xml_path, backup_path, PROGRAM_NAME,
4885 start_mono, end_mono), true);
4892 ARDOUR_UI::reset_peak_display ()
4894 if (!_session || !_session->master_out() || !editor_meter) return;
4895 editor_meter->clear_meters();
4896 editor_meter_max_peak = -INFINITY;
4897 editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
4901 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
4903 if (!_session || !_session->master_out()) return;
4904 if (group == _session->master_out()->route_group()) {
4905 reset_peak_display ();
4910 ARDOUR_UI::reset_route_peak_display (Route* route)
4912 if (!_session || !_session->master_out()) return;
4913 if (_session->master_out().get() == route) {
4914 reset_peak_display ();
4919 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
4921 audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
4922 audio_midi_setup->set_position (WIN_POS_CENTER);
4927 response = audio_midi_setup->run();
4929 case Gtk::RESPONSE_OK:
4930 if (!AudioEngine::instance()->running()) {
4944 ARDOUR_UI::transport_numpad_timeout ()
4946 _numpad_locate_happening = false;
4947 if (_numpad_timeout_connection.connected() )
4948 _numpad_timeout_connection.disconnect();
4953 ARDOUR_UI::transport_numpad_decimal ()
4955 _numpad_timeout_connection.disconnect();
4957 if (_numpad_locate_happening) {
4958 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
4959 _numpad_locate_happening = false;
4961 _pending_locate_num = 0;
4962 _numpad_locate_happening = true;
4963 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
4968 ARDOUR_UI::transport_numpad_event (int num)
4970 if ( _numpad_locate_happening ) {
4971 _pending_locate_num = _pending_locate_num*10 + num;
4974 case 0: toggle_roll(false, false); break;
4975 case 1: transport_rewind(1); break;
4976 case 2: transport_forward(1); break;
4977 case 3: transport_record(true); break;
4978 case 4: toggle_session_auto_loop(); break;
4979 case 5: transport_record(false); toggle_session_auto_loop(); break;
4980 case 6: toggle_punch(); break;
4981 case 7: toggle_click(); break;
4982 case 8: toggle_auto_return(); break;
4983 case 9: toggle_follow_edits(); break;
4989 ARDOUR_UI::set_flat_buttons ()
4991 CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
4995 ARDOUR_UI::audioengine_became_silent ()
4997 MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
4999 Gtk::MESSAGE_WARNING,
5003 msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5005 Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5006 Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5007 Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5008 Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5009 Gtk::HBox pay_button_box;
5010 Gtk::HBox subscribe_button_box;
5012 pay_button_box.pack_start (pay_button, true, false);
5013 subscribe_button_box.pack_start (subscribe_button, true, false);
5015 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 */
5017 pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5018 subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5020 msg.get_vbox()->pack_start (pay_label);
5021 msg.get_vbox()->pack_start (pay_button_box);
5022 msg.get_vbox()->pack_start (subscribe_label);
5023 msg.get_vbox()->pack_start (subscribe_button_box);
5025 msg.get_vbox()->show_all ();
5027 msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5028 msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5029 msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5034 case Gtk::RESPONSE_YES:
5035 AudioEngine::instance()->reset_silence_countdown ();
5038 case Gtk::RESPONSE_NO:
5040 save_state_canfail ("");
5044 case Gtk::RESPONSE_CANCEL:
5046 /* don't reset, save session and exit */
5052 ARDOUR_UI::hide_application ()
5054 Application::instance ()-> hide ();
5058 ARDOUR_UI::cancel_solo ()
5061 if (_session->soloing()) {
5062 _session->set_solo (_session->get_routes(), false);
5063 } else if (_session->listening()) {
5064 _session->set_listen (_session->get_routes(), false);
5067 _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window