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