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