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