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