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