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