GUI part of 00169f1da (TRY_AUTOSTART_ENGINE)
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2013 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #include "gtk2ardour-version.h"
23 #endif
24
25 #include <algorithm>
26 #include <cmath>
27 #include <iostream>
28 #include <cerrno>
29
30 #include <stdarg.h>
31
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
34 #endif
35
36 #include <stdint.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 #include <unistd.h>
40 #include <time.h>
41
42 #include <glib.h>
43 #include "pbd/gstdio_compat.h"
44
45 #include <gtkmm/messagedialog.h>
46 #include <gtkmm/accelmap.h>
47
48 #include "pbd/error.h"
49 #include "pbd/basename.h"
50 #include "pbd/compose.h"
51 #include "pbd/convert.h"
52 #include "pbd/failed_constructor.h"
53 #include "pbd/enumwriter.h"
54 #include "pbd/memento_command.h"
55 #include "pbd/openuri.h"
56 #include "pbd/stl_delete.h"
57 #include "pbd/file_utils.h"
58 #include "pbd/localtime_r.h"
59 #include "pbd/pthread_utils.h"
60 #include "pbd/replace_all.h"
61 #include "pbd/xml++.h"
62
63 #include "gtkmm2ext/application.h"
64 #include "gtkmm2ext/bindings.h"
65 #include "gtkmm2ext/gtk_ui.h"
66 #include "gtkmm2ext/utils.h"
67 #include "gtkmm2ext/click_box.h"
68 #include "gtkmm2ext/fastmeter.h"
69 #include "gtkmm2ext/popup.h"
70 #include "gtkmm2ext/window_title.h"
71
72 #include "ardour/ardour.h"
73 #include "ardour/audio_backend.h"
74 #include "ardour/audio_track.h"
75 #include "ardour/audioengine.h"
76 #include "ardour/audiofilesource.h"
77 #include "ardour/automation_watch.h"
78 #include "ardour/diskstream.h"
79 #include "ardour/filename_extensions.h"
80 #include "ardour/filesystem_paths.h"
81 #include "ardour/ltc_file_reader.h"
82 #include "ardour/midi_track.h"
83 #include "ardour/port.h"
84 #include "ardour/plugin_manager.h"
85 #include "ardour/process_thread.h"
86 #include "ardour/profile.h"
87 #include "ardour/recent_sessions.h"
88 #include "ardour/session_directory.h"
89 #include "ardour/session_route.h"
90 #include "ardour/session_state_utils.h"
91 #include "ardour/session_utils.h"
92 #include "ardour/source_factory.h"
93 #include "ardour/slave.h"
94 #include "ardour/system_exec.h"
95
96 #include "LuaBridge/LuaBridge.h"
97
98 #ifdef WINDOWS_VST_SUPPORT
99 #include <fst.h>
100 #endif
101 #ifdef AUDIOUNIT_SUPPORT
102 #include "ardour/audio_unit.h"
103 #endif
104
105 // fix for OSX (nsm.h has a check function, AU/Apple defines check)
106 #ifdef check
107 #undef check
108 #endif
109
110 #include "timecode/time.h"
111
112 typedef uint64_t microseconds_t;
113
114 #include "about.h"
115 #include "editing.h"
116 #include "actions.h"
117 #include "add_route_dialog.h"
118 #include "ambiguous_file_dialog.h"
119 #include "ardour_ui.h"
120 #include "audio_clock.h"
121 #include "audio_region_view.h"
122 #include "big_clock_window.h"
123 #include "bundle_manager.h"
124 #include "duplicate_routes_dialog.h"
125 #include "debug.h"
126 #include "engine_dialog.h"
127 #include "export_video_dialog.h"
128 #include "export_video_infobox.h"
129 #include "gain_meter.h"
130 #include "global_port_matrix.h"
131 #include "gui_object.h"
132 #include "gui_thread.h"
133 #include "keyboard.h"
134 #include "keyeditor.h"
135 #include "location_ui.h"
136 #include "lua_script_manager.h"
137 #include "luawindow.h"
138 #include "main_clock.h"
139 #include "missing_file_dialog.h"
140 #include "missing_plugin_dialog.h"
141 #include "mixer_ui.h"
142 #include "meterbridge.h"
143 #include "mouse_cursors.h"
144 #include "nsm.h"
145 #include "opts.h"
146 #include "pingback.h"
147 #include "processor_box.h"
148 #include "prompter.h"
149 #include "public_editor.h"
150 #include "rc_option_editor.h"
151 #include "route_time_axis.h"
152 #include "route_params_ui.h"
153 #include "save_as_dialog.h"
154 #include "script_selector.h"
155 #include "session_dialog.h"
156 #include "session_metadata_dialog.h"
157 #include "session_option_editor.h"
158 #include "shuttle_control.h"
159 #include "speaker_dialog.h"
160 #include "splash.h"
161 #include "startup.h"
162 #include "theme_manager.h"
163 #include "time_axis_view_item.h"
164 #include "timers.h"
165 #include "utils.h"
166 #include "video_server_dialog.h"
167 #include "add_video_dialog.h"
168 #include "transcode_video_dialog.h"
169
170 #include "i18n.h"
171
172 using namespace ARDOUR;
173 using namespace ARDOUR_UI_UTILS;
174 using namespace PBD;
175 using namespace Gtkmm2ext;
176 using namespace Gtk;
177 using namespace std;
178 using namespace Editing;
179
180 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
181
182 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
183 sigc::signal<void>      ARDOUR_UI::CloseAllDialogs;
184
185 static bool
186 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
187 {
188         MessageDialog msg (string_compose (_("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
189                                              "Would you like these files to be copied and used for %1 %2.x?\n\n"
190                                              "(This will require you to restart %1.)"),
191                                            PROGRAM_NAME, PROGRAM_VERSION, version),
192                            false, /* no markup */
193                            Gtk::MESSAGE_INFO,
194                            Gtk::BUTTONS_YES_NO,
195                            true /* modal, though it hardly matters since it is the only window */
196                 );
197
198         msg.set_default_response (Gtk::RESPONSE_YES);
199         msg.show_all ();
200
201         return (msg.run() == Gtk::RESPONSE_YES);
202 }
203
204 static void
205 libxml_generic_error_func (void* /* parsing_context*/,
206                    const char* msg,
207                    ...)
208 {
209         va_list ap;
210         char buf[2048];
211
212         va_start (ap, msg);
213         vsnprintf (buf, sizeof (buf), msg, ap);
214         error << buf << endmsg;
215         va_end (ap);
216 }
217
218 static void
219 libxml_structured_error_func (void* /* parsing_context*/,
220                               xmlErrorPtr err)
221 {
222         string msg;
223
224         if (err->message)
225                 msg = err->message;
226
227         replace_all (msg, "\n", "");
228
229         if (err->file && err->line) {
230                 error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
231
232                 if (err->int2) {
233                         error << ':' << err->int2;
234                 }
235         }
236         error << endmsg;
237 }
238
239
240 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
241         : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
242         , session_loaded (false)
243         , gui_object_state (new GUIObjectState)
244         , primary_clock   (new MainClock (X_("primary"),   X_("transport"), true ))
245         , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
246         , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
247         , video_timeline(0)
248         , global_actions (X_("global"))
249         , ignore_dual_punch (false)
250         , editor (0)
251         , mixer (0)
252         , nsm (0)
253         , _was_dirty (false)
254         , _mixer_on_top (false)
255         , _initial_verbose_plugin_scan (false)
256         , first_time_engine_run (true)
257         , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
258         , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
259         , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
260         , goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd))
261         , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
262         , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
263         , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
264         , auto_return_button (ArdourButton::led_default_elements)
265         , follow_edits_button (ArdourButton::led_default_elements)
266         , auto_input_button (ArdourButton::led_default_elements)
267         , auditioning_alert_button (_("Audition"))
268         , solo_alert_button (_("Solo"))
269         , feedback_alert_button (_("Feedback"))
270         , error_alert_button ( ArdourButton::just_led_default_elements )
271         , editor_meter(0)
272         , editor_meter_peak_display()
273         , _numpad_locate_happening (false)
274         , _session_is_new (false)
275         , last_key_press_time (0)
276         , save_as_dialog (0)
277         , meterbridge (0)
278         , luawindow (0)
279         , rc_option_editor (0)
280         , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
281         , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
282         , about (X_("about"), _("About"))
283         , location_ui (X_("locations"), _("Locations"))
284         , route_params (X_("inspector"), _("Tracks and Busses"))
285         , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
286         , export_video_dialog (X_("video-export"), _("Video Export Dialog"))
287         , lua_script_window (X_("script-manager"), _("Script Manager"))
288         , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
289         , add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
290         , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
291         , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
292         , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
293         , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
294         , key_editor (X_("key-editor"), _("Bindings Editor"), boost::bind (&ARDOUR_UI::create_key_editor, this))
295         , video_server_process (0)
296         , splash (0)
297         , have_configure_timeout (false)
298         , last_configure_time (0)
299         , last_peak_grab (0)
300         , have_disk_speed_dialog_displayed (false)
301         , _status_bar_visibility (X_("status-bar"))
302         , _feedback_exists (false)
303         , _log_not_acknowledged (LogLevelNone)
304         , duplicate_routes_dialog (0)
305         , editor_visibility_button (S_("Window|Editor"))
306         , mixer_visibility_button (S_("Window|Mixer"))
307         , prefs_visibility_button (S_("Window|Preferences"))
308 {
309         Gtkmm2ext::init (localedir);
310
311         UIConfiguration::instance().post_gui_init ();
312
313         if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
314                 MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
315                 msg.run ();
316                 /* configuration was modified, exit immediately */
317                 _exit (0);
318         }
319
320         if (theArdourUI == 0) {
321                 theArdourUI = this;
322         }
323
324         /* stop libxml from spewing to stdout/stderr */
325
326         xmlSetGenericErrorFunc (this, libxml_generic_error_func);
327         xmlSetStructuredErrorFunc (this, libxml_structured_error_func);
328
329         UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
330         boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
331         UIConfiguration::instance().map_parameters (pc);
332
333         roll_button.set_controllable (roll_controllable);
334         stop_button.set_controllable (stop_controllable);
335         goto_start_button.set_controllable (goto_start_controllable);
336         goto_end_button.set_controllable (goto_end_controllable);
337         auto_loop_button.set_controllable (auto_loop_controllable);
338         play_selection_button.set_controllable (play_selection_controllable);
339         rec_button.set_controllable (rec_controllable);
340
341         roll_button.set_name ("transport button");
342         stop_button.set_name ("transport button");
343         goto_start_button.set_name ("transport button");
344         goto_end_button.set_name ("transport button");
345         auto_loop_button.set_name ("transport button");
346         play_selection_button.set_name ("transport button");
347         rec_button.set_name ("transport recenable button");
348         midi_panic_button.set_name ("transport button");
349
350         ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
351         ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
352
353         ARDOUR::Session::VersionMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_format_mismatch, this, _1, _2), gui_context());
354
355         /* handle dialog requests */
356
357         ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
358
359         /* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
360
361         ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
362
363         /* handle Audio/MIDI setup when session requires it */
364
365         ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1));
366
367         /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
368
369         ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
370
371         /* handle sr mismatch with a dialog - cross-thread from engine */
372         ARDOUR::Session::NotifyAboutSampleRateMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::sr_mismatch_message, this, _1, _2), gui_context ());
373
374         /* handle requests to quit (coming from JACK session) */
375
376         ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::finish, this), gui_context ());
377
378         /* tell the user about feedback */
379
380         ARDOUR::Session::FeedbackDetected.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::feedback_detected, this), gui_context ());
381         ARDOUR::Session::SuccessfulGraphSort.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::successful_graph_sort, this), gui_context ());
382
383         /* handle requests to deal with missing files */
384
385         ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
386
387         /* and ambiguous files */
388
389         ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
390
391         /* also plugin scan messages */
392         ARDOUR::PluginScanMessage.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_dialog, this, _1, _2, _3), gui_context());
393         ARDOUR::PluginScanTimeout.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_timeout, this, _1), gui_context());
394
395         ARDOUR::GUIIdle.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::gui_idle_handler, this), gui_context());
396
397         Config->ParameterChanged.connect ( forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::set_flat_buttons, this), gui_context() );
398         set_flat_buttons();
399
400         /* lets get this party started */
401
402         setup_gtk_ardour_enums ();
403         setup_profile ();
404
405         SessionEvent::create_per_thread_pool ("GUI", 4096);
406
407         /* we like keyboards */
408
409         keyboard = new ArdourKeyboard(*this);
410
411         XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
412         if (node) {
413                 keyboard->set_state (*node, Stateful::loading_state_version);
414         }
415
416         UIConfiguration::instance().reset_dpi ();
417
418         TimeAxisViewItem::set_constant_heights ();
419
420         /* Set this up so that our window proxies can register actions */
421
422         ActionManager::init ();
423
424         /* The following must happen after ARDOUR::init() so that Config is set up */
425
426         const XMLNode* ui_xml = Config->extra_xml (X_("UI"));
427
428         if (ui_xml) {
429                 key_editor.set_state (*ui_xml, 0);
430                 session_option_editor.set_state (*ui_xml, 0);
431                 speaker_config_window.set_state (*ui_xml, 0);
432                 about.set_state (*ui_xml, 0);
433                 add_route_dialog.set_state (*ui_xml, 0);
434                 add_video_dialog.set_state (*ui_xml, 0);
435                 route_params.set_state (*ui_xml, 0);
436                 bundle_manager.set_state (*ui_xml, 0);
437                 location_ui.set_state (*ui_xml, 0);
438                 big_clock_window.set_state (*ui_xml, 0);
439                 audio_port_matrix.set_state (*ui_xml, 0);
440                 midi_port_matrix.set_state (*ui_xml, 0);
441                 export_video_dialog.set_state (*ui_xml, 0);
442                 lua_script_window.set_state (*ui_xml, 0);
443         }
444
445         /* Separate windows */
446
447         WM::Manager::instance().register_window (&key_editor);
448         WM::Manager::instance().register_window (&session_option_editor);
449         WM::Manager::instance().register_window (&speaker_config_window);
450         WM::Manager::instance().register_window (&about);
451         WM::Manager::instance().register_window (&add_route_dialog);
452         WM::Manager::instance().register_window (&add_video_dialog);
453         WM::Manager::instance().register_window (&route_params);
454         WM::Manager::instance().register_window (&audio_midi_setup);
455         WM::Manager::instance().register_window (&export_video_dialog);
456         WM::Manager::instance().register_window (&lua_script_window);
457         WM::Manager::instance().register_window (&bundle_manager);
458         WM::Manager::instance().register_window (&location_ui);
459         WM::Manager::instance().register_window (&big_clock_window);
460         WM::Manager::instance().register_window (&audio_port_matrix);
461         WM::Manager::instance().register_window (&midi_port_matrix);
462
463         /* Trigger setting up the color scheme and loading the GTK RC file */
464
465         UIConfiguration::instance().load_rc_file (false);
466
467         _process_thread = new ProcessThread ();
468         _process_thread->init ();
469
470         UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets));
471
472         attach_to_engine ();
473 }
474
475 GlobalPortMatrixWindow*
476 ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
477 {
478         if (!_session) {
479                 return 0;
480         }
481         return new GlobalPortMatrixWindow (_session, type);
482 }
483
484 void
485 ARDOUR_UI::attach_to_engine ()
486 {
487         AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
488         ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
489 }
490
491 void
492 ARDOUR_UI::engine_stopped ()
493 {
494         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
495         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
496         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
497         update_sample_rate (0);
498         update_cpu_load ();
499 }
500
501 void
502 ARDOUR_UI::engine_running ()
503 {
504         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running)
505         if (first_time_engine_run) {
506                 post_engine();
507                 first_time_engine_run = false;
508         }
509
510         if (_session) {
511                 _session->reset_xrun_count ();
512         }
513         update_disk_space ();
514         update_cpu_load ();
515         update_xrun_count ();
516         update_sample_rate (AudioEngine::instance()->sample_rate());
517         update_timecode_format ();
518         update_peak_thread_work ();
519         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true);
520         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false);
521 }
522
523 void
524 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
525 {
526         if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
527                 /* we can't rely on the original string continuing to exist when we are called
528                    again in the GUI thread, so make a copy and note that we need to
529                    free it later.
530                 */
531                 char *copy = strdup (reason);
532                 Gtkmm2ext::UI::instance()->call_slot (MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
533                 return;
534         }
535
536         ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
537         ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
538
539         update_sample_rate (0);
540
541         string msgstr;
542
543         /* if the reason is a non-empty string, it means that the backend was shutdown
544            rather than just Ardour.
545         */
546
547         if (strlen (reason)) {
548                 msgstr = string_compose (_("The audio backend was shutdown because:\n\n%1"), reason);
549         } else {
550                 msgstr = string_compose (_("\
551 The audio backend has either been shutdown or it\n\
552 disconnected %1 because %1\n\
553 was not fast enough. Try to restart\n\
554 the audio backend and save the session."), PROGRAM_NAME);
555         }
556
557         MessageDialog msg (_main_window, msgstr);
558         pop_back_splash (msg);
559         msg.run ();
560
561         if (free_reason) {
562                 free (const_cast<char*> (reason));
563         }
564 }
565
566 void
567 ARDOUR_UI::post_engine ()
568 {
569         /* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine
570          */
571 #ifdef AUDIOUNIT_SUPPORT
572         std::string au_msg;
573         if (AUPluginInfo::au_get_crashlog(au_msg)) {
574                 popup_error(_("Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see the log window for further details."));
575                 error << _("Audio Unit Plugin Scan Failed:") << endmsg;
576                 info << au_msg << endmsg;
577         }
578 #endif
579
580         ARDOUR::init_post_engine ();
581
582         /* connect to important signals */
583
584         AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
585         AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
586         AudioEngine::instance()->BufferSizeChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
587         AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
588         AudioEngine::instance()->BecameSilent.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::audioengine_became_silent, this), gui_context());
589
590         if (setup_windows ()) {
591                 throw failed_constructor ();
592         }
593
594         /* Do this after setup_windows (), as that's when the _status_bar_visibility is created */
595         XMLNode* n = Config->extra_xml (X_("UI"));
596         if (n) {
597                 _status_bar_visibility.set_state (*n);
598         }
599
600         check_memory_locking();
601
602         /* this is the first point at which all the possible actions are
603          * available, because some of the available actions are dependent on
604          * aspects of the engine/backend.
605          */
606
607         if (ARDOUR_COMMAND_LINE::show_key_actions) {
608
609
610                 vector<string> paths;
611                 vector<string> labels;
612                 vector<string> tooltips;
613                 vector<string> keys;
614                 vector<Glib::RefPtr<Gtk::Action> > actions;
615
616                 Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
617
618                 vector<string>::iterator k;
619                 vector<string>::iterator p;
620
621                 for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) {
622
623                         if ((*k).empty()) {
624                                 cout << *p << endl;
625                         } else {
626                                 cout << *p << " => " << *k << endl;
627                         }
628                 }
629
630                 halt_connection.disconnect ();
631                 AudioEngine::instance()->stop ();
632                 exit (0);
633         }
634
635         /* this being a GUI and all, we want peakfiles */
636
637         AudioFileSource::set_build_peakfiles (true);
638         AudioFileSource::set_build_missing_peakfiles (true);
639
640         /* set default clock modes */
641
642         primary_clock->set_mode (AudioClock::Timecode);
643         secondary_clock->set_mode (AudioClock::BBT);
644
645         /* start the time-of-day-clock */
646
647 #ifndef __APPLE__
648         /* OS X provides a nearly-always visible wallclock, so don't be stupid */
649         update_wall_clock ();
650         Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1);
651 #endif
652
653         {
654                 DisplaySuspender ds;
655                 Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
656                 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
657                 Config->map_parameters (pc);
658
659                 UIConfiguration::instance().map_parameters (pc);
660         }
661 }
662
663 ARDOUR_UI::~ARDOUR_UI ()
664 {
665         UIConfiguration::instance().save_state();
666
667         stop_video_server();
668
669         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
670                 // don't bother at 'real' exit. the OS cleans up for us.
671                 delete big_clock; big_clock = 0;
672                 delete primary_clock; primary_clock = 0;
673                 delete secondary_clock; secondary_clock = 0;
674                 delete _process_thread; _process_thread = 0;
675                 delete meterbridge; meterbridge = 0;
676                 delete luawindow; luawindow = 0;
677                 delete editor; editor = 0;
678                 delete mixer; mixer = 0;
679                 delete nsm; nsm = 0;
680                 delete gui_object_state; gui_object_state = 0;
681                 FastMeter::flush_pattern_cache ();
682                 PixFader::flush_pattern_cache ();
683         }
684
685 #ifndef NDEBUG
686         /* Small trick to flush main-thread event pool.
687          * Other thread-pools are destroyed at pthread_exit(),
688          * but tmain thread termination is too late to trigger Pool::~Pool()
689          */
690         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.
691         delete ev->event_pool();
692 #endif
693 }
694
695 void
696 ARDOUR_UI::pop_back_splash (Gtk::Window& win)
697 {
698         if (Splash::instance()) {
699                 Splash::instance()->pop_back_for (win);
700         }
701 }
702
703 gint
704 ARDOUR_UI::configure_timeout ()
705 {
706         if (last_configure_time == 0) {
707                 /* no configure events yet */
708                 return true;
709         }
710
711         /* force a gap of 0.5 seconds since the last configure event
712          */
713
714         if (get_microseconds() - last_configure_time < 500000) {
715                 return true;
716         } else {
717                 have_configure_timeout = false;
718                 save_ardour_state ();
719                 return false;
720         }
721 }
722
723 gboolean
724 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
725 {
726         if (have_configure_timeout) {
727                 last_configure_time = get_microseconds();
728         } else {
729                 Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
730                 have_configure_timeout = true;
731         }
732
733         return FALSE;
734 }
735
736 void
737 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
738 {
739         const XMLProperty* prop;
740
741         if ((prop = node.property ("roll")) != 0) {
742                 roll_controllable->set_id (prop->value());
743         }
744         if ((prop = node.property ("stop")) != 0) {
745                 stop_controllable->set_id (prop->value());
746         }
747         if ((prop = node.property ("goto-start")) != 0) {
748                 goto_start_controllable->set_id (prop->value());
749         }
750         if ((prop = node.property ("goto-end")) != 0) {
751                 goto_end_controllable->set_id (prop->value());
752         }
753         if ((prop = node.property ("auto-loop")) != 0) {
754                 auto_loop_controllable->set_id (prop->value());
755         }
756         if ((prop = node.property ("play-selection")) != 0) {
757                 play_selection_controllable->set_id (prop->value());
758         }
759         if ((prop = node.property ("rec")) != 0) {
760                 rec_controllable->set_id (prop->value());
761         }
762         if ((prop = node.property ("shuttle")) != 0) {
763                 shuttle_box->controllable()->set_id (prop->value());
764         }
765 }
766
767 XMLNode&
768 ARDOUR_UI::get_transport_controllable_state ()
769 {
770         XMLNode* node = new XMLNode(X_("TransportControllables"));
771         char buf[64];
772
773         roll_controllable->id().print (buf, sizeof (buf));
774         node->add_property (X_("roll"), buf);
775         stop_controllable->id().print (buf, sizeof (buf));
776         node->add_property (X_("stop"), buf);
777         goto_start_controllable->id().print (buf, sizeof (buf));
778         node->add_property (X_("goto_start"), buf);
779         goto_end_controllable->id().print (buf, sizeof (buf));
780         node->add_property (X_("goto_end"), buf);
781         auto_loop_controllable->id().print (buf, sizeof (buf));
782         node->add_property (X_("auto_loop"), buf);
783         play_selection_controllable->id().print (buf, sizeof (buf));
784         node->add_property (X_("play_selection"), buf);
785         rec_controllable->id().print (buf, sizeof (buf));
786         node->add_property (X_("rec"), buf);
787         shuttle_box->controllable()->id().print (buf, sizeof (buf));
788         node->add_property (X_("shuttle"), buf);
789
790         return *node;
791 }
792
793 void
794 ARDOUR_UI::save_session_at_its_request (std::string snapshot_name)
795 {
796         if (_session) {
797                 _session->save_state (snapshot_name);
798         }
799 }
800
801 gint
802 ARDOUR_UI::autosave_session ()
803 {
804         if (g_main_depth() > 1) {
805                 /* inside a recursive main loop,
806                    give up because we may not be able to
807                    take a lock.
808                 */
809                 return 1;
810         }
811
812         if (!Config->get_periodic_safety_backups()) {
813                 return 1;
814         }
815
816         if (_session) {
817                 _session->maybe_write_autosave();
818         }
819
820         return 1;
821 }
822
823 void
824 ARDOUR_UI::session_dirty_changed ()
825 {
826         update_autosave ();
827         update_title ();
828 }
829
830 void
831 ARDOUR_UI::update_autosave ()
832 {
833         if (_session && _session->dirty()) {
834                 if (_autosave_connection.connected()) {
835                         _autosave_connection.disconnect();
836                 }
837
838                 _autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
839                                 Config->get_periodic_safety_backup_interval() * 1000);
840
841         } else {
842                 if (_autosave_connection.connected()) {
843                         _autosave_connection.disconnect();
844                 }
845         }
846 }
847
848 void
849 ARDOUR_UI::check_announcements ()
850 {
851 #ifdef PHONE_HOME
852         string _annc_filename;
853
854 #ifdef __APPLE__
855         _annc_filename = PROGRAM_NAME "_announcements_osx_";
856 #elif defined PLATFORM_WINDOWS
857         _annc_filename = PROGRAM_NAME "_announcements_windows_";
858 #else
859         _annc_filename = PROGRAM_NAME "_announcements_linux_";
860 #endif
861         _annc_filename.append (VERSIONSTRING);
862
863         _announce_string = "";
864
865         std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
866         FILE* fin = g_fopen (path.c_str(), "rb");
867         if (fin) {
868                 while (!feof (fin)) {
869                         char tmp[1024];
870                         size_t len;
871                         if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
872                                 break;
873                         }
874                         _announce_string.append (tmp, len);
875                 }
876                 fclose (fin);
877         }
878
879         pingback (VERSIONSTRING, path);
880 #endif
881 }
882
883 static bool
884 _hide_splash (gpointer arg)
885 {
886         ((ARDOUR_UI*)arg)->hide_splash();
887         return false;
888 }
889
890 int
891 ARDOUR_UI::starting ()
892 {
893         Application* app = Application::instance ();
894         const char *nsm_url;
895         bool brand_new_user = ArdourStartup::required ();
896
897         app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
898         app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::load_from_application_api));
899
900         if (ARDOUR_COMMAND_LINE::check_announcements) {
901                 check_announcements ();
902         }
903
904         app->ready ();
905
906         /* we need to create this early because it may need to set the
907          *  audio backend end up.
908          */
909
910         try {
911                 audio_midi_setup.get (true);
912         } catch (...) {
913                 std::cerr << "audio-midi engine setup failed."<< std::endl;
914                 return -1;
915         }
916
917         if ((nsm_url = g_getenv ("NSM_URL")) != 0) {
918                 nsm = new NSM_Client;
919                 if (!nsm->init (nsm_url)) {
920                         /* the ardour executable may have different names:
921                          *
922                          * waf's obj.target for distro versions: eg ardour4, ardourvst4
923                          * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
924                          * argv[0] does not apply since we need the wrapper-script (not the binary itself)
925                          *
926                          * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
927                          */
928                         const char *process_name = g_getenv ("ARDOUR_SELF");
929                         nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour4");
930
931                         unsigned int i = 0;
932                         // wait for announce reply from nsm server
933                         for ( i = 0; i < 5000; ++i) {
934                                 nsm->check ();
935
936                                 Glib::usleep (i);
937                                 if (nsm->is_active()) {
938                                         break;
939                                 }
940                         }
941                         if (i == 5000) {
942                                 error << _("NSM server did not announce itself") << endmsg;
943                                 return -1;
944                         }
945                         // wait for open command from nsm server
946                         for ( i = 0; i < 5000; ++i) {
947                                 nsm->check ();
948                                 Glib::usleep (1000);
949                                 if (nsm->client_id ()) {
950                                         break;
951                                 }
952                         }
953
954                         if (i == 5000) {
955                                 error << _("NSM: no client ID provided") << endmsg;
956                                 return -1;
957                         }
958
959                         if (_session && nsm) {
960                                 _session->set_nsm_state( nsm->is_active() );
961                         } else {
962                                 error << _("NSM: no session created") << endmsg;
963                                 return -1;
964                         }
965
966                         // nsm requires these actions disabled
967                         vector<string> action_names;
968                         action_names.push_back("SaveAs");
969                         action_names.push_back("Rename");
970                         action_names.push_back("New");
971                         action_names.push_back("Open");
972                         action_names.push_back("Recent");
973                         action_names.push_back("Close");
974
975                         for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
976                                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
977                                 if (act) {
978                                         act->set_sensitive (false);
979                                 }
980                         }
981
982                 } else {
983                         delete nsm;
984                         nsm = 0;
985                         error << _("NSM: initialization failed") << endmsg;
986                         return -1;
987                 }
988
989         } else  {
990
991                 if (brand_new_user) {
992                         _initial_verbose_plugin_scan = true;
993                         ArdourStartup s;
994                         s.present ();
995                         main().run();
996                         s.hide ();
997                         _initial_verbose_plugin_scan = false;
998                         switch (s.response ()) {
999                         case Gtk::RESPONSE_OK:
1000                                 break;
1001                         default:
1002                                 return -1;
1003                         }
1004                 }
1005
1006 #ifdef NO_PLUGIN_STATE
1007
1008                 ARDOUR::RecentSessions rs;
1009                 ARDOUR::read_recent_sessions (rs);
1010
1011                 string path = Glib::build_filename (user_config_directory(), ".iknowaboutfreeversion");
1012
1013                 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS) && !rs.empty()) {
1014
1015                         /* already used Ardour, have sessions ... warn about plugin state */
1016
1017                         ArdourDialog d (_("Free/Demo Version Warning"), true);
1018                         Label l;
1019                         Button b (string_compose (_("Subscribe and support development of %1"), PROGRAM_NAME));
1020                         CheckButton c (_("Don't warn me about this again"));
1021
1022                         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"),
1023                                                       string_compose (_("This is a free/demo version of %1"), PROGRAM_NAME),
1024                                                       _("It will not restore OR save any plugin settings"),
1025                                                       _("If you load an existing session with plugin settings\n"
1026                                                         "they will not be used and will be lost."),
1027                                                       _("To get full access to updates without this limitation\n"
1028                                                         "consider becoming a subscriber for a low cost every month.")));
1029                         l.set_justify (JUSTIFY_CENTER);
1030
1031                         b.signal_clicked().connect (mem_fun(*this, &ARDOUR_UI::launch_subscribe));
1032
1033                         d.get_vbox()->pack_start (l, true, true);
1034                         d.get_vbox()->pack_start (b, false, false, 12);
1035                         d.get_vbox()->pack_start (c, false, false, 12);
1036
1037                         d.add_button (_("Quit now"), RESPONSE_CANCEL);
1038                         d.add_button (string_compose (_("Continue using %1"), PROGRAM_NAME), RESPONSE_OK);
1039
1040                         d.show_all ();
1041
1042                         c.signal_toggled().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (toggle_file_existence), path)));
1043
1044                         if (d.run () != RESPONSE_OK) {
1045                                 _exit (0);
1046                         }
1047                 }
1048 #endif
1049
1050                 /* go get a session */
1051
1052                 const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
1053
1054                 if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
1055                         std::cerr << "Cannot get session parameters."<< std::endl;
1056                         return -1;
1057                 }
1058         }
1059
1060         use_config ();
1061
1062         WM::Manager::instance().show_visible ();
1063
1064         /* We have to do this here since goto_editor_window() ends up calling show_all() on the
1065          * editor window, and we may want stuff to be hidden.
1066          */
1067         _status_bar_visibility.update ();
1068
1069         BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
1070
1071         if (splash && splash->is_visible()) {
1072                 // in 1 second, hide the splash screen
1073                 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
1074         }
1075
1076         /* all other dialogs are created conditionally */
1077
1078         return 0;
1079 }
1080
1081 void
1082 ARDOUR_UI::check_memory_locking ()
1083 {
1084 #if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
1085         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
1086         return;
1087 #else // !__APPLE__
1088
1089         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
1090
1091         if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
1092
1093                 struct rlimit limits;
1094                 int64_t ram;
1095                 long pages, page_size;
1096 #ifdef __FreeBSD__
1097                 size_t pages_len=sizeof(pages);
1098                 if ((page_size = getpagesize()) < 0 ||
1099                                 sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
1100 #else
1101                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
1102 #endif
1103                 {
1104                         ram = 0;
1105                 } else {
1106                         ram = (int64_t) pages * (int64_t) page_size;
1107                 }
1108
1109                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
1110                         return;
1111                 }
1112
1113                 if (limits.rlim_cur != RLIM_INFINITY) {
1114
1115                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
1116
1117                                 MessageDialog msg (
1118                                         string_compose (
1119                                                 _("WARNING: Your system has a limit for maximum amount of locked memory. "
1120                                                   "This might cause %1 to run out of memory before your system "
1121                                                   "runs out of memory. \n\n"
1122                                                   "You can view the memory limit with 'ulimit -l', "
1123                                                   "and it is normally controlled by %2"),
1124                                                 PROGRAM_NAME,
1125 #ifdef __FreeBSD__
1126                                                 X_("/etc/login.conf")
1127 #else
1128                                                 X_(" /etc/security/limits.conf")
1129 #endif
1130                                         ).c_str());
1131
1132                                 msg.set_default_response (RESPONSE_OK);
1133
1134                                 VBox* vbox = msg.get_vbox();
1135                                 HBox hbox;
1136                                 CheckButton cb (_("Do not show this window again"));
1137                                 hbox.pack_start (cb, true, false);
1138                                 vbox->pack_start (hbox);
1139                                 cb.show();
1140                                 vbox->show();
1141                                 hbox.show ();
1142
1143                                 pop_back_splash (msg);
1144
1145                                 msg.run ();
1146
1147                                 if (cb.get_active()) {
1148                                         XMLNode node (X_("no-memory-warning"));
1149                                         Config->add_instant_xml (node);
1150                                 }
1151                         }
1152                 }
1153         }
1154 #endif // !__APPLE__
1155 }
1156
1157
1158 void
1159 ARDOUR_UI::queue_finish ()
1160 {
1161         Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
1162 }
1163
1164 bool
1165 ARDOUR_UI::idle_finish ()
1166 {
1167         finish ();
1168         return false; /* do not call again */
1169 }
1170
1171 void
1172 ARDOUR_UI::finish()
1173 {
1174         if (_session) {
1175                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
1176
1177                 if (_session->dirty()) {
1178                         vector<string> actions;
1179                         actions.push_back (_("Don't quit"));
1180                         actions.push_back (_("Just quit"));
1181                         actions.push_back (_("Save and quit"));
1182                         switch (ask_about_saving_session(actions)) {
1183                         case -1:
1184                                 return;
1185                                 break;
1186                         case 1:
1187                                 /* use the default name */
1188                                 if (save_state_canfail ("")) {
1189                                         /* failed - don't quit */
1190                                         MessageDialog msg (_main_window,
1191                                                            string_compose (_("\
1192 %1 was unable to save your session.\n\n\
1193 If you still wish to quit, please use the\n\n\
1194 \"Just quit\" option."), PROGRAM_NAME));
1195                                         pop_back_splash(msg);
1196                                         msg.run ();
1197                                         return;
1198                                 }
1199                                 break;
1200                         case 0:
1201                                 break;
1202                         }
1203                 }
1204
1205                 second_connection.disconnect ();
1206                 point_one_second_connection.disconnect ();
1207                 point_zero_something_second_connection.disconnect();
1208                 fps_connection.disconnect();
1209         }
1210
1211         delete ARDOUR_UI::instance()->video_timeline;
1212         ARDOUR_UI::instance()->video_timeline = NULL;
1213         stop_video_server();
1214
1215         /* Save state before deleting the session, as that causes some
1216            windows to be destroyed before their visible state can be
1217            saved.
1218         */
1219         save_ardour_state ();
1220
1221         close_all_dialogs ();
1222
1223         if (_session) {
1224                 _session->set_clean ();
1225                 _session->remove_pending_capture_state ();
1226                 delete _session;
1227                 _session = 0;
1228         }
1229
1230         halt_connection.disconnect ();
1231         AudioEngine::instance()->stop ();
1232 #ifdef WINDOWS_VST_SUPPORT
1233         fst_stop_threading();
1234 #endif
1235         quit ();
1236 }
1237
1238 int
1239 ARDOUR_UI::ask_about_saving_session (const vector<string>& actions)
1240 {
1241         ArdourDialog window (_("Unsaved Session"));
1242         Gtk::HBox dhbox;  // the hbox for the image and text
1243         Gtk::Label  prompt_label;
1244         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
1245
1246         string msg;
1247
1248         assert (actions.size() >= 3);
1249
1250         window.add_button (actions[0], RESPONSE_REJECT);
1251         window.add_button (actions[1], RESPONSE_APPLY);
1252         window.add_button (actions[2], RESPONSE_ACCEPT);
1253
1254         window.set_default_response (RESPONSE_ACCEPT);
1255
1256         Gtk::Button noquit_button (msg);
1257         noquit_button.set_name ("EditorGTKButton");
1258
1259         string prompt;
1260
1261         if (_session->snap_name() == _session->name()) {
1262                 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?"),
1263                                         _session->snap_name());
1264         } else {
1265                 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?"),
1266                                         _session->snap_name());
1267         }
1268
1269         prompt_label.set_text (prompt);
1270         prompt_label.set_name (X_("PrompterLabel"));
1271         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
1272
1273         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
1274         dhbox.set_homogeneous (false);
1275         dhbox.pack_start (*dimage, false, false, 5);
1276         dhbox.pack_start (prompt_label, true, false, 5);
1277         window.get_vbox()->pack_start (dhbox);
1278
1279         window.set_name (_("Prompter"));
1280         window.set_modal (true);
1281         window.set_resizable (false);
1282
1283         dhbox.show();
1284         prompt_label.show();
1285         dimage->show();
1286         window.show();
1287         window.present ();
1288
1289         ResponseType r = (ResponseType) window.run();
1290
1291         window.hide ();
1292
1293         switch (r) {
1294         case RESPONSE_ACCEPT: // save and get out of here
1295                 return 1;
1296         case RESPONSE_APPLY:  // get out of here
1297                 return 0;
1298         default:
1299                 break;
1300         }
1301
1302         return -1;
1303 }
1304
1305
1306 void
1307 ARDOUR_UI::every_second ()
1308 {
1309         update_cpu_load ();
1310         update_xrun_count ();
1311         update_buffer_load ();
1312         update_disk_space ();
1313         update_timecode_format ();
1314         update_peak_thread_work ();
1315
1316         if (nsm && nsm->is_active ()) {
1317                 nsm->check ();
1318
1319                 if (!_was_dirty && _session->dirty ()) {
1320                         nsm->is_dirty ();
1321                         _was_dirty = true;
1322                 }
1323                 else if (_was_dirty && !_session->dirty ()){
1324                         nsm->is_clean ();
1325                         _was_dirty = false;
1326                 }
1327         }
1328 }
1329
1330 void
1331 ARDOUR_UI::every_point_one_seconds ()
1332 {
1333         // TODO get rid of this..
1334         // ShuttleControl is updated directly via TransportStateChange signal
1335 }
1336
1337 void
1338 ARDOUR_UI::every_point_zero_something_seconds ()
1339 {
1340         // august 2007: actual update frequency: 25Hz (40ms), not 100Hz
1341
1342         if (editor_meter && UIConfiguration::instance().get_show_editor_meter()) {
1343                 float mpeak = editor_meter->update_meters();
1344                 if (mpeak > editor_meter_max_peak) {
1345                         if (mpeak >= UIConfiguration::instance().get_meter_peak()) {
1346                                 editor_meter_peak_display.set_active_state ( Gtkmm2ext::ExplicitActive );
1347                         }
1348                 }
1349         }
1350 }
1351
1352 void
1353 ARDOUR_UI::set_fps_timeout_connection ()
1354 {
1355         unsigned int interval = 40;
1356         if (!_session) return;
1357         if (_session->timecode_frames_per_second() != 0) {
1358                 /* ideally we'll use a select() to sleep and not accumulate
1359                  * idle time to provide a regular periodic signal.
1360                  * See linux_vst_gui_support.cc 'elapsed_time_ms'.
1361                  * However, that'll require a dedicated thread and cross-thread
1362                  * signals to the GUI Thread..
1363                  */
1364                 interval = floor(500. /* update twice per FPS, since Glib::signal_timeout is very irregular */
1365                                 * _session->frame_rate() / _session->nominal_frame_rate()
1366                                 / _session->timecode_frames_per_second()
1367                                 );
1368 #ifdef PLATFORM_WINDOWS
1369                 // the smallest windows scheduler time-slice is ~15ms.
1370                 // periodic GUI timeouts shorter than that will cause
1371                 // WaitForSingleObject to spinlock (100% of one CPU Core)
1372                 // and gtk never enters idle mode.
1373                 // also changing timeBeginPeriod(1) does not affect that in
1374                 // any beneficial way, so we just limit the max rate for now.
1375                 interval = std::max(30u, interval); // at most ~33Hz.
1376 #else
1377                 interval = std::max(8u, interval); // at most 120Hz.
1378 #endif
1379         }
1380         fps_connection.disconnect();
1381         Timers::set_fps_interval (interval);
1382 }
1383
1384 void
1385 ARDOUR_UI::update_sample_rate (framecnt_t)
1386 {
1387         char buf[64];
1388
1389         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
1390
1391         if (!AudioEngine::instance()->connected()) {
1392
1393                 snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1394
1395         } else {
1396
1397                 framecnt_t rate = AudioEngine::instance()->sample_rate();
1398
1399                 if (rate == 0) {
1400                         /* no sample rate available */
1401                         snprintf (buf, sizeof (buf), "%s", _("Audio: <span foreground=\"red\">none</span>"));
1402                 } else {
1403
1404                         if (fmod (rate, 1000.0) != 0.0) {
1405                                 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%.1f kHz / %4.1f ms</span>"),
1406                                           (float) rate / 1000.0f,
1407                                           (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1408                         } else {
1409                                 snprintf (buf, sizeof (buf), _("Audio: <span foreground=\"green\">%" PRId64 " kHz / %4.1f ms</span>"),
1410                                           rate/1000,
1411                                           (AudioEngine::instance()->usecs_per_cycle() / 1000.0f));
1412                         }
1413                 }
1414         }
1415         sample_rate_label.set_markup (buf);
1416 }
1417
1418 void
1419 ARDOUR_UI::update_format ()
1420 {
1421         if (!_session) {
1422                 format_label.set_text ("");
1423                 return;
1424         }
1425
1426         stringstream s;
1427         s << _("File:") << X_(" <span foreground=\"green\">");
1428
1429         switch (_session->config.get_native_file_header_format ()) {
1430         case BWF:
1431                 s << _("BWF");
1432                 break;
1433         case WAVE:
1434                 s << _("WAV");
1435                 break;
1436         case WAVE64:
1437                 s << _("WAV64");
1438                 break;
1439         case CAF:
1440                 s << _("CAF");
1441                 break;
1442         case AIFF:
1443                 s << _("AIFF");
1444                 break;
1445         case iXML:
1446                 s << _("iXML");
1447                 break;
1448         case RF64:
1449                 s << _("RF64");
1450                 break;
1451         case RF64_WAV:
1452                 s << _("RF64/WAV");
1453                 break;
1454         case MBWF:
1455                 s << _("MBWF");
1456                 break;
1457         }
1458
1459         s << " ";
1460
1461         switch (_session->config.get_native_file_data_format ()) {
1462         case FormatFloat:
1463                 s << _("32-float");
1464                 break;
1465         case FormatInt24:
1466                 s << _("24-int");
1467                 break;
1468         case FormatInt16:
1469                 s << _("16-int");
1470                 break;
1471         }
1472
1473         s << X_("</span>");
1474
1475         format_label.set_markup (s.str ());
1476 }
1477
1478 void
1479 ARDOUR_UI::update_xrun_count ()
1480 {
1481         char buf[64];
1482
1483         /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1484            should also be changed.
1485         */
1486
1487         if (_session) {
1488                 const unsigned int x = _session->get_xrun_count ();
1489                 if (x > 9999) {
1490                         snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">&gt;10K</span>"), X_("red"));
1491                 } else {
1492                         snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">%u</span>"), x > 0 ? X_("red") : X_("green"), x);
1493                 }
1494         } else {
1495                 snprintf (buf, sizeof (buf), _("X: <span foreground=\"%s\">?</span>"), X_("yellow"));
1496         }
1497         xrun_label.set_markup (buf);
1498         set_tip (xrun_label, _("Audio dropouts. Shift+click to reset"));
1499 }
1500
1501 void
1502 ARDOUR_UI::update_cpu_load ()
1503 {
1504         char buf[64];
1505
1506         /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1507            should also be changed.
1508         */
1509
1510         double const c = AudioEngine::instance()->get_dsp_load ();
1511         snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c);
1512         cpu_load_label.set_markup (buf);
1513 }
1514
1515 void
1516 ARDOUR_UI::update_peak_thread_work ()
1517 {
1518         char buf[64];
1519         const int c = SourceFactory::peak_work_queue_length ();
1520         if (c > 0) {
1521                 snprintf (buf, sizeof (buf), _("PkBld: <span foreground=\"%s\">%d</span>"), c >= 2 ? X_("red") : X_("green"), c);
1522                 peak_thread_work_label.set_markup (buf);
1523         } else {
1524                 peak_thread_work_label.set_markup (X_(""));
1525         }
1526 }
1527
1528 void
1529 ARDOUR_UI::update_buffer_load ()
1530 {
1531         char buf[256];
1532
1533         uint32_t const playback = _session ? _session->playback_load () : 100;
1534         uint32_t const capture = _session ? _session->capture_load () : 100;
1535
1536         /* If this text is changed, the set_size_request_to_display_given_text call in ARDOUR_UI::resize_text_widgets
1537            should also be changed.
1538         */
1539
1540         if (_session) {
1541                 snprintf (
1542                         buf, sizeof (buf),
1543                         _("Buffers: <span foreground=\"green\">p:</span><span foreground=\"%s\">%" PRIu32 "%%</span> "
1544                                    "<span foreground=\"green\">c:</span><span foreground=\"%s\">%" PRIu32 "%%</span>"),
1545                         playback <= 5 ? X_("red") : X_("green"),
1546                         playback,
1547                         capture <= 5 ? X_("red") : X_("green"),
1548                         capture
1549                         );
1550
1551                 buffer_load_label.set_markup (buf);
1552         } else {
1553                 buffer_load_label.set_text ("");
1554         }
1555 }
1556
1557 void
1558 ARDOUR_UI::count_recenabled_streams (Route& route)
1559 {
1560         Track* track = dynamic_cast<Track*>(&route);
1561         if (track && track->record_enabled()) {
1562                 rec_enabled_streams += track->n_inputs().n_total();
1563         }
1564 }
1565
1566 void
1567 ARDOUR_UI::update_disk_space()
1568 {
1569         if (_session == 0) {
1570                 return;
1571         }
1572
1573         boost::optional<framecnt_t> opt_frames = _session->available_capture_duration();
1574         char buf[64];
1575         framecnt_t fr = _session->frame_rate();
1576
1577         if (fr == 0) {
1578                 /* skip update - no SR available */
1579                 return;
1580         }
1581
1582         if (!opt_frames) {
1583                 /* Available space is unknown */
1584                 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">Unknown</span>"));
1585         } else if (opt_frames.get_value_or (0) == max_framecnt) {
1586                 snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">24hrs+</span>"));
1587         } else {
1588                 rec_enabled_streams = 0;
1589                 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
1590
1591                 framecnt_t frames = opt_frames.get_value_or (0);
1592
1593                 if (rec_enabled_streams) {
1594                         frames /= rec_enabled_streams;
1595                 }
1596
1597                 int hrs;
1598                 int mins;
1599                 int secs;
1600
1601                 hrs  = frames / (fr * 3600);
1602
1603                 if (hrs > 24) {
1604                         snprintf (buf, sizeof (buf), "%s", _("Disk: <span foreground=\"green\">&gt;24 hrs</span>"));
1605                 } else {
1606                         frames -= hrs * fr * 3600;
1607                         mins = frames / (fr * 60);
1608                         frames -= mins * fr * 60;
1609                         secs = frames / fr;
1610
1611                         bool const low = (hrs == 0 && mins <= 30);
1612
1613                         snprintf (
1614                                 buf, sizeof(buf),
1615                                 _("Disk: <span foreground=\"%s\">%02dh:%02dm:%02ds</span>"),
1616                                 low ? X_("red") : X_("green"),
1617                                 hrs, mins, secs
1618                                 );
1619                 }
1620         }
1621
1622         disk_space_label.set_markup (buf);
1623 }
1624
1625 void
1626 ARDOUR_UI::update_timecode_format ()
1627 {
1628         char buf[64];
1629
1630         if (_session) {
1631                 bool matching;
1632                 TimecodeSlave* tcslave;
1633                 SyncSource sync_src = Config->get_sync_source();
1634
1635                 if ((sync_src == LTC || sync_src == MTC) && (tcslave = dynamic_cast<TimecodeSlave*>(_session->slave())) != 0) {
1636                         matching = (tcslave->apparent_timecode_format() == _session->config.get_timecode_format());
1637                 } else {
1638                         matching = true;
1639                 }
1640
1641                 snprintf (buf, sizeof (buf), S_("Timecode|TC: <span foreground=\"%s\">%s</span>"),
1642                           matching ? X_("green") : X_("red"),
1643                           Timecode::timecode_format_name (_session->config.get_timecode_format()).c_str());
1644         } else {
1645                 snprintf (buf, sizeof (buf), "TC: n/a");
1646         }
1647
1648         timecode_format_label.set_markup (buf);
1649 }
1650
1651 gint
1652 ARDOUR_UI::update_wall_clock ()
1653 {
1654         time_t now;
1655         struct tm *tm_now;
1656         static int last_min = -1;
1657
1658         time (&now);
1659         tm_now = localtime (&now);
1660         if (last_min != tm_now->tm_min) {
1661                 char buf[16];
1662                 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1663                 wall_clock_label.set_text (buf);
1664                 last_min = tm_now->tm_min;
1665         }
1666
1667         return TRUE;
1668 }
1669
1670 void
1671 ARDOUR_UI::open_recent_session ()
1672 {
1673         bool can_return = (_session != 0);
1674
1675         SessionDialog recent_session_dialog;
1676
1677         while (true) {
1678
1679                 ResponseType r = (ResponseType) recent_session_dialog.run ();
1680
1681                 switch (r) {
1682                 case RESPONSE_ACCEPT:
1683                         break;
1684                 default:
1685                         if (can_return) {
1686                                 recent_session_dialog.hide();
1687                                 return;
1688                         } else {
1689                                 exit (1);
1690                         }
1691                 }
1692
1693                 recent_session_dialog.hide();
1694
1695                 bool should_be_new;
1696
1697                 std::string path = recent_session_dialog.session_folder();
1698                 std::string state = recent_session_dialog.session_name (should_be_new);
1699
1700                 if (should_be_new == true) {
1701                         continue;
1702                 }
1703
1704                 _session_is_new = false;
1705
1706                 if (load_session (path, state) == 0) {
1707                         break;
1708                 }
1709
1710                 can_return = false;
1711         }
1712 }
1713
1714 bool
1715 ARDOUR_UI::check_audioengine (Gtk::Window& parent)
1716 {
1717         if (!AudioEngine::instance()->connected()) {
1718                 MessageDialog msg (parent, string_compose (
1719                                            _("%1 is not connected to any audio backend.\n"
1720                                              "You cannot open or close sessions in this condition"),
1721                                            PROGRAM_NAME));
1722                 pop_back_splash (msg);
1723                 msg.run ();
1724                 return false;
1725         }
1726         return true;
1727 }
1728
1729 void
1730 ARDOUR_UI::open_session ()
1731 {
1732         if (!check_audioengine (_main_window)) {
1733                 return;
1734         }
1735
1736         /* ardour sessions are folders */
1737         Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1738         open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1739         open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1740         open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1741
1742         if (_session) {
1743                 string session_parent_dir = Glib::path_get_dirname(_session->path());
1744                 open_session_selector.set_current_folder(session_parent_dir);
1745         } else {
1746                 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1747         }
1748
1749         Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1750         try {
1751                 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1752                 string default_session_folder = Config->get_default_session_parent_dir();
1753                 open_session_selector.add_shortcut_folder (default_session_folder);
1754         }
1755         catch (Glib::Error & e) {
1756                 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1757         }
1758
1759         FileFilter session_filter;
1760         session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1761         session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1762         open_session_selector.add_filter (session_filter);
1763         open_session_selector.set_filter (session_filter);
1764
1765         int response = open_session_selector.run();
1766         open_session_selector.hide ();
1767
1768         if (response == Gtk::RESPONSE_CANCEL) {
1769                 return;
1770         }
1771
1772         string session_path = open_session_selector.get_filename();
1773         string path, name;
1774         bool isnew;
1775
1776         if (session_path.length() > 0) {
1777                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1778                         _session_is_new = isnew;
1779                         load_session (path, name);
1780                 }
1781         }
1782 }
1783
1784 void
1785 ARDOUR_UI::session_add_mixed_track (
1786                 const ChanCount& input,
1787                 const ChanCount& output,
1788                 RouteGroup* route_group,
1789                 uint32_t how_many,
1790                 const string& name_template,
1791                 bool strict_io,
1792                 PluginInfoPtr instrument)
1793 {
1794         list<boost::shared_ptr<MidiTrack> > tracks;
1795
1796         if (_session == 0) {
1797                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1798                 return;
1799         }
1800
1801         try {
1802                 tracks = _session->new_midi_track (input, output, instrument, ARDOUR::Normal, route_group, how_many, name_template);
1803
1804                 if (tracks.size() != how_many) {
1805                         error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
1806                 }
1807         }
1808
1809         catch (...) {
1810                 display_insufficient_ports_message ();
1811                 return;
1812         }
1813
1814         if (strict_io) {
1815                 for (list<boost::shared_ptr<MidiTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
1816                         (*i)->set_strict_io (true);
1817                 }
1818         }
1819 }
1820
1821 void
1822 ARDOUR_UI::session_add_midi_bus (
1823                 RouteGroup* route_group,
1824                 uint32_t how_many,
1825                 const string& name_template,
1826                 bool strict_io,
1827                 PluginInfoPtr instrument)
1828 {
1829         RouteList routes;
1830
1831         if (_session == 0) {
1832                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1833                 return;
1834         }
1835
1836         try {
1837                 routes = _session->new_midi_route (route_group, how_many, name_template, instrument);
1838                 if (routes.size() != how_many) {
1839                         error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
1840                 }
1841
1842         }
1843         catch (...) {
1844                 display_insufficient_ports_message ();
1845                 return;
1846         }
1847
1848         if (strict_io) {
1849                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1850                         (*i)->set_strict_io (true);
1851                 }
1852         }
1853 }
1854
1855 void
1856 ARDOUR_UI::session_add_midi_route (
1857                 bool disk,
1858                 RouteGroup* route_group,
1859                 uint32_t how_many,
1860                 const string& name_template,
1861                 bool strict_io,
1862                 PluginInfoPtr instrument)
1863 {
1864         ChanCount one_midi_channel;
1865         one_midi_channel.set (DataType::MIDI, 1);
1866
1867         if (disk) {
1868                 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument);
1869         } else {
1870                 session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument);
1871         }
1872 }
1873
1874 void
1875 ARDOUR_UI::session_add_audio_route (
1876         bool track,
1877         int32_t input_channels,
1878         int32_t output_channels,
1879         ARDOUR::TrackMode mode,
1880         RouteGroup* route_group,
1881         uint32_t how_many,
1882         string const & name_template,
1883         bool strict_io
1884         )
1885 {
1886         list<boost::shared_ptr<AudioTrack> > tracks;
1887         RouteList routes;
1888
1889         if (_session == 0) {
1890                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1891                 return;
1892         }
1893
1894         try {
1895                 if (track) {
1896                         tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
1897
1898                         if (tracks.size() != how_many) {
1899                                 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
1900                                       << endmsg;
1901                         }
1902
1903                 } else {
1904
1905                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
1906
1907                         if (routes.size() != how_many) {
1908                                 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
1909                                       << endmsg;
1910                         }
1911                 }
1912         }
1913
1914         catch (...) {
1915                 display_insufficient_ports_message ();
1916                 return;
1917         }
1918
1919         if (strict_io) {
1920                 for (list<boost::shared_ptr<AudioTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
1921                         (*i)->set_strict_io (true);
1922                 }
1923                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1924                         (*i)->set_strict_io (true);
1925                 }
1926         }
1927 }
1928
1929 void
1930 ARDOUR_UI::display_insufficient_ports_message ()
1931 {
1932         MessageDialog msg (_main_window,
1933                         string_compose (_("There are insufficient ports available\n\
1934 to create a new track or bus.\n\
1935 You should save %1, exit and\n\
1936 restart with more ports."), PROGRAM_NAME));
1937         pop_back_splash (msg);
1938         msg.run ();
1939 }
1940
1941 void
1942 ARDOUR_UI::transport_goto_start ()
1943 {
1944         if (_session) {
1945                 _session->goto_start();
1946
1947                 /* force displayed area in editor to start no matter
1948                    what "follow playhead" setting is.
1949                 */
1950
1951                 if (editor) {
1952                         editor->center_screen (_session->current_start_frame ());
1953                 }
1954         }
1955 }
1956
1957 void
1958 ARDOUR_UI::transport_goto_zero ()
1959 {
1960         if (_session) {
1961                 _session->request_locate (0);
1962
1963                 /* force displayed area in editor to start no matter
1964                    what "follow playhead" setting is.
1965                 */
1966
1967                 if (editor) {
1968                         editor->reset_x_origin (0);
1969                 }
1970         }
1971 }
1972
1973 void
1974 ARDOUR_UI::transport_goto_wallclock ()
1975 {
1976         if (_session && editor) {
1977
1978                 time_t now;
1979                 struct tm tmnow;
1980                 framepos_t frames;
1981
1982                 time (&now);
1983                 localtime_r (&now, &tmnow);
1984
1985                 framecnt_t frame_rate = _session->frame_rate();
1986
1987                 if (frame_rate == 0) {
1988                         /* no frame rate available */
1989                         return;
1990                 }
1991
1992                 frames = tmnow.tm_hour * (60 * 60 * frame_rate);
1993                 frames += tmnow.tm_min * (60 * frame_rate);
1994                 frames += tmnow.tm_sec * frame_rate;
1995
1996                 _session->request_locate (frames, _session->transport_rolling ());
1997
1998                 /* force displayed area in editor to start no matter
1999                    what "follow playhead" setting is.
2000                 */
2001
2002                 if (editor) {
2003                         editor->center_screen (frames);
2004                 }
2005         }
2006 }
2007
2008 void
2009 ARDOUR_UI::transport_goto_end ()
2010 {
2011         if (_session) {
2012                 framepos_t const frame = _session->current_end_frame();
2013                 _session->request_locate (frame);
2014
2015                 /* force displayed area in editor to start no matter
2016                    what "follow playhead" setting is.
2017                 */
2018
2019                 if (editor) {
2020                         editor->center_screen (frame);
2021                 }
2022         }
2023 }
2024
2025 void
2026 ARDOUR_UI::transport_stop ()
2027 {
2028         if (!_session) {
2029                 return;
2030         }
2031
2032         if (_session->is_auditioning()) {
2033                 _session->cancel_audition ();
2034                 return;
2035         }
2036
2037         _session->request_stop (false, true);
2038 }
2039
2040 /** Check if any tracks are record enabled. If none are, record enable all of them.
2041  * @return true if track record-enabled status was changed, false otherwise.
2042  */
2043 bool
2044 ARDOUR_UI::trx_record_enable_all_tracks ()
2045 {
2046         if (!_session) {
2047                 return false;
2048         }
2049
2050         boost::shared_ptr<RouteList> rl = _session->get_tracks ();
2051         bool none_record_enabled = true;
2052
2053         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2054                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
2055                 assert (t);
2056
2057                 if (t->record_enabled()) {
2058                         none_record_enabled = false;
2059                         break;
2060                 }
2061         }
2062
2063         if (none_record_enabled) {
2064                 _session->set_record_enabled (rl, true, Session::rt_cleanup);
2065         }
2066
2067         return none_record_enabled;
2068 }
2069
2070 void
2071 ARDOUR_UI::transport_record (bool roll)
2072 {
2073         if (_session) {
2074                 switch (_session->record_status()) {
2075                 case Session::Disabled:
2076                         if (_session->ntracks() == 0) {
2077                                 MessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu."));
2078                                 msg.run ();
2079                                 return;
2080                         }
2081                         if (Profile->get_trx()) {
2082                                 roll = trx_record_enable_all_tracks ();
2083                         }
2084                         _session->maybe_enable_record ();
2085                         if (roll) {
2086                                 transport_roll ();
2087                         }
2088                         break;
2089                 case Session::Recording:
2090                         if (roll) {
2091                                 _session->request_stop();
2092                         } else {
2093                                 _session->disable_record (false, true);
2094                         }
2095                         break;
2096
2097                 case Session::Enabled:
2098                         _session->disable_record (false, true);
2099                 }
2100         }
2101 }
2102
2103 void
2104 ARDOUR_UI::transport_roll ()
2105 {
2106         if (!_session) {
2107                 return;
2108         }
2109
2110         if (_session->is_auditioning()) {
2111                 return;
2112         }
2113
2114 #if 0
2115         if (_session->config.get_external_sync()) {
2116                 switch (Config->get_sync_source()) {
2117                 case Engine:
2118                         break;
2119                 default:
2120                         /* transport controlled by the master */
2121                         return;
2122                 }
2123         }
2124 #endif
2125
2126         bool rolling = _session->transport_rolling();
2127
2128         if (_session->get_play_loop()) {
2129
2130                 /* If loop playback is not a mode, then we should cancel
2131                    it when this action is requested. If it is a mode
2132                    we just leave it in place.
2133                 */
2134
2135                 if (!Config->get_loop_is_mode()) {
2136                         /* XXX it is not possible to just leave seamless loop and keep
2137                            playing at present (nov 4th 2009)
2138                         */
2139                         if (!Config->get_seamless_loop()) {
2140                                 /* stop loop playback and stop rolling */
2141                                 _session->request_play_loop (false, true);
2142                         } else if (rolling) {
2143                                 /* stop loop playback but keep rolling */
2144                                 _session->request_play_loop (false, false);
2145                         }
2146                 }
2147
2148         } else if (_session->get_play_range () ) {
2149                 /* stop playing a range if we currently are */
2150                 _session->request_play_range (0, true);
2151         }
2152
2153         if (!rolling) {
2154                 _session->request_transport_speed (1.0f);
2155         }
2156 }
2157
2158 bool
2159 ARDOUR_UI::get_smart_mode() const
2160 {
2161         return ( editor->get_smart_mode() );
2162 }
2163
2164
2165 void
2166 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2167 {
2168         if (!_session) {
2169                 return;
2170         }
2171
2172         if (_session->is_auditioning()) {
2173                 _session->cancel_audition ();
2174                 return;
2175         }
2176
2177         if (_session->config.get_external_sync()) {
2178                 switch (Config->get_sync_source()) {
2179                 case Engine:
2180                         break;
2181                 default:
2182                         /* transport controlled by the master */
2183                         return;
2184                 }
2185         }
2186
2187         bool rolling = _session->transport_rolling();
2188         bool affect_transport = true;
2189
2190         if (rolling && roll_out_of_bounded_mode) {
2191                 /* drop out of loop/range playback but leave transport rolling */
2192                 if (_session->get_play_loop()) {
2193                         if (_session->actively_recording()) {
2194
2195                                 /* just stop using the loop, then actually stop
2196                                  * below
2197                                  */
2198                                 _session->request_play_loop (false, affect_transport);
2199
2200                         } else {
2201                                 if (Config->get_seamless_loop()) {
2202                                         /* the disk buffers contain copies of the loop - we can't
2203                                            just keep playing, so stop the transport. the user
2204                                            can restart as they wish.
2205                                         */
2206                                         affect_transport = true;
2207                                 } else {
2208                                         /* disk buffers are normal, so we can keep playing */
2209                                         affect_transport = false;
2210                                 }
2211                                 _session->request_play_loop (false, affect_transport);
2212                         }
2213                 } else if (_session->get_play_range ()) {
2214                         affect_transport = false;
2215                         _session->request_play_range (0, true);
2216                 }
2217         }
2218
2219         if (affect_transport) {
2220                 if (rolling) {
2221                         _session->request_stop (with_abort, true);
2222                 } else {
2223                         /* the only external sync condition we can be in here
2224                          * would be Engine (JACK) sync, in which case we still
2225                          * want to do this.
2226                          */
2227
2228                         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
2229                                 _session->request_play_range (&editor->get_selection().time, true);
2230                                 _session->set_requested_return_frame( editor->get_selection().time.front().start );  //force an auto-return here
2231                         }
2232                         _session->request_transport_speed (1.0f);
2233                 }
2234         }
2235 }
2236
2237 void
2238 ARDOUR_UI::toggle_session_auto_loop ()
2239 {
2240         if (!_session) {
2241                 return;
2242         }
2243
2244         Location * looploc = _session->locations()->auto_loop_location();
2245
2246         if (!looploc) {
2247                 return;
2248         }
2249
2250         if (_session->get_play_loop()) {
2251
2252                 /* looping enabled, our job is to disable it */
2253
2254                 _session->request_play_loop (false);
2255
2256         } else {
2257
2258                 /* looping not enabled, our job is to enable it.
2259
2260                    loop-is-NOT-mode: this action always starts the transport rolling.
2261                    loop-IS-mode:     this action simply sets the loop play mechanism, but
2262                                         does not start transport.
2263                 */
2264                 if (Config->get_loop_is_mode()) {
2265                         _session->request_play_loop (true, false);
2266                 } else {
2267                         _session->request_play_loop (true, true);
2268                 }
2269         }
2270
2271         //show the loop markers
2272         looploc->set_hidden (false, this);
2273 }
2274
2275 void
2276 ARDOUR_UI::transport_play_selection ()
2277 {
2278         if (!_session) {
2279                 return;
2280         }
2281
2282         editor->play_selection ();
2283 }
2284
2285 void
2286 ARDOUR_UI::transport_play_preroll ()
2287 {
2288         if (!_session) {
2289                 return;
2290         }
2291         editor->play_with_preroll ();
2292 }
2293
2294 void
2295 ARDOUR_UI::transport_rewind (int option)
2296 {
2297         float current_transport_speed;
2298
2299         if (_session) {
2300                 current_transport_speed = _session->transport_speed();
2301
2302                 if (current_transport_speed >= 0.0f) {
2303                         switch (option) {
2304                         case 0:
2305                                 _session->request_transport_speed (-1.0f);
2306                                 break;
2307                         case 1:
2308                                 _session->request_transport_speed (-4.0f);
2309                                 break;
2310                         case -1:
2311                                 _session->request_transport_speed (-0.5f);
2312                                 break;
2313                         }
2314                 } else {
2315                         /* speed up */
2316                         _session->request_transport_speed (current_transport_speed * 1.5f);
2317                 }
2318         }
2319 }
2320
2321 void
2322 ARDOUR_UI::transport_forward (int option)
2323 {
2324         if (!_session) {
2325                 return;
2326         }
2327
2328         float current_transport_speed = _session->transport_speed();
2329
2330         if (current_transport_speed <= 0.0f) {
2331                 switch (option) {
2332                 case 0:
2333                         _session->request_transport_speed (1.0f);
2334                         break;
2335                 case 1:
2336                         _session->request_transport_speed (4.0f);
2337                         break;
2338                 case -1:
2339                         _session->request_transport_speed (0.5f);
2340                         break;
2341                 }
2342         } else {
2343                 /* speed up */
2344                 _session->request_transport_speed (current_transport_speed * 1.5f);
2345         }
2346 }
2347
2348 void
2349 ARDOUR_UI::toggle_record_enable (uint32_t rid)
2350 {
2351         if (!_session) {
2352                 return;
2353         }
2354
2355         boost::shared_ptr<Route> r;
2356
2357         if ((r = _session->route_by_remote_id (rid)) != 0) {
2358
2359                 boost::shared_ptr<Track> t;
2360
2361                 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2362                         t->set_record_enabled (!t->record_enabled(), Controllable::UseGroup);
2363                 }
2364         }
2365 }
2366
2367 void
2368 ARDOUR_UI::map_transport_state ()
2369 {
2370         if (!_session) {
2371                 auto_loop_button.unset_active_state ();
2372                 play_selection_button.unset_active_state ();
2373                 roll_button.unset_active_state ();
2374                 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2375                 return;
2376         }
2377
2378         shuttle_box->map_transport_state ();
2379
2380         float sp = _session->transport_speed();
2381
2382         if (sp != 0.0f) {
2383
2384                 /* we're rolling */
2385
2386                 if (_session->get_play_range()) {
2387
2388                         play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2389                         roll_button.unset_active_state ();
2390                         auto_loop_button.unset_active_state ();
2391
2392                 } else if (_session->get_play_loop ()) {
2393
2394                         auto_loop_button.set_active (true);
2395                         play_selection_button.set_active (false);
2396                         if (Config->get_loop_is_mode()) {
2397                                 roll_button.set_active (true);
2398                         } else {
2399                                 roll_button.set_active (false);
2400                         }
2401
2402                 } else {
2403
2404                         roll_button.set_active (true);
2405                         play_selection_button.set_active (false);
2406                         auto_loop_button.set_active (false);
2407                 }
2408
2409                 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2410                         /* light up both roll and play-selection if they are joined */
2411                         roll_button.set_active (true);
2412                         play_selection_button.set_active (true);
2413                 }
2414
2415                 stop_button.set_active (false);
2416
2417         } else {
2418
2419                 stop_button.set_active (true);
2420                 roll_button.set_active (false);
2421                 play_selection_button.set_active (false);
2422                 if (Config->get_loop_is_mode ()) {
2423                         auto_loop_button.set_active (_session->get_play_loop());
2424                 } else {
2425                         auto_loop_button.set_active (false);
2426                 }
2427                 update_disk_space ();
2428         }
2429 }
2430
2431 void
2432 ARDOUR_UI::blink_handler (bool blink_on)
2433 {
2434         transport_rec_enable_blink (blink_on);
2435         solo_blink (blink_on);
2436         sync_blink (blink_on);
2437         audition_blink (blink_on);
2438         feedback_blink (blink_on);
2439         error_blink (blink_on);
2440 }
2441
2442 void
2443 ARDOUR_UI::update_clocks ()
2444 {
2445         if (!_session) return;
2446
2447         if (editor && !editor->dragging_playhead()) {
2448                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2449         }
2450 }
2451
2452 void
2453 ARDOUR_UI::start_clocking ()
2454 {
2455         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2456                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2457         } else {
2458                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2459         }
2460 }
2461
2462 void
2463 ARDOUR_UI::stop_clocking ()
2464 {
2465         clock_signal_connection.disconnect ();
2466 }
2467
2468 bool
2469 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2470 {
2471         char buf[256];
2472
2473         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2474
2475         label->set_text (buf);
2476         bar->set_fraction (fraction);
2477
2478         /* process events, redraws, etc. */
2479
2480         while (gtk_events_pending()) {
2481                 gtk_main_iteration ();
2482         }
2483
2484         return true; /* continue with save-as */
2485 }
2486
2487 void
2488 ARDOUR_UI::save_session_as ()
2489 {
2490         if (!_session) {
2491                 return;
2492         }
2493
2494         if (!save_as_dialog) {
2495                 save_as_dialog = new SaveAsDialog;
2496         }
2497
2498         save_as_dialog->set_name (_session->name());
2499
2500         int response = save_as_dialog->run ();
2501
2502         save_as_dialog->hide ();
2503
2504         switch (response) {
2505         case Gtk::RESPONSE_OK:
2506                 break;
2507         default:
2508                 return;
2509         }
2510
2511
2512         Session::SaveAs sa;
2513
2514         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2515         sa.new_name = save_as_dialog->new_name ();
2516         sa.switch_to = save_as_dialog->switch_to();
2517         sa.copy_media = save_as_dialog->copy_media();
2518         sa.copy_external = save_as_dialog->copy_external();
2519         sa.include_media = save_as_dialog->include_media ();
2520
2521         /* Only bother with a progress dialog if we're going to copy
2522            media into the save-as target. Without that choice, this
2523            will be very fast because we're only talking about a few kB's to
2524            perhaps a couple of MB's of data.
2525         */
2526
2527         ArdourDialog progress_dialog (_("Save As"), true);
2528
2529         if (sa.include_media && sa.copy_media) {
2530
2531                 Gtk::Label label;
2532                 Gtk::ProgressBar progress_bar;
2533
2534                 progress_dialog.get_vbox()->pack_start (label);
2535                 progress_dialog.get_vbox()->pack_start (progress_bar);
2536                 label.show ();
2537                 progress_bar.show ();
2538
2539                 /* this signal will be emitted from within this, the calling thread,
2540                  * after every file is copied. It provides information on percentage
2541                  * complete (in terms of total data to copy), the number of files
2542                  * copied so far, and the total number to copy.
2543                  */
2544
2545                 ScopedConnection c;
2546
2547                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
2548
2549                 progress_dialog.show_all ();
2550                 progress_dialog.present ();
2551         }
2552
2553         if (_session->save_as (sa)) {
2554                 /* ERROR MESSAGE */
2555                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2556                 msg.run ();
2557         }
2558
2559         if (!sa.include_media) {
2560                 unload_session (false);
2561                 load_session (sa.final_session_folder_name, sa.new_name);
2562         }
2563 }
2564
2565 void
2566 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2567 {
2568                 char timebuf[128];
2569                 time_t n;
2570                 struct tm local_time;
2571
2572                 time (&n);
2573                 localtime_r (&n, &local_time);
2574                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2575
2576                 save_state (timebuf, switch_to_it);
2577 }
2578
2579
2580 bool
2581 ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
2582 {
2583         string snapname;
2584
2585         prompter.get_result (snapname);
2586
2587         bool do_save = (snapname.length() != 0);
2588
2589         if (do_save) {
2590                 char illegal = Session::session_name_is_legal(snapname);
2591                 if (illegal) {
2592                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2593                                              "snapshot names may not contain a '%1' character"), illegal));
2594                         msg.run ();
2595                         return false;
2596                 }
2597         }
2598
2599         vector<std::string> p;
2600         get_state_files_in_directory (_session->session_directory().root_path(), p);
2601         vector<string> n = get_file_names_no_extension (p);
2602
2603         if (find (n.begin(), n.end(), snapname) != n.end()) {
2604
2605                 do_save = overwrite_file_dialog (prompter,
2606                                                  _("Confirm Snapshot Overwrite"),
2607                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2608         }
2609
2610         if (do_save) {
2611                 save_state (snapname, switch_to_it);
2612         }
2613         else {
2614                 return false;
2615         }
2616
2617         return true;
2618 }
2619
2620
2621 /** Ask the user for the name of a new snapshot and then take it.
2622  */
2623
2624 void
2625 ARDOUR_UI::snapshot_session (bool switch_to_it)
2626 {
2627         ArdourPrompter prompter (true);
2628
2629         prompter.set_name ("Prompter");
2630         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2631         if (switch_to_it) {
2632                 prompter.set_title (_("Save as..."));
2633                 prompter.set_prompt (_("New session name"));
2634         } else {
2635                 prompter.set_title (_("Take Snapshot"));
2636                 prompter.set_prompt (_("Name of new snapshot"));
2637         }
2638
2639         if (switch_to_it) {
2640                 prompter.set_initial_text (_session->snap_name());
2641         } else {
2642                 char timebuf[128];
2643                 time_t n;
2644                 struct tm local_time;
2645
2646                 time (&n);
2647                 localtime_r (&n, &local_time);
2648                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2649                 prompter.set_initial_text (timebuf);
2650         }
2651
2652         bool finished = false;
2653         while (!finished) {
2654                 switch (prompter.run()) {
2655                 case RESPONSE_ACCEPT:
2656                 {
2657                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2658                         break;
2659                 }
2660
2661                 default:
2662                         finished = true;
2663                         break;
2664                 }
2665         }
2666 }
2667
2668 /** Ask the user for a new session name and then rename the session to it.
2669  */
2670
2671 void
2672 ARDOUR_UI::rename_session ()
2673 {
2674         if (!_session) {
2675                 return;
2676         }
2677
2678         ArdourPrompter prompter (true);
2679         string name;
2680
2681         prompter.set_name ("Prompter");
2682         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2683         prompter.set_title (_("Rename Session"));
2684         prompter.set_prompt (_("New session name"));
2685
2686   again:
2687         switch (prompter.run()) {
2688         case RESPONSE_ACCEPT:
2689         {
2690                 prompter.get_result (name);
2691
2692                 bool do_rename = (name.length() != 0);
2693
2694                 if (do_rename) {
2695                         char illegal = Session::session_name_is_legal (name);
2696
2697                         if (illegal) {
2698                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2699                                                                      "session names may not contain a '%1' character"), illegal));
2700                                 msg.run ();
2701                                 goto again;
2702                         }
2703
2704                         switch (_session->rename (name)) {
2705                         case -1: {
2706                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2707                                 msg.set_position (WIN_POS_MOUSE);
2708                                 msg.run ();
2709                                 goto again;
2710                                 break;
2711                         }
2712                         case 0:
2713                                 break;
2714                         default: {
2715                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2716                                 msg.set_position (WIN_POS_MOUSE);
2717                                 msg.run ();
2718                                 break;
2719                         }
2720                         }
2721                 }
2722
2723                 break;
2724         }
2725
2726         default:
2727                 break;
2728         }
2729 }
2730
2731 void
2732 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2733 {
2734         if (!_session || _session->deletion_in_progress()) {
2735                 return;
2736         }
2737
2738         XMLNode* node = new XMLNode (X_("UI"));
2739
2740         WM::Manager::instance().add_state (*node);
2741
2742         node->add_child_nocopy (gui_object_state->get_state());
2743
2744         _session->add_extra_xml (*node);
2745
2746         if (export_video_dialog) {
2747                 _session->add_extra_xml (export_video_dialog->get_state());
2748         }
2749
2750         save_state_canfail (name, switch_to_it);
2751 }
2752
2753 int
2754 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2755 {
2756         if (_session) {
2757                 int ret;
2758
2759                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2760                         return ret;
2761                 }
2762         }
2763
2764         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2765         return 0;
2766 }
2767
2768 void
2769 ARDOUR_UI::primary_clock_value_changed ()
2770 {
2771         if (_session) {
2772                 _session->request_locate (primary_clock->current_time ());
2773         }
2774 }
2775
2776 void
2777 ARDOUR_UI::big_clock_value_changed ()
2778 {
2779         if (_session) {
2780                 _session->request_locate (big_clock->current_time ());
2781         }
2782 }
2783
2784 void
2785 ARDOUR_UI::secondary_clock_value_changed ()
2786 {
2787         if (_session) {
2788                 _session->request_locate (secondary_clock->current_time ());
2789         }
2790 }
2791
2792 void
2793 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2794 {
2795         if (_session == 0) {
2796                 return;
2797         }
2798
2799         if (_session->step_editing()) {
2800                 return;
2801         }
2802
2803         Session::RecordState const r = _session->record_status ();
2804         bool const h = _session->have_rec_enabled_track ();
2805
2806         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2807                 if (onoff) {
2808                         rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2809                 } else {
2810                         rec_button.set_active_state (Gtkmm2ext::Off);
2811                 }
2812         } else if (r == Session::Recording && h) {
2813                 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2814         } else {
2815                 rec_button.unset_active_state ();
2816         }
2817 }
2818
2819 bool
2820 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2821 {
2822         string name;
2823
2824         prompter.get_result (name);
2825
2826         if (name.length()) {
2827                 int failed = _session->save_template (name);
2828
2829                 if (failed == -2) { /* file already exists. */
2830                         bool overwrite = overwrite_file_dialog (prompter,
2831                                                                 _("Confirm Template Overwrite"),
2832                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
2833
2834                         if (overwrite) {
2835                                 _session->save_template (name, true);
2836                         }
2837                         else {
2838                                 return false;
2839                         }
2840                 }
2841         }
2842
2843         return true;
2844 }
2845
2846 void
2847 ARDOUR_UI::save_template ()
2848 {
2849         ArdourPrompter prompter (true);
2850
2851         if (!check_audioengine (_main_window)) {
2852                 return;
2853         }
2854
2855         prompter.set_name (X_("Prompter"));
2856         prompter.set_title (_("Save Template"));
2857         prompter.set_prompt (_("Name for template:"));
2858         prompter.set_initial_text(_session->name() + _("-template"));
2859         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2860
2861         bool finished = false;
2862         while (!finished) {
2863                 switch (prompter.run()) {
2864                 case RESPONSE_ACCEPT:
2865                         finished = process_save_template_prompter (prompter);
2866                         break;
2867
2868                 default:
2869                         finished = true;
2870                         break;
2871                 }
2872         }
2873 }
2874
2875 void
2876 ARDOUR_UI::edit_metadata ()
2877 {
2878         SessionMetadataEditor dialog;
2879         dialog.set_session (_session);
2880         dialog.grab_focus ();
2881         dialog.run ();
2882 }
2883
2884 void
2885 ARDOUR_UI::import_metadata ()
2886 {
2887         SessionMetadataImporter dialog;
2888         dialog.set_session (_session);
2889         dialog.run ();
2890 }
2891
2892 bool
2893 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2894 {
2895         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2896
2897         MessageDialog msg (str,
2898                            false,
2899                            Gtk::MESSAGE_WARNING,
2900                            Gtk::BUTTONS_YES_NO,
2901                            true);
2902
2903
2904         msg.set_name (X_("OpenExistingDialog"));
2905         msg.set_title (_("Open Existing Session"));
2906         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2907         msg.set_position (Gtk::WIN_POS_CENTER);
2908         pop_back_splash (msg);
2909
2910         switch (msg.run()) {
2911         case RESPONSE_YES:
2912                 return true;
2913                 break;
2914         }
2915         return false;
2916 }
2917
2918 int
2919 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
2920 {
2921         BusProfile bus_profile;
2922
2923         if (nsm) {
2924
2925                 bus_profile.master_out_channels = 2;
2926                 bus_profile.input_ac = AutoConnectPhysical;
2927                 bus_profile.output_ac = AutoConnectMaster;
2928                 bus_profile.requested_physical_in = 0; // use all available
2929                 bus_profile.requested_physical_out = 0; // use all available
2930
2931         } else {
2932
2933                 /* get settings from advanced section of NSD */
2934
2935                 if (sd.create_master_bus()) {
2936                         bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
2937                 } else {
2938                         bus_profile.master_out_channels = 0;
2939                 }
2940
2941                 if (sd.connect_inputs()) {
2942                         bus_profile.input_ac = AutoConnectPhysical;
2943                 } else {
2944                         bus_profile.input_ac = AutoConnectOption (0);
2945                 }
2946
2947                 bus_profile.output_ac = AutoConnectOption (0);
2948
2949                 if (sd.connect_outputs ()) {
2950                         if (sd.connect_outs_to_master()) {
2951                                 bus_profile.output_ac = AutoConnectMaster;
2952                         } else if (sd.connect_outs_to_physical()) {
2953                                 bus_profile.output_ac = AutoConnectPhysical;
2954                         }
2955                 }
2956
2957                 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
2958                 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
2959         }
2960
2961         if (build_session (session_path, session_name, bus_profile)) {
2962                 return -1;
2963         }
2964
2965         return 0;
2966 }
2967
2968 void
2969 ARDOUR_UI::load_from_application_api (const std::string& path)
2970 {
2971         ARDOUR_COMMAND_LINE::session_name = path;
2972         /* Cancel SessionDialog if it's visible to make OSX delegates work.
2973          *
2974          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
2975          * race-condition:
2976          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
2977          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
2978          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
2979          *    -> SessionDialog is not displayed
2980          */
2981
2982         if (_session_dialog) {
2983                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
2984                 std::string session_path = path;
2985                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
2986                         session_path = Glib::path_get_dirname (session_path);
2987                 }
2988                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
2989                 _session_dialog->set_provided_session (session_name, session_path);
2990                 _session_dialog->response (RESPONSE_NONE);
2991                 _session_dialog->hide();
2992                 return;
2993         }
2994
2995         int rv;
2996         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2997                 /* /path/to/foo => /path/to/foo, foo */
2998                 rv = load_session (path, basename_nosuffix (path));
2999         } else {
3000                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3001                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3002         }
3003
3004         // if load_session fails -> pop up SessionDialog.
3005         if (rv) {
3006                 ARDOUR_COMMAND_LINE::session_name = "";
3007
3008                 if (get_session_parameters (true, false)) {
3009                         exit (1);
3010                 }
3011         }
3012 }
3013
3014 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3015 int
3016 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3017 {
3018         string session_name;
3019         string session_path;
3020         string template_name;
3021         int ret = -1;
3022         bool likely_new = false;
3023         bool cancel_not_quit;
3024
3025         /* deal with any existing DIRTY session now, rather than later. don't
3026          * treat a non-dirty session this way, so that it stays visible
3027          * as we bring up the new session dialog.
3028          */
3029
3030         if (_session && ARDOUR_UI::instance()->video_timeline) {
3031                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3032         }
3033
3034         /* if there is already a session, relabel the button
3035            on the SessionDialog so that we don't Quit directly
3036         */
3037         cancel_not_quit = (_session != 0);
3038
3039         if (_session && _session->dirty()) {
3040                 if (unload_session (false)) {
3041                         /* unload cancelled by user */
3042                         return 0;
3043                 }
3044                 ARDOUR_COMMAND_LINE::session_name = "";
3045         }
3046
3047         if (!load_template.empty()) {
3048                 should_be_new = true;
3049                 template_name = load_template;
3050         }
3051
3052         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3053         session_path = ARDOUR_COMMAND_LINE::session_name;
3054
3055         if (!session_path.empty()) {
3056                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3057                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3058                                 /* session/snapshot file, change path to be dir */
3059                                 session_path = Glib::path_get_dirname (session_path);
3060                         }
3061                 }
3062         }
3063
3064         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3065
3066         _session_dialog = &session_dialog;
3067         while (ret != 0) {
3068
3069                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3070
3071                         /* if they named a specific statefile, use it, otherwise they are
3072                            just giving a session folder, and we want to use it as is
3073                            to find the session.
3074                         */
3075
3076                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3077
3078                         if (suffix != string::npos) {
3079                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3080                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3081                                 session_name = Glib::path_get_basename (session_name);
3082                         } else {
3083                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3084                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3085                         }
3086                 } else {
3087                         session_path = "";
3088                         session_name = "";
3089                         session_dialog.clear_given ();
3090                 }
3091
3092                 if (should_be_new || session_name.empty()) {
3093                         /* need the dialog to get info from user */
3094
3095                         cerr << "run dialog\n";
3096
3097                         switch (session_dialog.run()) {
3098                         case RESPONSE_ACCEPT:
3099                                 break;
3100                         case RESPONSE_NONE:
3101                                 /* this is used for async * app->ShouldLoad(). */
3102                                 continue; // while loop
3103                                 break;
3104                         default:
3105                                 if (quit_on_cancel) {
3106                                         // JE - Currently (July 2014) this section can only get reached if the
3107                                         // user quits from the main 'Session Setup' dialog (i.e. reaching this
3108                                         // point does NOT indicate an abnormal termination). Therefore, let's
3109                                         // behave gracefully (i.e. let's do some cleanup) before we call exit()
3110                                         ARDOUR::cleanup ();
3111                                         pthread_cancel_all ();
3112
3113                                         exit (1);
3114                                 } else {
3115                                         return ret;
3116                                 }
3117                         }
3118
3119                         session_dialog.hide ();
3120                 }
3121
3122                 /* if we run the startup dialog again, offer more than just "new session" */
3123
3124                 should_be_new = false;
3125
3126                 session_name = session_dialog.session_name (likely_new);
3127                 session_path = session_dialog.session_folder ();
3128
3129                 if (nsm) {
3130                         likely_new = true;
3131                 }
3132
3133                 string::size_type suffix = session_name.find (statefile_suffix);
3134
3135                 if (suffix != string::npos) {
3136                         session_name = session_name.substr (0, suffix);
3137                 }
3138
3139                 /* this shouldn't happen, but we catch it just in case it does */
3140
3141                 if (session_name.empty()) {
3142                         continue;
3143                 }
3144
3145                 if (session_dialog.use_session_template()) {
3146                         template_name = session_dialog.session_template_name();
3147                         _session_is_new = true;
3148                 }
3149
3150                 if (session_name[0] == G_DIR_SEPARATOR ||
3151 #ifdef PLATFORM_WINDOWS
3152                     (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3153 #else
3154                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3155                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3156 #endif
3157                          )
3158                 {
3159
3160                         /* absolute path or cwd-relative path specified for session name: infer session folder
3161                            from what was given.
3162                         */
3163
3164                         session_path = Glib::path_get_dirname (session_name);
3165                         session_name = Glib::path_get_basename (session_name);
3166
3167                 } else {
3168
3169                         session_path = session_dialog.session_folder();
3170
3171                         char illegal = Session::session_name_is_legal (session_name);
3172
3173                         if (illegal) {
3174                                 MessageDialog msg (session_dialog,
3175                                                    string_compose (_("To ensure compatibility with various systems\n"
3176                                                                      "session names may not contain a '%1' character"),
3177                                                                    illegal));
3178                                 msg.run ();
3179                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3180                                 continue;
3181                         }
3182                 }
3183
3184                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3185
3186
3187                         if (likely_new && !nsm) {
3188
3189                                 std::string existing = Glib::build_filename (session_path, session_name);
3190
3191                                 if (!ask_about_loading_existing_session (existing)) {
3192                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3193                                         continue;
3194                                 }
3195                         }
3196
3197                         _session_is_new = false;
3198
3199                 } else {
3200
3201                         if (!likely_new) {
3202                                 pop_back_splash (session_dialog);
3203                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3204                                 msg.run ();
3205                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3206                                 continue;
3207                         }
3208
3209                         char illegal = Session::session_name_is_legal(session_name);
3210
3211                         if (illegal) {
3212                                 pop_back_splash (session_dialog);
3213                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3214                                                                                     "session names may not contain a '%1' character"), illegal));
3215                                 msg.run ();
3216                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3217                                 continue;
3218                         }
3219
3220                         _session_is_new = true;
3221                 }
3222
3223                 if (likely_new && template_name.empty()) {
3224
3225                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3226
3227                 } else {
3228
3229                         ret = load_session (session_path, session_name, template_name);
3230
3231                         if (ret == -2) {
3232                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3233                                 exit (1);
3234                         }
3235
3236                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3237                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3238                                 exit (1);
3239                         }
3240
3241                         /* clear this to avoid endless attempts to load the
3242                            same session.
3243                         */
3244
3245                         ARDOUR_COMMAND_LINE::session_name = "";
3246                 }
3247         }
3248
3249         _session_dialog = NULL;
3250
3251         return ret;
3252 }
3253
3254 void
3255 ARDOUR_UI::close_session()
3256 {
3257         if (!check_audioengine (_main_window)) {
3258                 return;
3259         }
3260
3261         if (unload_session (true)) {
3262                 return;
3263         }
3264
3265         ARDOUR_COMMAND_LINE::session_name = "";
3266
3267         if (get_session_parameters (true, false)) {
3268                 exit (1);
3269         }
3270 }
3271
3272 /** @param snap_name Snapshot name (without .ardour suffix).
3273  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3274  */
3275 int
3276 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3277 {
3278         Session *new_session;
3279         int unload_status;
3280         int retval = -1;
3281
3282         if (_session) {
3283                 unload_status = unload_session ();
3284
3285                 if (unload_status < 0) {
3286                         goto out;
3287                 } else if (unload_status > 0) {
3288                         retval = 0;
3289                         goto out;
3290                 }
3291         }
3292
3293         session_loaded = false;
3294
3295         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3296
3297         try {
3298                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3299         }
3300
3301         /* this one is special */
3302
3303         catch (AudioEngine::PortRegistrationFailure& err) {
3304
3305                 MessageDialog msg (err.what(),
3306                                    true,
3307                                    Gtk::MESSAGE_INFO,
3308                                    Gtk::BUTTONS_CLOSE);
3309
3310                 msg.set_title (_("Port Registration Error"));
3311                 msg.set_secondary_text (_("Click the Close button to try again."));
3312                 msg.set_position (Gtk::WIN_POS_CENTER);
3313                 pop_back_splash (msg);
3314                 msg.present ();
3315
3316                 int response = msg.run ();
3317
3318                 msg.hide ();
3319
3320                 switch (response) {
3321                 case RESPONSE_CANCEL:
3322                         exit (1);
3323                 default:
3324                         break;
3325                 }
3326                 goto out;
3327         }
3328         catch (SessionException e) {
3329                 MessageDialog msg (string_compose(
3330                                            _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3331                                            path, snap_name, e.what()),
3332                                    true,
3333                                    Gtk::MESSAGE_INFO,
3334                                    BUTTONS_OK);
3335
3336                 msg.set_title (_("Loading Error"));
3337                 msg.set_position (Gtk::WIN_POS_CENTER);
3338                 pop_back_splash (msg);
3339                 msg.present ();
3340
3341                 dump_errors (cerr);
3342
3343                 (void) msg.run ();
3344                 msg.hide ();
3345
3346                 goto out;
3347         }
3348         catch (...) {
3349
3350                 MessageDialog msg (string_compose(
3351                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
3352                                            path, snap_name),
3353                                    true,
3354                                    Gtk::MESSAGE_INFO,
3355                                    BUTTONS_OK);
3356
3357                 msg.set_title (_("Loading Error"));
3358                 msg.set_position (Gtk::WIN_POS_CENTER);
3359                 pop_back_splash (msg);
3360                 msg.present ();
3361
3362                 dump_errors (cerr);
3363
3364                 (void) msg.run ();
3365                 msg.hide ();
3366
3367                 goto out;
3368         }
3369
3370         {
3371                 list<string> const u = new_session->unknown_processors ();
3372                 if (!u.empty()) {
3373                         MissingPluginDialog d (_session, u);
3374                         d.run ();
3375                 }
3376         }
3377
3378         if (!new_session->writable()) {
3379                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3380                                    true,
3381                                    Gtk::MESSAGE_INFO,
3382                                    BUTTONS_OK);
3383
3384                 msg.set_title (_("Read-only Session"));
3385                 msg.set_position (Gtk::WIN_POS_CENTER);
3386                 pop_back_splash (msg);
3387                 msg.present ();
3388                 (void) msg.run ();
3389                 msg.hide ();
3390         }
3391
3392
3393         /* Now the session been created, add the transport controls */
3394         new_session->add_controllable(roll_controllable);
3395         new_session->add_controllable(stop_controllable);
3396         new_session->add_controllable(goto_start_controllable);
3397         new_session->add_controllable(goto_end_controllable);
3398         new_session->add_controllable(auto_loop_controllable);
3399         new_session->add_controllable(play_selection_controllable);
3400         new_session->add_controllable(rec_controllable);
3401
3402         set_session (new_session);
3403
3404         session_loaded = true;
3405
3406         if (_session) {
3407                 _session->set_clean ();
3408         }
3409
3410 #ifdef WINDOWS_VST_SUPPORT
3411         fst_stop_threading();
3412 #endif
3413
3414         {
3415                 Timers::TimerSuspender t;
3416                 flush_pending ();
3417         }
3418
3419 #ifdef WINDOWS_VST_SUPPORT
3420         fst_start_threading();
3421 #endif
3422         retval = 0;
3423
3424   out:
3425         return retval;
3426 }
3427
3428 int
3429 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3430 {
3431         Session *new_session;
3432         int x;
3433
3434         session_loaded = false;
3435         x = unload_session ();
3436
3437         if (x < 0) {
3438                 return -1;
3439         } else if (x > 0) {
3440                 return 0;
3441         }
3442
3443         _session_is_new = true;
3444
3445         try {
3446                 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3447         }
3448
3449         catch (SessionException e) {
3450                 dump_errors (cerr);
3451                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3452                 msg.set_title (_("Loading Error"));
3453                 msg.set_position (Gtk::WIN_POS_CENTER);
3454                 pop_back_splash (msg);
3455                 msg.run ();
3456                 return -1;
3457         }
3458         catch (...) {
3459                 dump_errors (cerr);
3460                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3461                 msg.set_title (_("Loading Error"));
3462                 msg.set_position (Gtk::WIN_POS_CENTER);
3463                 pop_back_splash (msg);
3464                 msg.run ();
3465                 return -1;
3466         }
3467
3468         /* Give the new session the default GUI state, if such things exist */
3469
3470         XMLNode* n;
3471         n = Config->instant_xml (X_("Editor"));
3472         if (n) {
3473                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3474                 new_session->add_instant_xml (*n, false);
3475         }
3476         n = Config->instant_xml (X_("Mixer"));
3477         if (n) {
3478                 new_session->add_instant_xml (*n, false);
3479         }
3480
3481         /* Put the playhead at 0 and scroll fully left */
3482         n = new_session->instant_xml (X_("Editor"));
3483         if (n) {
3484                 n->add_property (X_("playhead"), X_("0"));
3485                 n->add_property (X_("left-frame"), X_("0"));
3486         }
3487
3488         set_session (new_session);
3489
3490         session_loaded = true;
3491
3492         new_session->save_state(new_session->name());
3493
3494         return 0;
3495 }
3496
3497 void
3498 ARDOUR_UI::launch_chat ()
3499 {
3500         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3501
3502         dialog.set_title (_("About the Chat"));
3503         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."));
3504
3505         switch (dialog.run()) {
3506         case RESPONSE_OK:
3507 #ifdef __APPLE__
3508                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3509 #elif defined PLATFORM_WINDOWS
3510                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3511 #else
3512                 open_uri("http://webchat.freenode.net/?channels=ardour");
3513 #endif
3514                 break;
3515         default:
3516                 break;
3517         }
3518 }
3519
3520 void
3521 ARDOUR_UI::launch_manual ()
3522 {
3523         PBD::open_uri (Config->get_tutorial_manual_url());
3524 }
3525
3526 void
3527 ARDOUR_UI::launch_reference ()
3528 {
3529         PBD::open_uri (Config->get_reference_manual_url());
3530 }
3531
3532 void
3533 ARDOUR_UI::launch_tracker ()
3534 {
3535         PBD::open_uri ("http://tracker.ardour.org");
3536 }
3537
3538 void
3539 ARDOUR_UI::launch_subscribe ()
3540 {
3541         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3542 }
3543
3544 void
3545 ARDOUR_UI::launch_cheat_sheet ()
3546 {
3547 #ifdef __APPLE__
3548         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3549 #else
3550         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3551 #endif
3552 }
3553
3554 void
3555 ARDOUR_UI::launch_website ()
3556 {
3557         PBD::open_uri ("http://ardour.org");
3558 }
3559
3560 void
3561 ARDOUR_UI::launch_website_dev ()
3562 {
3563         PBD::open_uri ("http://ardour.org/development.html");
3564 }
3565
3566 void
3567 ARDOUR_UI::launch_forums ()
3568 {
3569         PBD::open_uri ("https://community.ardour.org/forums");
3570 }
3571
3572 void
3573 ARDOUR_UI::launch_howto_report ()
3574 {
3575         PBD::open_uri ("http://ardour.org/reporting_bugs");
3576 }
3577
3578 void
3579 ARDOUR_UI::loading_message (const std::string& msg)
3580 {
3581         if (ARDOUR_COMMAND_LINE::no_splash) {
3582                 return;
3583         }
3584
3585         if (!splash) {
3586                 show_splash ();
3587         }
3588
3589         splash->message (msg);
3590 }
3591
3592 void
3593 ARDOUR_UI::show_splash ()
3594 {
3595         if (splash == 0) {
3596                 try {
3597                         splash = new Splash;
3598                 } catch (...) {
3599                         return;
3600                 }
3601         }
3602
3603         splash->display ();
3604 }
3605
3606 void
3607 ARDOUR_UI::hide_splash ()
3608 {
3609         delete splash;
3610         splash = 0;
3611 }
3612
3613 void
3614 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3615 {
3616         size_t removed;
3617
3618         removed = rep.paths.size();
3619
3620         if (removed == 0) {
3621                 MessageDialog msgd (_main_window,
3622                                     _("No files were ready for clean-up"),
3623                                     true,
3624                                     Gtk::MESSAGE_INFO,
3625                                     Gtk::BUTTONS_OK);
3626                 msgd.set_title (_("Clean-up"));
3627                 msgd.set_secondary_text (_("If this seems suprising, \n\
3628 check for any existing snapshots.\n\
3629 These may still include regions that\n\
3630 require some unused files to continue to exist."));
3631
3632                 msgd.run ();
3633                 return;
3634         }
3635
3636         ArdourDialog results (_("Clean-up"), true, false);
3637
3638         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3639             CleanupResultsModelColumns() {
3640                     add (visible_name);
3641                     add (fullpath);
3642             }
3643             Gtk::TreeModelColumn<std::string> visible_name;
3644             Gtk::TreeModelColumn<std::string> fullpath;
3645         };
3646
3647
3648         CleanupResultsModelColumns results_columns;
3649         Glib::RefPtr<Gtk::ListStore> results_model;
3650         Gtk::TreeView results_display;
3651
3652         results_model = ListStore::create (results_columns);
3653         results_display.set_model (results_model);
3654         results_display.append_column (list_title, results_columns.visible_name);
3655
3656         results_display.set_name ("CleanupResultsList");
3657         results_display.set_headers_visible (true);
3658         results_display.set_headers_clickable (false);
3659         results_display.set_reorderable (false);
3660
3661         Gtk::ScrolledWindow list_scroller;
3662         Gtk::Label txt;
3663         Gtk::VBox dvbox;
3664         Gtk::HBox dhbox;  // the hbox for the image and text
3665         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3666         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3667
3668         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3669
3670         const string dead_directory = _session->session_directory().dead_path();
3671
3672         /* subst:
3673            %1 - number of files removed
3674            %2 - location of "dead"
3675            %3 - size of files affected
3676            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3677         */
3678
3679         const char* bprefix;
3680         double space_adjusted = 0;
3681
3682         if (rep.space < 1000) {
3683                 bprefix = X_("");
3684                 space_adjusted = rep.space;
3685         } else if (rep.space < 1000000) {
3686                 bprefix = _("kilo");
3687                 space_adjusted = floorf((float)rep.space / 1000.0);
3688         } else if (rep.space < 1000000 * 1000) {
3689                 bprefix = _("mega");
3690                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3691         } else {
3692                 bprefix = _("giga");
3693                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3694         }
3695
3696         if (msg_delete) {
3697                 txt.set_markup (string_compose (P_("\
3698 The following file was deleted from %2,\n\
3699 releasing %3 %4bytes of disk space", "\
3700 The following %1 files were deleted from %2,\n\
3701 releasing %3 %4bytes of disk space", removed),
3702                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3703         } else {
3704                 txt.set_markup (string_compose (P_("\
3705 The following file was not in use and \n\
3706 has been moved to: %2\n\n\
3707 After a restart of %5\n\n\
3708 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3709 will release an additional %3 %4bytes of disk space.\n", "\
3710 The following %1 files were not in use and \n\
3711 have been moved to: %2\n\n\
3712 After a restart of %5\n\n\
3713 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3714 will release an additional %3 %4bytes of disk space.\n", removed),
3715                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3716         }
3717
3718         dhbox.pack_start (*dimage, true, false, 5);
3719         dhbox.pack_start (txt, true, false, 5);
3720
3721         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3722                 TreeModel::Row row = *(results_model->append());
3723                 row[results_columns.visible_name] = *i;
3724                 row[results_columns.fullpath] = *i;
3725         }
3726
3727         list_scroller.add (results_display);
3728         list_scroller.set_size_request (-1, 150);
3729         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3730
3731         dvbox.pack_start (dhbox, true, false, 5);
3732         dvbox.pack_start (list_scroller, true, false, 5);
3733         ddhbox.pack_start (dvbox, true, false, 5);
3734
3735         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3736         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3737         results.set_default_response (RESPONSE_CLOSE);
3738         results.set_position (Gtk::WIN_POS_MOUSE);
3739
3740         results_display.show();
3741         list_scroller.show();
3742         txt.show();
3743         dvbox.show();
3744         dhbox.show();
3745         ddhbox.show();
3746         dimage->show();
3747
3748         //results.get_vbox()->show();
3749         results.set_resizable (false);
3750
3751         results.run ();
3752
3753 }
3754
3755 void
3756 ARDOUR_UI::cleanup ()
3757 {
3758         if (_session == 0) {
3759                 /* shouldn't happen: menu item is insensitive */
3760                 return;
3761         }
3762
3763
3764         MessageDialog checker (_("Are you sure you want to clean-up?"),
3765                                 true,
3766                                 Gtk::MESSAGE_QUESTION,
3767                                 Gtk::BUTTONS_NONE);
3768
3769         checker.set_title (_("Clean-up"));
3770
3771         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3772 ALL undo/redo information will be lost if you clean-up.\n\
3773 Clean-up will move all unused files to a \"dead\" location."));
3774
3775         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3776         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3777         checker.set_default_response (RESPONSE_CANCEL);
3778
3779         checker.set_name (_("CleanupDialog"));
3780         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3781         checker.set_position (Gtk::WIN_POS_MOUSE);
3782
3783         switch (checker.run()) {
3784         case RESPONSE_ACCEPT:
3785                 break;
3786         default:
3787                 return;
3788         }
3789
3790         ARDOUR::CleanupReport rep;
3791
3792         editor->prepare_for_cleanup ();
3793
3794         /* do not allow flush until a session is reloaded */
3795
3796         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3797         if (act) {
3798                 act->set_sensitive (false);
3799         }
3800
3801         if (_session->cleanup_sources (rep)) {
3802                 editor->finish_cleanup ();
3803                 return;
3804         }
3805
3806         editor->finish_cleanup ();
3807
3808         checker.hide();
3809         display_cleanup_results (rep, _("Cleaned Files"), false);
3810 }
3811
3812 void
3813 ARDOUR_UI::flush_trash ()
3814 {
3815         if (_session == 0) {
3816                 /* shouldn't happen: menu item is insensitive */
3817                 return;
3818         }
3819
3820         ARDOUR::CleanupReport rep;
3821
3822         if (_session->cleanup_trash_sources (rep)) {
3823                 return;
3824         }
3825
3826         display_cleanup_results (rep, _("deleted file"), true);
3827 }
3828
3829 void
3830 ARDOUR_UI::cleanup_peakfiles ()
3831 {
3832         if (_session == 0) {
3833                 /* shouldn't happen: menu item is insensitive */
3834                 return;
3835         }
3836
3837         if (! _session->can_cleanup_peakfiles ()) {
3838                 return;
3839         }
3840
3841         // get all region-views in this session
3842         RegionSelection rs;
3843         TrackViewList empty;
3844         empty.clear();
3845         editor->get_regions_after(rs, (framepos_t) 0, empty);
3846         std::list<RegionView*> views = rs.by_layer();
3847
3848         // remove displayed audio-region-views waveforms
3849         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3850                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3851                 if (!arv) { continue ; }
3852                 arv->delete_waves();
3853         }
3854
3855         // cleanup peak files:
3856         // - stop pending peakfile threads
3857         // - close peakfiles if any
3858         // - remove peak dir in session
3859         // - setup peakfiles (background thread)
3860         _session->cleanup_peakfiles ();
3861
3862         // re-add waves to ARV
3863         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3864                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3865                 if (!arv) { continue ; }
3866                 arv->create_waves();
3867         }
3868 }
3869
3870 void
3871 ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
3872 {
3873         uint32_t order_hint = UINT32_MAX;
3874
3875         if (editor->get_selection().tracks.empty()) {
3876                 return;
3877         }
3878
3879         /*
3880           we want the new routes to have their order keys set starting from
3881           the highest order key in the selection + 1 (if available).
3882         */
3883
3884         if (place == AddRouteDialog::AfterSelection) {
3885                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
3886                 if (rtav) {
3887                         order_hint = rtav->route()->order_key();
3888                         order_hint++;
3889                 }
3890         } else if (place == AddRouteDialog::BeforeSelection) {
3891                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
3892                 if (rtav) {
3893                         order_hint = rtav->route()->order_key();
3894                 }
3895         } else if (place == AddRouteDialog::First) {
3896                 order_hint = 0;
3897         } else {
3898                 /* leave order_hint at UINT32_MAX */
3899         }
3900
3901         if (order_hint == UINT32_MAX) {
3902                 /** AddRouteDialog::Last or selection with first/last not a RouteTimeAxisView
3903                  * not setting an order hint will place new routes last.
3904                  */
3905                 return;
3906         }
3907
3908         _session->set_order_hint (order_hint);
3909
3910         /* create a gap in the existing route order keys to accomodate new routes.*/
3911         boost::shared_ptr <RouteList> rd = _session->get_routes();
3912         for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
3913                 boost::shared_ptr<Route> rt (*ri);
3914
3915                 if (rt->is_monitor()) {
3916                         continue;
3917                 }
3918
3919                 if (rt->order_key () >= order_hint) {
3920                         rt->set_order_key (rt->order_key () + add_route_dialog->count());
3921                 }
3922         }
3923 }
3924
3925 void
3926 ARDOUR_UI::start_duplicate_routes ()
3927 {
3928         if (!duplicate_routes_dialog) {
3929                 duplicate_routes_dialog = new DuplicateRouteDialog;
3930         }
3931
3932         if (duplicate_routes_dialog->restart (_session)) {
3933                 return;
3934         }
3935
3936         duplicate_routes_dialog->present ();
3937 }
3938
3939 void
3940 ARDOUR_UI::add_route (Gtk::Window* /* ignored */)
3941 {
3942         int count;
3943
3944         if (!_session) {
3945                 return;
3946         }
3947
3948         if (add_route_dialog->is_visible()) {
3949                 /* we're already doing this */
3950                 return;
3951         }
3952
3953         ResponseType r = (ResponseType) add_route_dialog->run ();
3954
3955         add_route_dialog->hide();
3956
3957         switch (r) {
3958                 case RESPONSE_ACCEPT:
3959                         break;
3960                 default:
3961                         return;
3962                         break;
3963         }
3964
3965         if ((count = add_route_dialog->count()) <= 0) {
3966                 return;
3967         }
3968
3969         setup_order_hint(add_route_dialog->insert_at());
3970         string template_path = add_route_dialog->track_template();
3971         DisplaySuspender ds;
3972
3973         if (!template_path.empty()) {
3974                 if (add_route_dialog->name_template_is_default())  {
3975                         _session->new_route_from_template (count, template_path, string());
3976                 } else {
3977                         _session->new_route_from_template (count, template_path, add_route_dialog->name_template());
3978                 }
3979                 return;
3980         }
3981
3982         ChanCount input_chan= add_route_dialog->channels ();
3983         ChanCount output_chan;
3984         string name_template = add_route_dialog->name_template ();
3985         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
3986         RouteGroup* route_group = add_route_dialog->route_group ();
3987         AutoConnectOption oac = Config->get_output_auto_connect();
3988         bool strict_io = add_route_dialog->use_strict_io ();
3989
3990         if (oac & AutoConnectMaster) {
3991                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
3992                 output_chan.set (DataType::MIDI, 0);
3993         } else {
3994                 output_chan = input_chan;
3995         }
3996
3997         /* XXX do something with name template */
3998
3999         switch (add_route_dialog->type_wanted()) {
4000         case AddRouteDialog::AudioTrack:
4001                 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io);
4002                 break;
4003         case AddRouteDialog::MidiTrack:
4004                 session_add_midi_track (route_group, count, name_template, strict_io, instrument);
4005                 break;
4006         case AddRouteDialog::MixedTrack:
4007                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument);
4008                 break;
4009         case AddRouteDialog::AudioBus:
4010                 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io);
4011                 break;
4012         case AddRouteDialog::MidiBus:
4013                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument);
4014                 break;
4015         }
4016 }
4017
4018 void
4019 ARDOUR_UI::add_lua_script ()
4020 {
4021         if (!_session) {
4022                 return;
4023         }
4024
4025         LuaScriptInfoPtr spi;
4026         ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
4027         switch (ss.run ()) {
4028                 case Gtk::RESPONSE_ACCEPT:
4029                         spi = ss.script();
4030                         break;
4031                 default:
4032                         return;
4033         }
4034         ss.hide();
4035
4036         std::string script = "";
4037
4038         try {
4039                 script = Glib::file_get_contents (spi->path);
4040         } catch (Glib::FileError e) {
4041                 string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
4042                 MessageDialog am (msg);
4043                 am.run ();
4044                 return;
4045         }
4046
4047         LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
4048         std::vector<std::string> reg = _session->registered_lua_functions ();
4049
4050         ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
4051         switch (spd.run ()) {
4052                 case Gtk::RESPONSE_ACCEPT:
4053                         break;
4054                 default:
4055                         return;
4056         }
4057
4058         try {
4059                 _session->register_lua_function (spd.name(), script, lsp);
4060         } catch (luabridge::LuaException const& e) {
4061                 string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
4062                 MessageDialog am (msg);
4063                 am.run ();
4064         } catch (SessionException e) {
4065                 string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
4066                 MessageDialog am (msg);
4067                 am.run ();
4068         }
4069 }
4070
4071 void
4072 ARDOUR_UI::remove_lua_script ()
4073 {
4074         if (!_session) {
4075                 return;
4076         }
4077         if (_session->registered_lua_function_count () ==  0) {
4078                 string msg = _("There are no active Lua session scripts present in this session.");
4079                 MessageDialog am (msg);
4080                 am.run ();
4081                 return;
4082         }
4083
4084         std::vector<std::string> reg = _session->registered_lua_functions ();
4085         SessionScriptManager sm ("Remove Lua Session Script", reg);
4086         switch (sm.run ()) {
4087                 case Gtk::RESPONSE_ACCEPT:
4088                         break;
4089                 default:
4090                         return;
4091         }
4092         try {
4093                 _session->unregister_lua_function (sm.name());
4094         } catch (luabridge::LuaException const& e) {
4095                 string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
4096                 MessageDialog am (msg);
4097                 am.run ();
4098         }
4099 }
4100
4101 void
4102 ARDOUR_UI::stop_video_server (bool ask_confirm)
4103 {
4104         if (!video_server_process && ask_confirm) {
4105                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4106         }
4107         if (video_server_process) {
4108                 if(ask_confirm) {
4109                         ArdourDialog confirm (_("Stop Video-Server"), true);
4110                         Label m (_("Do you really want to stop the Video Server?"));
4111                         confirm.get_vbox()->pack_start (m, true, true);
4112                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4113                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4114                         confirm.show_all ();
4115                         if (confirm.run() == RESPONSE_CANCEL) {
4116                                 return;
4117                         }
4118                 }
4119                 delete video_server_process;
4120                 video_server_process =0;
4121         }
4122 }
4123
4124 void
4125 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4126 {
4127   ARDOUR_UI::start_video_server( float_window, true);
4128 }
4129
4130 bool
4131 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4132 {
4133         if (!_session) {
4134                 return false;
4135         }
4136         if (popup_msg) {
4137                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4138                         if (video_server_process) {
4139                                 popup_error(_("The Video Server is already started."));
4140                         } else {
4141                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4142                         }
4143                 }
4144         }
4145
4146         int firsttime = 0;
4147         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4148                 if (firsttime++) {
4149                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4150                 }
4151                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4152                 if (float_window) {
4153                         video_server_dialog->set_transient_for (*float_window);
4154                 }
4155
4156                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4157                         video_server_dialog->hide();
4158                 } else {
4159                         ResponseType r = (ResponseType) video_server_dialog->run ();
4160                         video_server_dialog->hide();
4161                         if (r != RESPONSE_ACCEPT) { return false; }
4162                         if (video_server_dialog->show_again()) {
4163                                 Config->set_show_video_server_dialog(false);
4164                         }
4165                 }
4166
4167                 std::string icsd_exec = video_server_dialog->get_exec_path();
4168                 std::string icsd_docroot = video_server_dialog->get_docroot();
4169                 if (icsd_docroot.empty()) {
4170 #ifndef PLATFORM_WINDOWS
4171                         icsd_docroot = X_("/");
4172 #else
4173                         icsd_docroot = X_("C:\\");
4174 #endif
4175                 }
4176
4177                 GStatBuf sb;
4178                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4179                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4180                         continue;
4181                 }
4182 #ifndef PLATFORM_WINDOWS
4183                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4184                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4185                         warning << _("Given Video Server is not an executable file.") << endmsg;
4186                         continue;
4187                 }
4188 #else
4189                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4190                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4191                         warning << _("Given Video Server is not an executable file.") << endmsg;
4192                         continue;
4193                 }
4194 #endif
4195
4196                 char **argp;
4197                 argp=(char**) calloc(9,sizeof(char*));
4198                 argp[0] = strdup(icsd_exec.c_str());
4199                 argp[1] = strdup("-P");
4200                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4201                 argp[3] = strdup("-p");
4202                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4203                 argp[5] = strdup("-C");
4204                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4205                 argp[7] = strdup(icsd_docroot.c_str());
4206                 argp[8] = 0;
4207                 stop_video_server();
4208
4209                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4210                         Config->set_video_advanced_setup(false);
4211                 } else {
4212                         std::ostringstream osstream;
4213                         osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4214                         Config->set_video_server_url(osstream.str());
4215                         Config->set_video_server_docroot(icsd_docroot);
4216                         Config->set_video_advanced_setup(true);
4217                 }
4218
4219                 if (video_server_process) {
4220                         delete video_server_process;
4221                 }
4222
4223                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4224                 if (video_server_process->start()) {
4225                         warning << _("Cannot launch the video-server") << endmsg;
4226                         continue;
4227                 }
4228                 int timeout = 120; // 6 sec
4229                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4230                         Glib::usleep (50000);
4231                         gui_idle_handler();
4232                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4233                 }
4234                 if (timeout <= 0) {
4235                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4236                 } else {
4237                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4238                                 delete video_server_process;
4239                                 video_server_process = 0;
4240                         }
4241                 }
4242         }
4243         return true;
4244 }
4245
4246 void
4247 ARDOUR_UI::add_video (Gtk::Window* float_window)
4248 {
4249         if (!_session) {
4250                 return;
4251         }
4252
4253         if (!start_video_server(float_window, false)) {
4254                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4255                 return;
4256         }
4257
4258         if (float_window) {
4259                 add_video_dialog->set_transient_for (*float_window);
4260         }
4261
4262         if (add_video_dialog->is_visible()) {
4263                 /* we're already doing this */
4264                 return;
4265         }
4266
4267         ResponseType r = (ResponseType) add_video_dialog->run ();
4268         add_video_dialog->hide();
4269         if (r != RESPONSE_ACCEPT) { return; }
4270
4271         bool local_file, orig_local_file;
4272         std::string path = add_video_dialog->file_name(local_file);
4273
4274         std::string orig_path = path;
4275         orig_local_file = local_file;
4276
4277         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4278
4279         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4280                 warning << string_compose(_("could not open %1"), path) << endmsg;
4281                 return;
4282         }
4283         if (!local_file && path.length() == 0) {
4284                 warning << _("no video-file selected") << endmsg;
4285                 return;
4286         }
4287
4288         std::string audio_from_video;
4289         bool detect_ltc = false;
4290
4291         switch (add_video_dialog->import_option()) {
4292                 case VTL_IMPORT_TRANSCODE:
4293                         {
4294                                 TranscodeVideoDialog *transcode_video_dialog;
4295                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4296                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4297                                 transcode_video_dialog->hide();
4298                                 if (r != RESPONSE_ACCEPT) {
4299                                         delete transcode_video_dialog;
4300                                         return;
4301                                 }
4302
4303                                 audio_from_video = transcode_video_dialog->get_audiofile();
4304
4305                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4306                                         detect_ltc = true;
4307                                 }
4308                                 else if (!audio_from_video.empty()) {
4309                                         editor->embed_audio_from_video(
4310                                                         audio_from_video,
4311                                                         video_timeline->get_offset(),
4312                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4313                                                         );
4314                                 }
4315                                 switch (transcode_video_dialog->import_option()) {
4316                                         case VTL_IMPORT_TRANSCODED:
4317                                                 path = transcode_video_dialog->get_filename();
4318                                                 local_file = true;
4319                                                 break;
4320                                         case VTL_IMPORT_REFERENCE:
4321                                                 break;
4322                                         default:
4323                                                 delete transcode_video_dialog;
4324                                                 return;
4325                                 }
4326                                 delete transcode_video_dialog;
4327                         }
4328                         break;
4329                 default:
4330                 case VTL_IMPORT_NONE:
4331                         break;
4332         }
4333
4334         /* strip _session->session_directory().video_path() from video file if possible */
4335         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4336                  path=path.substr(_session->session_directory().video_path().size());
4337                  if (path.at(0) == G_DIR_SEPARATOR) {
4338                          path=path.substr(1);
4339                  }
4340         }
4341
4342         video_timeline->set_update_session_fps(auto_set_session_fps);
4343
4344         if (video_timeline->video_file_info(path, local_file)) {
4345                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4346                 node->add_property (X_("Filename"), path);
4347                 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4348                 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4349                 if (orig_local_file) {
4350                         node->add_property (X_("OriginalVideoFile"), orig_path);
4351                 } else {
4352                         node->remove_property (X_("OriginalVideoFile"));
4353                 }
4354                 _session->add_extra_xml (*node);
4355                 _session->set_dirty ();
4356
4357                 if (!audio_from_video.empty() && detect_ltc) {
4358                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4359
4360                         try {
4361                                 /* TODO ask user about TV standard (LTC alignment if any) */
4362                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4363                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4364
4365                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4366
4367                                 /* TODO seek near end of file, and read LTC until end.
4368                                  * if it fails to find any LTC frames, scan complete file
4369                                  *
4370                                  * calculate drift of LTC compared to video-duration,
4371                                  * ask user for reference (timecode from start/mid/end)
4372                                  */
4373                         } catch (...) {
4374                                 // LTCFileReader will have written error messages
4375                         }
4376
4377                         ::g_unlink(audio_from_video.c_str());
4378
4379                         if (ltc_seq.size() == 0) {
4380                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4381                         } else {
4382                                 /* the very first TC in the file is somteimes not aligned properly */
4383                                 int i = ltc_seq.size() -1;
4384                                 ARDOUR::frameoffset_t video_start_offset =
4385                                         _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4386                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4387                                 video_timeline->set_offset(video_start_offset);
4388                         }
4389                 }
4390
4391                 _session->maybe_update_session_range(
4392                         std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4393                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4394
4395
4396                 if (add_video_dialog->launch_xjadeo() && local_file) {
4397                         editor->set_xjadeo_sensitive(true);
4398                         editor->toggle_xjadeo_proc(1);
4399                 } else {
4400                         editor->toggle_xjadeo_proc(0);
4401                 }
4402                 editor->toggle_ruler_video(true);
4403         }
4404 }
4405
4406 void
4407 ARDOUR_UI::remove_video ()
4408 {
4409         video_timeline->close_session();
4410         editor->toggle_ruler_video(false);
4411
4412         /* reset state */
4413         video_timeline->set_offset_locked(false);
4414         video_timeline->set_offset(0);
4415
4416         /* delete session state */
4417         XMLNode* node = new XMLNode(X_("Videotimeline"));
4418         _session->add_extra_xml(*node);
4419         node = new XMLNode(X_("Videomonitor"));
4420         _session->add_extra_xml(*node);
4421         node = new XMLNode(X_("Videoexport"));
4422         _session->add_extra_xml(*node);
4423         stop_video_server();
4424 }
4425
4426 void
4427 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4428 {
4429         if (localcacheonly) {
4430                 video_timeline->vmon_update();
4431         } else {
4432                 video_timeline->flush_cache();
4433         }
4434         editor->queue_visual_videotimeline_update();
4435 }
4436
4437 void
4438 ARDOUR_UI::export_video (bool range)
4439 {
4440         if (ARDOUR::Config->get_show_video_export_info()) {
4441                 ExportVideoInfobox infobox (_session);
4442                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4443                 if (infobox.show_again()) {
4444                         ARDOUR::Config->set_show_video_export_info(false);
4445                 }
4446                 switch (rv) {
4447                         case GTK_RESPONSE_YES:
4448                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4449                                 break;
4450                         default:
4451                                 break;
4452                 }
4453         }
4454         export_video_dialog->set_session (_session);
4455         export_video_dialog->apply_state(editor->get_selection().time, range);
4456         export_video_dialog->run ();
4457         export_video_dialog->hide ();
4458 }
4459
4460 XMLNode*
4461 ARDOUR_UI::mixer_settings () const
4462 {
4463         XMLNode* node = 0;
4464
4465         if (_session) {
4466                 node = _session->instant_xml(X_("Mixer"));
4467         } else {
4468                 node = Config->instant_xml(X_("Mixer"));
4469         }
4470
4471         if (!node) {
4472                 node = new XMLNode (X_("Mixer"));
4473         }
4474
4475         return node;
4476 }
4477
4478 XMLNode*
4479 ARDOUR_UI::main_window_settings () const
4480 {
4481         XMLNode* node = 0;
4482
4483         if (_session) {
4484                 node = _session->instant_xml(X_("Main"));
4485         } else {
4486                 node = Config->instant_xml(X_("Main"));
4487         }
4488
4489         if (!node) {
4490                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4491                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4492                 }
4493         }
4494
4495         if (!node) {
4496                 node = new XMLNode (X_("Main"));
4497         }
4498
4499         return node;
4500 }
4501
4502 XMLNode*
4503 ARDOUR_UI::editor_settings () const
4504 {
4505         XMLNode* node = 0;
4506
4507         if (_session) {
4508                 node = _session->instant_xml(X_("Editor"));
4509         } else {
4510                 node = Config->instant_xml(X_("Editor"));
4511         }
4512
4513         if (!node) {
4514                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4515                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4516                 }
4517         }
4518
4519         if (!node) {
4520                 node = new XMLNode (X_("Editor"));
4521         }
4522
4523         return node;
4524 }
4525
4526 XMLNode*
4527 ARDOUR_UI::keyboard_settings () const
4528 {
4529         XMLNode* node = 0;
4530
4531         node = Config->extra_xml(X_("Keyboard"));
4532
4533         if (!node) {
4534                 node = new XMLNode (X_("Keyboard"));
4535         }
4536
4537         return node;
4538 }
4539
4540 void
4541 ARDOUR_UI::create_xrun_marker (framepos_t where)
4542 {
4543         if (_session) {
4544                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
4545                 _session->locations()->add (location);
4546         }
4547 }
4548
4549 void
4550 ARDOUR_UI::halt_on_xrun_message ()
4551 {
4552         cerr << "HALT on xrun\n";
4553         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4554         msg.run ();
4555 }
4556
4557 void
4558 ARDOUR_UI::xrun_handler (framepos_t where)
4559 {
4560         if (!_session) {
4561                 return;
4562         }
4563
4564         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4565
4566         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4567                 create_xrun_marker(where);
4568         }
4569
4570         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4571                 halt_on_xrun_message ();
4572         }
4573 }
4574
4575 void
4576 ARDOUR_UI::disk_overrun_handler ()
4577 {
4578         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4579
4580         if (!have_disk_speed_dialog_displayed) {
4581                 have_disk_speed_dialog_displayed = true;
4582                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4583 The disk system on your computer\n\
4584 was not able to keep up with %1.\n\
4585 \n\
4586 Specifically, it failed to write data to disk\n\
4587 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4588                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4589                 msg->show ();
4590         }
4591 }
4592
4593
4594 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4595 static MessageDialog *scan_dlg = NULL;
4596 static ProgressBar   *scan_pbar = NULL;
4597 static HBox          *scan_tbox = NULL;
4598 static Gtk::Button   *scan_timeout_button;
4599
4600 void
4601 ARDOUR_UI::cancel_plugin_scan ()
4602 {
4603         PluginManager::instance().cancel_plugin_scan();
4604 }
4605
4606 void
4607 ARDOUR_UI::cancel_plugin_timeout ()
4608 {
4609         PluginManager::instance().cancel_plugin_timeout();
4610         scan_timeout_button->set_sensitive (false);
4611 }
4612
4613 void
4614 ARDOUR_UI::plugin_scan_timeout (int timeout)
4615 {
4616         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4617                 return;
4618         }
4619         if (timeout > 0) {
4620                 scan_pbar->set_sensitive (false);
4621                 scan_timeout_button->set_sensitive (true);
4622                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4623                 scan_tbox->show();
4624         } else {
4625                 scan_pbar->set_sensitive (false);
4626                 scan_timeout_button->set_sensitive (false);
4627         }
4628         gui_idle_handler();
4629 }
4630
4631 void
4632 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4633 {
4634         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4635                 return;
4636         }
4637
4638         const bool cancelled = PluginManager::instance().cancelled();
4639         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4640                 if (cancelled && scan_dlg->is_mapped()) {
4641                         scan_dlg->hide();
4642                         gui_idle_handler();
4643                         return;
4644                 }
4645                 if (cancelled || !can_cancel) {
4646                         return;
4647                 }
4648         }
4649
4650         static Gtk::Button *cancel_button;
4651         if (!scan_dlg) {
4652                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4653                 VBox* vbox = scan_dlg->get_vbox();
4654                 vbox->set_size_request(400,-1);
4655                 scan_dlg->set_title (_("Scanning for plugins"));
4656
4657                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4658                 cancel_button->set_name ("EditorGTKButton");
4659                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4660                 cancel_button->show();
4661
4662                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4663
4664                 scan_tbox = manage( new HBox() );
4665
4666                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4667                 scan_timeout_button->set_name ("EditorGTKButton");
4668                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4669                 scan_timeout_button->show();
4670
4671                 scan_pbar = manage(new ProgressBar());
4672                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4673                 scan_pbar->set_text(_("Scan Timeout"));
4674                 scan_pbar->show();
4675
4676                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4677                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4678
4679                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4680         }
4681
4682         assert(scan_dlg && scan_tbox && cancel_button);
4683
4684         if (type == X_("closeme")) {
4685                 scan_tbox->hide();
4686                 scan_dlg->hide();
4687         } else {
4688                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4689                 scan_dlg->show();
4690         }
4691         if (!can_cancel || !cancelled) {
4692                 scan_timeout_button->set_sensitive(false);
4693         }
4694         cancel_button->set_sensitive(can_cancel && !cancelled);
4695
4696         gui_idle_handler();
4697 }
4698
4699 void
4700 ARDOUR_UI::gui_idle_handler ()
4701 {
4702         int timeout = 30;
4703         /* due to idle calls, gtk_events_pending() may always return true */
4704         while (gtk_events_pending() && --timeout) {
4705                 gtk_main_iteration ();
4706         }
4707 }
4708
4709 void
4710 ARDOUR_UI::disk_underrun_handler ()
4711 {
4712         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4713
4714         if (!have_disk_speed_dialog_displayed) {
4715                 have_disk_speed_dialog_displayed = true;
4716                 MessageDialog* msg = new MessageDialog (
4717                         _main_window, string_compose (_("The disk system on your computer\n\
4718 was not able to keep up with %1.\n\
4719 \n\
4720 Specifically, it failed to read data from disk\n\
4721 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4722                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4723                 msg->show ();
4724         }
4725 }
4726
4727 void
4728 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4729 {
4730         have_disk_speed_dialog_displayed = false;
4731         delete msg;
4732 }
4733
4734 void
4735 ARDOUR_UI::session_dialog (std::string msg)
4736 {
4737         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4738
4739         MessageDialog* d;
4740
4741         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4742         d->show_all ();
4743         d->run ();
4744         delete d;
4745 }
4746
4747 int
4748 ARDOUR_UI::pending_state_dialog ()
4749 {
4750         HBox* hbox = manage (new HBox());
4751         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4752         ArdourDialog dialog (_("Crash Recovery"), true);
4753         Label  message (string_compose (_("\
4754 This session appears to have been in the\n\
4755 middle of recording when %1 or\n\
4756 the computer was shutdown.\n\
4757 \n\
4758 %1 can recover any captured audio for\n\
4759 you, or it can ignore it. Please decide\n\
4760 what you would like to do.\n"), PROGRAM_NAME));
4761         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4762         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4763         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4764         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4765         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
4766         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
4767         dialog.set_default_response (RESPONSE_ACCEPT);
4768         dialog.set_position (WIN_POS_CENTER);
4769         message.show();
4770         image->show();
4771         hbox->show();
4772
4773         switch (dialog.run ()) {
4774         case RESPONSE_ACCEPT:
4775                 return 1;
4776         default:
4777                 return 0;
4778         }
4779 }
4780
4781 int
4782 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4783 {
4784         HBox* hbox = new HBox();
4785         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4786         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4787         Label  message (string_compose (_("\
4788 This session was created with a sample rate of %1 Hz, but\n\
4789 %2 is currently running at %3 Hz.  If you load this session,\n\
4790 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4791
4792         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4793         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4794         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4795         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4796         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4797         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4798         dialog.set_default_response (RESPONSE_ACCEPT);
4799         dialog.set_position (WIN_POS_CENTER);
4800         message.show();
4801         image->show();
4802         hbox->show();
4803
4804         switch (dialog.run()) {
4805         case RESPONSE_ACCEPT:
4806                 return 0;
4807         default:
4808                 break;
4809         }
4810
4811         return 1;
4812 }
4813
4814 void
4815 ARDOUR_UI::sr_mismatch_message (framecnt_t desired, framecnt_t actual)
4816 {
4817         MessageDialog msg (string_compose (_("\
4818 This session was created with a sample rate of %1 Hz, but\n\
4819 %2 is currently running at %3 Hz.\n\
4820 Audio will be recorded and played at the wrong sample rate.\n\
4821 Re-Configure the Audio Engine in\n\
4822 Menu > Window > Audio/Midi Setup"),
4823                                 desired, PROGRAM_NAME, actual),
4824                         true,
4825                         Gtk::MESSAGE_WARNING);
4826         msg.run ();
4827 }
4828
4829 void
4830 ARDOUR_UI::use_config ()
4831 {
4832         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
4833         if (node) {
4834                 set_transport_controllable_state (*node);
4835         }
4836 }
4837
4838 void
4839 ARDOUR_UI::update_transport_clocks (framepos_t pos)
4840 {
4841         if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
4842                 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4843         } else {
4844                 primary_clock->set (pos);
4845         }
4846
4847         if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
4848                 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4849         } else {
4850                 secondary_clock->set (pos);
4851         }
4852
4853         if (big_clock_window) {
4854                 big_clock->set (pos);
4855         }
4856         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
4857 }
4858
4859 void
4860 ARDOUR_UI::step_edit_status_change (bool yn)
4861 {
4862         // XXX should really store pre-step edit status of things
4863         // we make insensitive
4864
4865         if (yn) {
4866                 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
4867                 rec_button.set_sensitive (false);
4868         } else {
4869                 rec_button.unset_active_state ();;
4870                 rec_button.set_sensitive (true);
4871         }
4872 }
4873
4874 void
4875 ARDOUR_UI::record_state_changed ()
4876 {
4877         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
4878
4879         if (!_session || !big_clock_window) {
4880                 /* why bother - the clock isn't visible */
4881                 return;
4882         }
4883
4884         if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
4885                 big_clock->set_active (true);
4886         } else {
4887                 big_clock->set_active (false);
4888         }
4889 }
4890
4891 bool
4892 ARDOUR_UI::first_idle ()
4893 {
4894         if (_session) {
4895                 _session->allow_auto_play (true);
4896         }
4897
4898         if (editor) {
4899                 editor->first_idle();
4900         }
4901
4902         Keyboard::set_can_save_keybindings (true);
4903         return false;
4904 }
4905
4906 void
4907 ARDOUR_UI::store_clock_modes ()
4908 {
4909         XMLNode* node = new XMLNode(X_("ClockModes"));
4910
4911         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
4912                 XMLNode* child = new XMLNode (X_("Clock"));
4913
4914                 child->add_property (X_("name"), (*x)->name());
4915                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
4916                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
4917
4918                 node->add_child_nocopy (*child);
4919         }
4920
4921         _session->add_extra_xml (*node);
4922         _session->set_dirty ();
4923 }
4924
4925 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
4926         : Controllable (name), ui (u), type(tp)
4927 {
4928
4929 }
4930
4931 void
4932 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
4933 {
4934         if (val < 0.5) {
4935                 /* do nothing: these are radio-style actions */
4936                 return;
4937         }
4938
4939         const char *action = 0;
4940
4941         switch (type) {
4942         case Roll:
4943                 action = X_("Roll");
4944                 break;
4945         case Stop:
4946                 action = X_("Stop");
4947                 break;
4948         case GotoStart:
4949                 action = X_("GotoStart");
4950                 break;
4951         case GotoEnd:
4952                 action = X_("GotoEnd");
4953                 break;
4954         case AutoLoop:
4955                 action = X_("Loop");
4956                 break;
4957         case PlaySelection:
4958                 action = X_("PlaySelection");
4959                 break;
4960         case RecordEnable:
4961                 action = X_("Record");
4962                 break;
4963         default:
4964                 break;
4965         }
4966
4967         if (action == 0) {
4968                 return;
4969         }
4970
4971         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
4972
4973         if (act) {
4974                 act->activate ();
4975         }
4976 }
4977
4978 double
4979 ARDOUR_UI::TransportControllable::get_value (void) const
4980 {
4981         float val = 0.0;
4982
4983         switch (type) {
4984         case Roll:
4985                 break;
4986         case Stop:
4987                 break;
4988         case GotoStart:
4989                 break;
4990         case GotoEnd:
4991                 break;
4992         case AutoLoop:
4993                 break;
4994         case PlaySelection:
4995                 break;
4996         case RecordEnable:
4997                 break;
4998         default:
4999                 break;
5000         }
5001
5002         return val;
5003 }
5004
5005 void
5006 ARDOUR_UI::setup_profile ()
5007 {
5008         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5009                 Profile->set_small_screen ();
5010         }
5011
5012         if (g_getenv ("TRX")) {
5013                 Profile->set_trx ();
5014         }
5015
5016         if (g_getenv ("MIXBUS")) {
5017                 Profile->set_mixbus ();
5018         }
5019 }
5020
5021 int
5022 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5023 {
5024         MissingFileDialog dialog (s, str, type);
5025
5026         dialog.show ();
5027         dialog.present ();
5028
5029         int result = dialog.run ();
5030         dialog.hide ();
5031
5032         switch (result) {
5033         case RESPONSE_OK:
5034                 break;
5035         default:
5036                 return 1; // quit entire session load
5037         }
5038
5039         result = dialog.get_action ();
5040
5041         return result;
5042 }
5043
5044 int
5045 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5046 {
5047         AmbiguousFileDialog dialog (file, hits);
5048
5049         dialog.show ();
5050         dialog.present ();
5051
5052         dialog.run ();
5053
5054         return dialog.get_which ();
5055 }
5056
5057 /** Allocate our thread-local buffers */
5058 void
5059 ARDOUR_UI::get_process_buffers ()
5060 {
5061         _process_thread->get_buffers ();
5062 }
5063
5064 /** Drop our thread-local buffers */
5065 void
5066 ARDOUR_UI::drop_process_buffers ()
5067 {
5068         _process_thread->drop_buffers ();
5069 }
5070
5071 void
5072 ARDOUR_UI::feedback_detected ()
5073 {
5074         _feedback_exists = true;
5075 }
5076
5077 void
5078 ARDOUR_UI::successful_graph_sort ()
5079 {
5080         _feedback_exists = false;
5081 }
5082
5083 void
5084 ARDOUR_UI::midi_panic ()
5085 {
5086         if (_session) {
5087                 _session->midi_panic();
5088         }
5089 }
5090
5091 void
5092 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5093 {
5094         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5095         const char* end_big = "</span>";
5096         const char* start_mono = "<tt>";
5097         const char* end_mono = "</tt>";
5098
5099         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5100                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5101                                              "From now on, use the -2000 version with older versions of %3"),
5102                                            xml_path, backup_path, PROGRAM_NAME,
5103                                            start_big, end_big,
5104                                            start_mono, end_mono), true);
5105
5106         msg.run ();
5107 }
5108
5109
5110 void
5111 ARDOUR_UI::reset_peak_display ()
5112 {
5113         if (!_session || !_session->master_out() || !editor_meter) return;
5114         editor_meter->clear_meters();
5115         editor_meter_max_peak = -INFINITY;
5116         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5117 }
5118
5119 void
5120 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5121 {
5122         if (!_session || !_session->master_out()) return;
5123         if (group == _session->master_out()->route_group()) {
5124                 reset_peak_display ();
5125         }
5126 }
5127
5128 void
5129 ARDOUR_UI::reset_route_peak_display (Route* route)
5130 {
5131         if (!_session || !_session->master_out()) return;
5132         if (_session->master_out().get() == route) {
5133                 reset_peak_display ();
5134         }
5135 }
5136
5137 int
5138 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5139 {
5140         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5141         audio_midi_setup->set_position (WIN_POS_CENTER);
5142
5143         if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5144                 audio_midi_setup->try_autostart ();
5145                 if (ARDOUR::AudioEngine::instance()->running()) {
5146                         return 0;
5147                 }
5148         }
5149
5150         while (true) {
5151                 int response = audio_midi_setup->run();
5152                 switch (response) {
5153                 case Gtk::RESPONSE_OK:
5154                         if (!AudioEngine::instance()->running()) {
5155                                 continue;
5156                         } else {
5157                                 return 0;
5158                         }
5159                         return 0;
5160                 default:
5161                         return -1;
5162                 }
5163         }
5164 }
5165
5166
5167 gint
5168 ARDOUR_UI::transport_numpad_timeout ()
5169 {
5170         _numpad_locate_happening = false;
5171         if (_numpad_timeout_connection.connected() )
5172                 _numpad_timeout_connection.disconnect();
5173         return 1;
5174 }
5175
5176 void
5177 ARDOUR_UI::transport_numpad_decimal ()
5178 {
5179         _numpad_timeout_connection.disconnect();
5180
5181         if (_numpad_locate_happening) {
5182                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5183                 _numpad_locate_happening = false;
5184         } else {
5185                 _pending_locate_num = 0;
5186                 _numpad_locate_happening = true;
5187                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5188         }
5189 }
5190
5191 void
5192 ARDOUR_UI::transport_numpad_event (int num)
5193 {
5194         if ( _numpad_locate_happening ) {
5195                 _pending_locate_num = _pending_locate_num*10 + num;
5196         } else {
5197                 switch (num) {
5198                         case 0:  toggle_roll(false, false);             break;
5199                         case 1:  transport_rewind(1);                           break;
5200                         case 2:  transport_forward(1);                          break;
5201                         case 3:  transport_record(true);                        break;
5202                         case 4:  toggle_session_auto_loop();            break;
5203                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5204                         case 6:  toggle_punch();                                        break;
5205                         case 7:  toggle_click();                                break;
5206                         case 8:  toggle_auto_return();                  break;
5207                         case 9:  toggle_follow_edits();         break;
5208                 }
5209         }
5210 }
5211
5212 void
5213 ARDOUR_UI::set_flat_buttons ()
5214 {
5215         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5216 }
5217
5218 void
5219 ARDOUR_UI::audioengine_became_silent ()
5220 {
5221         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5222                            true,
5223                            Gtk::MESSAGE_WARNING,
5224                            Gtk::BUTTONS_NONE,
5225                            true);
5226
5227         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5228
5229         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5230         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5231         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5232         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5233         Gtk::HBox pay_button_box;
5234         Gtk::HBox subscribe_button_box;
5235
5236         pay_button_box.pack_start (pay_button, true, false);
5237         subscribe_button_box.pack_start (subscribe_button, true, false);
5238
5239         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 */
5240
5241         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5242         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5243
5244         msg.get_vbox()->pack_start (pay_label);
5245         msg.get_vbox()->pack_start (pay_button_box);
5246         msg.get_vbox()->pack_start (subscribe_label);
5247         msg.get_vbox()->pack_start (subscribe_button_box);
5248
5249         msg.get_vbox()->show_all ();
5250
5251         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5252         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5253         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5254
5255         int r = msg.run ();
5256
5257         switch (r) {
5258         case Gtk::RESPONSE_YES:
5259                 AudioEngine::instance()->reset_silence_countdown ();
5260                 break;
5261
5262         case Gtk::RESPONSE_NO:
5263                 /* save and quit */
5264                 save_state_canfail ("");
5265                 exit (0);
5266                 break;
5267
5268         case Gtk::RESPONSE_CANCEL:
5269         default:
5270                 /* don't reset, save session and exit */
5271                 break;
5272         }
5273 }
5274
5275 void
5276 ARDOUR_UI::hide_application ()
5277 {
5278     Application::instance ()-> hide ();
5279 }
5280
5281 void
5282 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5283 {
5284         /* icons, titles, WM stuff */
5285
5286         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5287
5288         if (window_icons.empty()) {
5289                 Glib::RefPtr<Gdk::Pixbuf> icon;
5290                 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
5291                         window_icons.push_back (icon);
5292                 }
5293                 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
5294                         window_icons.push_back (icon);
5295                 }
5296                 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
5297                         window_icons.push_back (icon);
5298                 }
5299                 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
5300                         window_icons.push_back (icon);
5301                 }
5302         }
5303
5304         if (!window_icons.empty()) {
5305                 window.set_default_icon_list (window_icons);
5306         }
5307
5308         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5309
5310         if (!name.empty()) {
5311                 title += name;
5312         }
5313
5314         window.set_title (title.get_string());
5315         window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
5316
5317         window.set_flags (CAN_FOCUS);
5318         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5319
5320         /* This is a hack to ensure that GTK-accelerators continue to
5321          * work. Once we switch over to entirely native bindings, this will be
5322          * unnecessary and should be removed
5323          */
5324         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5325
5326         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5327         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5328         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5329         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5330 }
5331
5332 bool
5333 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5334 {
5335         Gtkmm2ext::Bindings* bindings = 0;
5336         Gtk::Window* window = 0;
5337
5338         /* until we get ardour bindings working, we are not handling key
5339          * releases yet.
5340          */
5341
5342         if (ev->type != GDK_KEY_PRESS) {
5343                 return false;
5344         }
5345
5346         if (event_window == &_main_window) {
5347
5348                 window = event_window;
5349
5350                 /* find current tab contents */
5351
5352                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5353
5354                 /* see if it uses the ardour binding system */
5355
5356                 if (w) {
5357                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5358                 }
5359
5360                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5361
5362         } else {
5363
5364                 window = event_window;
5365
5366                 /* see if window uses ardour binding system */
5367
5368                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5369         }
5370
5371         /* An empty binding set is treated as if it doesn't exist */
5372
5373         if (bindings && bindings->empty()) {
5374                 bindings = 0;
5375         }
5376
5377         return key_press_focus_accelerator_handler (*window, ev, bindings);
5378 }
5379
5380 static Gtkmm2ext::Bindings*
5381 get_bindings_from_widget_heirarchy (GtkWidget* w)
5382 {
5383         void* p;
5384
5385         while (w) {
5386                 if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) {
5387                         break;
5388                 }
5389                 w = gtk_widget_get_parent (w);
5390         }
5391
5392         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5393 }
5394
5395 bool
5396 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5397 {
5398         GtkWindow* win = window.gobj();
5399         GtkWidget* focus = gtk_window_get_focus (win);
5400         bool special_handling_of_unmodified_accelerators = false;
5401         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5402
5403         if (focus) {
5404
5405                 /* some widget has keyboard focus */
5406
5407                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5408
5409                         /* A particular kind of focusable widget currently has keyboard
5410                          * focus. All unmodified key events should go to that widget
5411                          * first and not be used as an accelerator by default
5412                          */
5413
5414                         special_handling_of_unmodified_accelerators = true;
5415
5416                 } else {
5417
5418                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus);
5419                         if (focus_bindings) {
5420                                 bindings = focus_bindings;
5421                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5422                         }
5423                 }
5424         }
5425
5426         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 [title = %9] focus = %7 (%8) Key event: code = %2  state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n",
5427                                                           win,
5428                                                           ev->keyval,
5429                                                           show_gdk_event_state (ev->state),
5430                                                           special_handling_of_unmodified_accelerators,
5431                                                           Keyboard::some_magic_widget_has_focus(),
5432                                                           focus,
5433                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5434                                                           ((ev->state & mask) ? "yes" : "no"),
5435                                                           window.get_title()));
5436
5437         /* This exists to allow us to override the way GTK handles
5438            key events. The normal sequence is:
5439
5440            a) event is delivered to a GtkWindow
5441            b) accelerators/mnemonics are activated
5442            c) if (b) didn't handle the event, propagate to
5443                the focus widget and/or focus chain
5444
5445            The problem with this is that if the accelerators include
5446            keys without modifiers, such as the space bar or the
5447            letter "e", then pressing the key while typing into
5448            a text entry widget results in the accelerator being
5449            activated, instead of the desired letter appearing
5450            in the text entry.
5451
5452            There is no good way of fixing this, but this
5453            represents a compromise. The idea is that
5454            key events involving modifiers (not Shift)
5455            get routed into the activation pathway first, then
5456            get propagated to the focus widget if necessary.
5457
5458            If the key event doesn't involve modifiers,
5459            we deliver to the focus widget first, thus allowing
5460            it to get "normal text" without interference
5461            from acceleration.
5462
5463            Of course, this can also be problematic: if there
5464            is a widget with focus, then it will swallow
5465            all "normal text" accelerators.
5466         */
5467
5468
5469         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5470
5471                 /* no special handling or there are modifiers in effect: accelerate first */
5472
5473                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5474                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5475                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5476
5477                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5478                 KeyboardKey k (ev->state, ev->keyval);
5479
5480                 if (bindings) {
5481
5482                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5483
5484                         if (bindings->activate (k, Bindings::Press)) {
5485                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5486                                 return true;
5487                         }
5488                 }
5489
5490                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5491
5492                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5493                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5494                         return true;
5495                 }
5496
5497                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5498
5499                 if (gtk_window_propagate_key_event (win, ev)) {
5500                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5501                         return true;
5502                 }
5503
5504         } else {
5505
5506                 /* no modifiers, propagate first */
5507
5508                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5509
5510                 if (gtk_window_propagate_key_event (win, ev)) {
5511                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5512                         return true;
5513                 }
5514
5515                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5516                 KeyboardKey k (ev->state, ev->keyval);
5517
5518                 if (bindings) {
5519
5520                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5521
5522
5523                         if (bindings->activate (k, Bindings::Press)) {
5524                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5525                                 return true;
5526                         }
5527
5528                 }
5529
5530                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5531
5532                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5533                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5534                         return true;
5535                 }
5536         }
5537
5538         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5539         return true;
5540 }
5541
5542 void
5543 ARDOUR_UI::load_bindings ()
5544 {
5545         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5546                 error << _("Global keybindings are missing") << endmsg;
5547         }
5548 }
5549
5550 void
5551 ARDOUR_UI::cancel_solo ()
5552 {
5553         if (_session) {
5554                 if (_session->soloing()) {
5555                         _session->set_solo (_session->get_routes(), false);
5556                 } else if (_session->listening()) {
5557                         _session->set_listen (_session->get_routes(), false);
5558                 }
5559
5560                 _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window
5561         }
5562 }