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