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