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