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