Fix playhead smoothing when auditioning.
[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         case FLAC:
1665                 s << _("FLAC");
1666                 break;
1667         }
1668
1669         s << " ";
1670
1671         switch (_session->config.get_native_file_data_format ()) {
1672         case FormatFloat:
1673                 s << _("32-float");
1674                 break;
1675         case FormatInt24:
1676                 s << _("24-int");
1677                 break;
1678         case FormatInt16:
1679                 s << _("16-int");
1680                 break;
1681         }
1682
1683         s << X_("</span>");
1684
1685         format_label.set_markup (s.str ());
1686 }
1687
1688 void
1689 ARDOUR_UI::update_cpu_load ()
1690 {
1691         const unsigned int x = _session ? _session->get_xrun_count () : 0;
1692         double const c = AudioEngine::instance()->get_dsp_load ();
1693
1694         const char* const bg = c > 90 ? " background=\"red\"" : "";
1695
1696         char buf[64];
1697         if (x > 9999) {
1698                 snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span> (>10k)", bg, c);
1699         } else if (x > 0) {
1700                 snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span> (%d)", bg, c, x);
1701         } else {
1702                 snprintf (buf, sizeof (buf), "DSP: <span%s>%.0f%%</span>", bg, c);
1703         }
1704
1705         dsp_load_label.set_markup (buf);
1706
1707         if (x > 9999) {
1708                 snprintf (buf, sizeof (buf), _("DSP: %.1f%% X: >10k\n%s"), c, _("Shift+Click to clear xruns."));
1709         } else if (x > 0) {
1710                 snprintf (buf, sizeof (buf), _("DSP: %.1f%% X: %u\n%s"), c, x, _("Shift+Click to clear xruns."));
1711         } else {
1712                 snprintf (buf, sizeof (buf), _("DSP: %.1f%%"), c);
1713         }
1714
1715         ArdourWidgets::set_tooltip (dsp_load_label, buf);
1716 }
1717
1718 void
1719 ARDOUR_UI::update_peak_thread_work ()
1720 {
1721         char buf[64];
1722         const int c = SourceFactory::peak_work_queue_length ();
1723         if (c > 0) {
1724                 snprintf (buf, sizeof (buf), _("PkBld: <span foreground=\"%s\">%d</span>"), c >= 2 ? X_("red") : X_("green"), c);
1725                 peak_thread_work_label.set_markup (buf);
1726         } else {
1727                 peak_thread_work_label.set_markup (X_(""));
1728         }
1729 }
1730
1731 void
1732 ARDOUR_UI::count_recenabled_streams (Route& route)
1733 {
1734         Track* track = dynamic_cast<Track*>(&route);
1735         if (track && track->rec_enable_control()->get_value()) {
1736                 rec_enabled_streams += track->n_inputs().n_total();
1737         }
1738 }
1739
1740 void
1741 ARDOUR_UI::format_disk_space_label (float remain_sec)
1742 {
1743         if (remain_sec < 0) {
1744                 disk_space_label.set_text (_("N/A"));
1745                 ArdourWidgets::set_tooltip (disk_space_label, _("Unknown"));
1746                 return;
1747         }
1748
1749         char buf[64];
1750
1751         int sec = floor (remain_sec);
1752         int hrs  = sec / 3600;
1753         int mins = (sec / 60) % 60;
1754         int secs = sec % 60;
1755         snprintf (buf, sizeof(buf), _("%02dh:%02dm:%02ds"), hrs, mins, secs);
1756         ArdourWidgets::set_tooltip (disk_space_label, buf);
1757
1758         if (remain_sec > 86400) {
1759                 disk_space_label.set_text (_("Rec: >24h"));
1760                 return;
1761         } else if (remain_sec > 32400 /* 9 hours */) {
1762                 snprintf (buf, sizeof (buf), "Rec: %.0fh", remain_sec / 3600.f);
1763         } else if (remain_sec > 5940 /* 99 mins */) {
1764                 snprintf (buf, sizeof (buf), "Rec: %.1fh", remain_sec / 3600.f);
1765         } else {
1766                 snprintf (buf, sizeof (buf), "Rec: %.0fm", remain_sec / 60.f);
1767         }
1768         disk_space_label.set_text (buf);
1769
1770 }
1771
1772 void
1773 ARDOUR_UI::update_disk_space()
1774 {
1775         if (_session == 0) {
1776                 format_disk_space_label (-1);
1777                 return;
1778         }
1779
1780         boost::optional<samplecnt_t> opt_samples = _session->available_capture_duration();
1781         samplecnt_t fr = _session->sample_rate();
1782
1783         if (fr == 0) {
1784                 /* skip update - no SR available */
1785                 format_disk_space_label (-1);
1786                 return;
1787         }
1788
1789         if (!opt_samples) {
1790                 /* Available space is unknown */
1791                 format_disk_space_label (-1);
1792         } else if (opt_samples.get_value_or (0) == max_samplecnt) {
1793                 format_disk_space_label (max_samplecnt);
1794         } else {
1795                 rec_enabled_streams = 0;
1796                 _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
1797
1798                 samplecnt_t samples = opt_samples.get_value_or (0);
1799
1800                 if (rec_enabled_streams) {
1801                         samples /= rec_enabled_streams;
1802                 }
1803
1804                 format_disk_space_label (samples / (float)fr);
1805         }
1806
1807 }
1808
1809 void
1810 ARDOUR_UI::update_timecode_format ()
1811 {
1812         char buf[64];
1813
1814         if (_session) {
1815                 bool matching;
1816                 boost::shared_ptr<TimecodeTransportMaster> tcmaster;
1817                 boost::shared_ptr<TransportMaster> tm = TransportMasterManager::instance().current();
1818
1819                 if ((tm->type() == LTC || tm->type() == MTC) && (tcmaster = boost::dynamic_pointer_cast<TimecodeTransportMaster>(tm)) != 0) {
1820                         matching = (tcmaster->apparent_timecode_format() == _session->config.get_timecode_format());
1821                 } else {
1822                         matching = true;
1823                 }
1824
1825                 snprintf (buf, sizeof (buf), S_("Timecode|TC: <span foreground=\"%s\">%s</span>"),
1826                           matching ? X_("green") : X_("red"),
1827                           Timecode::timecode_format_name (_session->config.get_timecode_format()).c_str());
1828         } else {
1829                 snprintf (buf, sizeof (buf), "TC: n/a");
1830         }
1831
1832         timecode_format_label.set_markup (buf);
1833 }
1834
1835 gint
1836 ARDOUR_UI::update_wall_clock ()
1837 {
1838         time_t now;
1839         struct tm *tm_now;
1840         static int last_min = -1;
1841
1842         time (&now);
1843         tm_now = localtime (&now);
1844         if (last_min != tm_now->tm_min) {
1845                 char buf[16];
1846                 sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1847                 wall_clock_label.set_text (buf);
1848                 last_min = tm_now->tm_min;
1849         }
1850
1851         return TRUE;
1852 }
1853
1854 void
1855 ARDOUR_UI::open_recent_session ()
1856 {
1857         bool can_return = (_session != 0);
1858
1859         SessionDialog recent_session_dialog;
1860
1861         while (true) {
1862
1863                 ResponseType r = (ResponseType) recent_session_dialog.run ();
1864
1865                 switch (r) {
1866                 case RESPONSE_ACCEPT:
1867                         break;
1868                 default:
1869                         if (can_return) {
1870                                 recent_session_dialog.hide();
1871                                 return;
1872                         } else {
1873                                 exit (1);
1874                         }
1875                 }
1876
1877                 recent_session_dialog.hide();
1878
1879                 bool should_be_new;
1880
1881                 std::string path = recent_session_dialog.session_folder();
1882                 std::string state = recent_session_dialog.session_name (should_be_new);
1883
1884                 if (should_be_new == true) {
1885                         continue;
1886                 }
1887
1888                 _session_is_new = false;
1889
1890                 if (load_session (path, state) == 0) {
1891                         break;
1892                 }
1893
1894                 can_return = false;
1895         }
1896 }
1897
1898 bool
1899 ARDOUR_UI::check_audioengine (Gtk::Window& parent)
1900 {
1901         if (!AudioEngine::instance()->connected()) {
1902                 MessageDialog msg (parent, string_compose (
1903                                            _("%1 is not connected to any audio backend.\n"
1904                                            "You cannot open or close sessions in this condition"),
1905                                            PROGRAM_NAME));
1906                 pop_back_splash (msg);
1907                 msg.run ();
1908                 return false;
1909         }
1910         return true;
1911 }
1912
1913 void
1914 ARDOUR_UI::open_session ()
1915 {
1916         if (!check_audioengine (_main_window)) {
1917                 return;
1918         }
1919
1920         /* ardour sessions are folders */
1921         Gtk::FileChooserDialog open_session_selector(_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1922         open_session_selector.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1923         open_session_selector.add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1924         open_session_selector.set_default_response(Gtk::RESPONSE_ACCEPT);
1925
1926         if (_session) {
1927                 string session_parent_dir = Glib::path_get_dirname(_session->path());
1928                 open_session_selector.set_current_folder(session_parent_dir);
1929         } else {
1930                 open_session_selector.set_current_folder(Config->get_default_session_parent_dir());
1931         }
1932
1933         Gtkmm2ext::add_volume_shortcuts (open_session_selector);
1934         try {
1935                 /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */
1936                 string default_session_folder = Config->get_default_session_parent_dir();
1937                 open_session_selector.add_shortcut_folder (default_session_folder);
1938         }
1939         catch (Glib::Error const& e) {
1940                 std::cerr << "open_session_selector.add_shortcut_folder() threw Glib::Error " << e.what() << std::endl;
1941         }
1942
1943         FileFilter session_filter;
1944         session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
1945         session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
1946         open_session_selector.add_filter (session_filter);
1947
1948         FileFilter archive_filter;
1949         archive_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::session_archive_suffix));
1950         archive_filter.set_name (_("Session Archives"));
1951
1952         open_session_selector.add_filter (archive_filter);
1953
1954         open_session_selector.set_filter (session_filter);
1955
1956         int response = open_session_selector.run();
1957         open_session_selector.hide ();
1958
1959         if (response == Gtk::RESPONSE_CANCEL) {
1960                 return;
1961         }
1962
1963         string session_path = open_session_selector.get_filename();
1964         string path, name;
1965         bool isnew;
1966
1967         if (session_path.length() > 0) {
1968                 int rv = ARDOUR::inflate_session (session_path,
1969                                 Config->get_default_session_parent_dir(), path, name);
1970                 if (rv == 0) {
1971                         _session_is_new = false;
1972                         load_session (path, name);
1973                 }
1974                 else if (rv < 0) {
1975                         MessageDialog msg (_main_window,
1976                                         string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
1977                         msg.run ();
1978                 }
1979                 else if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1980                         _session_is_new = isnew;
1981                         load_session (path, name);
1982                 }
1983         }
1984 }
1985
1986 void
1987 ARDOUR_UI::session_add_mixed_track (
1988                 const ChanCount& input,
1989                 const ChanCount& output,
1990                 RouteGroup* route_group,
1991                 uint32_t how_many,
1992                 const string& name_template,
1993                 bool strict_io,
1994                 PluginInfoPtr instrument,
1995                 Plugin::PresetRecord* pset,
1996                 ARDOUR::PresentationInfo::order_t order)
1997 {
1998         assert (_session);
1999
2000         if (Profile->get_mixbus ()) {
2001                 strict_io = true;
2002         }
2003
2004         try {
2005                 list<boost::shared_ptr<MidiTrack> > tracks;
2006                 tracks = _session->new_midi_track (input, output, strict_io, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
2007
2008                 if (tracks.size() != how_many) {
2009                         error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
2010                 }
2011         }
2012
2013         catch (...) {
2014                 display_insufficient_ports_message ();
2015                 return;
2016         }
2017 }
2018
2019 void
2020 ARDOUR_UI::session_add_midi_bus (
2021                 RouteGroup* route_group,
2022                 uint32_t how_many,
2023                 const string& name_template,
2024                 bool strict_io,
2025                 PluginInfoPtr instrument,
2026                 Plugin::PresetRecord* pset,
2027                 ARDOUR::PresentationInfo::order_t order)
2028 {
2029         if (_session == 0) {
2030                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
2031                 return;
2032         }
2033
2034         if (Profile->get_mixbus ()) {
2035                 strict_io = true;
2036         }
2037
2038         try {
2039                 RouteList routes;
2040                 routes = _session->new_midi_route (route_group, how_many, name_template, strict_io, instrument, pset, PresentationInfo::MidiBus, order);
2041                 if (routes.size() != how_many) {
2042                         error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
2043                 }
2044
2045         }
2046         catch (...) {
2047                 display_insufficient_ports_message ();
2048                 return;
2049         }
2050 }
2051
2052 void
2053 ARDOUR_UI::session_add_midi_route (
2054                 bool disk,
2055                 RouteGroup* route_group,
2056                 uint32_t how_many,
2057                 const string& name_template,
2058                 bool strict_io,
2059                 PluginInfoPtr instrument,
2060                 Plugin::PresetRecord* pset,
2061                 ARDOUR::PresentationInfo::order_t order)
2062 {
2063         ChanCount one_midi_channel;
2064         one_midi_channel.set (DataType::MIDI, 1);
2065
2066         if (disk) {
2067                 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument, pset, order);
2068         } else {
2069                 session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument, pset, order);
2070         }
2071 }
2072
2073 void
2074 ARDOUR_UI::session_add_audio_route (
2075         bool track,
2076         int32_t input_channels,
2077         int32_t output_channels,
2078         ARDOUR::TrackMode mode,
2079         RouteGroup* route_group,
2080         uint32_t how_many,
2081         string const & name_template,
2082         bool strict_io,
2083         ARDOUR::PresentationInfo::order_t order)
2084 {
2085         list<boost::shared_ptr<AudioTrack> > tracks;
2086         RouteList routes;
2087
2088         assert (_session);
2089
2090         try {
2091                 if (track) {
2092                         tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode);
2093
2094                         if (tracks.size() != how_many) {
2095                                 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
2096                                       << endmsg;
2097                         }
2098
2099                 } else {
2100
2101                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order);
2102
2103                         if (routes.size() != how_many) {
2104                                 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
2105                                       << endmsg;
2106                         }
2107                 }
2108         }
2109
2110         catch (...) {
2111                 display_insufficient_ports_message ();
2112                 return;
2113         }
2114
2115         if (strict_io) {
2116                 for (list<boost::shared_ptr<AudioTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
2117                         (*i)->set_strict_io (true);
2118                 }
2119                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2120                         (*i)->set_strict_io (true);
2121                 }
2122         }
2123 }
2124
2125 void
2126 ARDOUR_UI::session_add_listen_bus (uint32_t how_many, string const & name_template)
2127 {
2128         RouteList routes;
2129
2130         assert (_session);
2131
2132         try {
2133                 routes = _session->new_audio_route (2, 2, 0, how_many, name_template, PresentationInfo::ListenBus, -1);
2134
2135                 if (routes.size() != how_many) {
2136                         error << string_compose (P_("could not create %1 new listen bus", "could not create %1 new listen busses", how_many), how_many)
2137                               << endmsg;
2138                 }
2139         }
2140
2141         catch (...) {
2142                 display_insufficient_ports_message ();
2143                 return;
2144         }
2145
2146         for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2147                 (*i)->set_strict_io (true);
2148         }
2149 }
2150
2151 void
2152 ARDOUR_UI::display_insufficient_ports_message ()
2153 {
2154         MessageDialog msg (_main_window,
2155                         string_compose (_("There are insufficient ports available\n\
2156 to create a new track or bus.\n\
2157 You should save %1, exit and\n\
2158 restart with more ports."), PROGRAM_NAME));
2159         pop_back_splash (msg);
2160         msg.run ();
2161 }
2162
2163 void
2164 ARDOUR_UI::transport_goto_start ()
2165 {
2166         if (_session) {
2167                 _session->goto_start();
2168
2169                 /* force displayed area in editor to start no matter
2170                    what "follow playhead" setting is.
2171                 */
2172
2173                 if (editor) {
2174                         editor->center_screen (_session->current_start_sample ());
2175                 }
2176         }
2177 }
2178
2179 void
2180 ARDOUR_UI::transport_goto_zero ()
2181 {
2182         if (_session) {
2183                 _session->request_locate (0);
2184
2185                 /* force displayed area in editor to start no matter
2186                    what "follow playhead" setting is.
2187                 */
2188
2189                 if (editor) {
2190                         editor->reset_x_origin (0);
2191                 }
2192         }
2193 }
2194
2195 void
2196 ARDOUR_UI::transport_goto_wallclock ()
2197 {
2198         if (_session && editor) {
2199
2200                 time_t now;
2201                 struct tm tmnow;
2202                 samplepos_t samples;
2203
2204                 time (&now);
2205                 localtime_r (&now, &tmnow);
2206
2207                 samplecnt_t sample_rate = _session->sample_rate();
2208
2209                 if (sample_rate == 0) {
2210                         /* no frame rate available */
2211                         return;
2212                 }
2213
2214                 samples = tmnow.tm_hour * (60 * 60 * sample_rate);
2215                 samples += tmnow.tm_min * (60 * sample_rate);
2216                 samples += tmnow.tm_sec * sample_rate;
2217
2218                 _session->request_locate (samples, _session->transport_rolling ());
2219
2220                 /* force displayed area in editor to start no matter
2221                    what "follow playhead" setting is.
2222                 */
2223
2224                 if (editor) {
2225                         editor->center_screen (samples);
2226                 }
2227         }
2228 }
2229
2230 void
2231 ARDOUR_UI::transport_goto_end ()
2232 {
2233         if (_session) {
2234                 samplepos_t const sample = _session->current_end_sample();
2235                 _session->request_locate (sample);
2236
2237                 /* force displayed area in editor to start no matter
2238                    what "follow playhead" setting is.
2239                 */
2240
2241                 if (editor) {
2242                         editor->center_screen (sample);
2243                 }
2244         }
2245 }
2246
2247 void
2248 ARDOUR_UI::transport_stop ()
2249 {
2250         if (!_session) {
2251                 return;
2252         }
2253
2254         if (_session->is_auditioning()) {
2255                 _session->cancel_audition ();
2256                 return;
2257         }
2258
2259         _session->request_stop (false, true);
2260 }
2261
2262 /** Check if any tracks are record enabled. If none are, record enable all of them.
2263  * @return true if track record-enabled status was changed, false otherwise.
2264  */
2265 bool
2266 ARDOUR_UI::trx_record_enable_all_tracks ()
2267 {
2268         if (!_session) {
2269                 return false;
2270         }
2271
2272         boost::shared_ptr<RouteList> rl = _session->get_tracks ();
2273         bool none_record_enabled = true;
2274
2275         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2276                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
2277                 assert (t);
2278
2279                 if (t->rec_enable_control()->get_value()) {
2280                         none_record_enabled = false;
2281                         break;
2282                 }
2283         }
2284
2285         if (none_record_enabled) {
2286                 _session->set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), 1.0, Controllable::NoGroup);
2287         }
2288
2289         return none_record_enabled;
2290 }
2291
2292 void
2293 ARDOUR_UI::transport_record (bool roll)
2294 {
2295         if (_session) {
2296                 switch (_session->record_status()) {
2297                 case Session::Disabled:
2298                         if (_session->ntracks() == 0) {
2299                                 MessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu."));
2300                                 msg.run ();
2301                                 return;
2302                         }
2303                         if (Profile->get_trx()) {
2304                                 roll = trx_record_enable_all_tracks ();
2305                         }
2306                         _session->maybe_enable_record ();
2307                         if (roll) {
2308                                 transport_roll ();
2309                         }
2310                         break;
2311                 case Session::Recording:
2312                         if (roll) {
2313                                 _session->request_stop();
2314                         } else {
2315                                 _session->disable_record (false, true);
2316                         }
2317                         break;
2318
2319                 case Session::Enabled:
2320                         _session->disable_record (false, true);
2321                 }
2322         }
2323 }
2324
2325 void
2326 ARDOUR_UI::transport_roll ()
2327 {
2328         if (!_session) {
2329                 return;
2330         }
2331
2332         if (_session->is_auditioning()) {
2333                 return;
2334         }
2335
2336         if (_session->config.get_external_sync()) {
2337                 switch (TransportMasterManager::instance().current()->type()) {
2338                 case Engine:
2339                         break;
2340                 default:
2341                         /* transport controlled by the master */
2342                         return;
2343                 }
2344         }
2345
2346         bool rolling = _session->transport_rolling();
2347
2348         if (_session->get_play_loop()) {
2349
2350                 /* If loop playback is not a mode, then we should cancel
2351                    it when this action is requested. If it is a mode
2352                    we just leave it in place.
2353                 */
2354
2355                 if (!Config->get_loop_is_mode()) {
2356                         /* XXX it is not possible to just leave seamless loop and keep
2357                            playing at present (nov 4th 2009)
2358                         */
2359                         if (!Config->get_seamless_loop()) {
2360                                 /* stop loop playback and stop rolling */
2361                                 _session->request_play_loop (false, true);
2362                         } else if (rolling) {
2363                                 /* stop loop playback but keep rolling */
2364                                 _session->request_play_loop (false, false);
2365                         }
2366                 }
2367
2368         } else if (_session->get_play_range () ) {
2369                 /* stop playing a range if we currently are */
2370                 _session->request_play_range (0, true);
2371         }
2372
2373         if (!rolling) {
2374                 _session->request_transport_speed (1.0f);
2375         }
2376 }
2377
2378 bool
2379 ARDOUR_UI::get_smart_mode() const
2380 {
2381         return ( editor->get_smart_mode() );
2382 }
2383
2384
2385 void
2386 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2387 {
2388         if (!_session) {
2389                 return;
2390         }
2391
2392         if (_session->is_auditioning()) {
2393                 _session->cancel_audition ();
2394                 return;
2395         }
2396
2397         if (_session->config.get_external_sync()) {
2398                 switch (TransportMasterManager::instance().current()->type()) {
2399                 case Engine:
2400                         break;
2401                 default:
2402                         /* transport controlled by the master */
2403                         return;
2404                 }
2405         }
2406
2407         bool rolling = _session->transport_rolling();
2408         bool affect_transport = true;
2409
2410         if (rolling && roll_out_of_bounded_mode) {
2411                 /* drop out of loop/range playback but leave transport rolling */
2412                 if (_session->get_play_loop()) {
2413                         if (_session->actively_recording()) {
2414
2415                                 /* just stop using the loop, then actually stop
2416                                  * below
2417                                  */
2418                                 _session->request_play_loop (false, affect_transport);
2419
2420                         } else {
2421                                 if (Config->get_seamless_loop()) {
2422                                         /* the disk buffers contain copies of the loop - we can't
2423                                            just keep playing, so stop the transport. the user
2424                                            can restart as they wish.
2425                                         */
2426                                         affect_transport = true;
2427                                 } else {
2428                                         /* disk buffers are normal, so we can keep playing */
2429                                         affect_transport = false;
2430                                 }
2431                                 _session->request_play_loop (false, affect_transport);
2432                         }
2433                 } else if (_session->get_play_range ()) {
2434                         affect_transport = false;
2435                         _session->request_play_range (0, true);
2436                 }
2437         }
2438
2439         if (affect_transport) {
2440                 if (rolling) {
2441                         _session->request_stop (with_abort, true);
2442
2443                 } else if (!with_abort) { /* with_abort == true means the
2444                                            * command was intended to stop
2445                                            * transport, not start.
2446                                            */
2447
2448                         /* the only external sync condition we can be in here
2449                          * would be Engine (JACK) sync, in which case we still
2450                          * want to do this.
2451                          */
2452
2453                         if (UIConfiguration::instance().get_follow_edits() && ( editor->get_selection().time.front().start == _session->transport_sample() ) ) {  //if playhead is exactly at the start of a range, we can assume it was placed there by follow_edits
2454                                 _session->request_play_range (&editor->get_selection().time, true);
2455                                 _session->set_requested_return_sample( editor->get_selection().time.front().start );  //force an auto-return here
2456                         }
2457                         _session->request_transport_speed (1.0f);
2458                 }
2459         }
2460 }
2461
2462 void
2463 ARDOUR_UI::toggle_session_auto_loop ()
2464 {
2465         if (!_session) {
2466                 return;
2467         }
2468
2469         Location * looploc = _session->locations()->auto_loop_location();
2470
2471         if (!looploc) {
2472                 return;
2473         }
2474
2475         if (_session->get_play_loop()) {
2476
2477                 /* looping enabled, our job is to disable it */
2478
2479                 _session->request_play_loop (false);
2480
2481         } else {
2482
2483                 /* looping not enabled, our job is to enable it.
2484
2485                    loop-is-NOT-mode: this action always starts the transport rolling.
2486                    loop-IS-mode:     this action simply sets the loop play mechanism, but
2487                                         does not start transport.
2488                 */
2489                 if (Config->get_loop_is_mode()) {
2490                         _session->request_play_loop (true, false);
2491                 } else {
2492                         _session->request_play_loop (true, true);
2493                 }
2494         }
2495
2496         //show the loop markers
2497         looploc->set_hidden (false, this);
2498 }
2499
2500 void
2501 ARDOUR_UI::transport_play_selection ()
2502 {
2503         if (!_session) {
2504                 return;
2505         }
2506
2507         editor->play_selection ();
2508 }
2509
2510 void
2511 ARDOUR_UI::transport_play_preroll ()
2512 {
2513         if (!_session) {
2514                 return;
2515         }
2516         editor->play_with_preroll ();
2517 }
2518
2519 void
2520 ARDOUR_UI::transport_rec_preroll ()
2521 {
2522         if (!_session) {
2523                 return;
2524         }
2525         editor->rec_with_preroll ();
2526 }
2527
2528 void
2529 ARDOUR_UI::transport_rec_count_in ()
2530 {
2531         if (!_session) {
2532                 return;
2533         }
2534         editor->rec_with_count_in ();
2535 }
2536
2537 void
2538 ARDOUR_UI::transport_rewind (int option)
2539 {
2540         float current_transport_speed;
2541
2542         if (_session) {
2543                 current_transport_speed = _session->transport_speed();
2544
2545                 if (current_transport_speed >= 0.0f) {
2546                         switch (option) {
2547                         case 0:
2548                                 _session->request_transport_speed (-1.0f);
2549                                 break;
2550                         case 1:
2551                                 _session->request_transport_speed (-4.0f);
2552                                 break;
2553                         case -1:
2554                                 _session->request_transport_speed (-0.5f);
2555                                 break;
2556                         }
2557                 } else {
2558                         /* speed up */
2559                         _session->request_transport_speed (current_transport_speed * 1.5f);
2560                 }
2561         }
2562 }
2563
2564 void
2565 ARDOUR_UI::transport_forward (int option)
2566 {
2567         if (!_session) {
2568                 return;
2569         }
2570
2571         float current_transport_speed = _session->transport_speed();
2572
2573         if (current_transport_speed <= 0.0f) {
2574                 switch (option) {
2575                 case 0:
2576                         _session->request_transport_speed (1.0f);
2577                         break;
2578                 case 1:
2579                         _session->request_transport_speed (4.0f);
2580                         break;
2581                 case -1:
2582                         _session->request_transport_speed (0.5f);
2583                         break;
2584                 }
2585         } else {
2586                 /* speed up */
2587                 _session->request_transport_speed (current_transport_speed * 1.5f);
2588         }
2589 }
2590
2591 void
2592 ARDOUR_UI::toggle_record_enable (uint16_t rid)
2593 {
2594         if (!_session) {
2595                 return;
2596         }
2597
2598         boost::shared_ptr<Route> r;
2599
2600         if ((r = _session->get_remote_nth_route (rid)) != 0) {
2601
2602                 boost::shared_ptr<Track> t;
2603
2604                 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2605                         t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup);
2606                 }
2607         }
2608 }
2609
2610 void
2611 ARDOUR_UI::map_transport_state ()
2612 {
2613         if (!_session) {
2614                 layered_button.set_sensitive (false);
2615                 return;
2616         }
2617
2618         shuttle_box.map_transport_state ();
2619
2620         float sp = _session->transport_speed();
2621
2622         if (sp != 0.0f) {
2623                 layered_button.set_sensitive (!_session->actively_recording ());
2624         } else {
2625                 layered_button.set_sensitive (true);
2626                 update_disk_space ();
2627         }
2628 }
2629
2630 void
2631 ARDOUR_UI::blink_handler (bool blink_on)
2632 {
2633         sync_blink (blink_on);
2634
2635         if (!UIConfiguration::instance().get_blink_alert_indicators()) {
2636                 blink_on = true;
2637         }
2638         error_blink (blink_on);
2639         solo_blink (blink_on);
2640         audition_blink (blink_on);
2641         feedback_blink (blink_on);
2642 }
2643
2644 void
2645 ARDOUR_UI::update_clocks ()
2646 {
2647         if (!_session) return;
2648
2649         if (editor && !editor->dragging_playhead()) {
2650                 Clock (_session->audible_sample()); /* EMIT_SIGNAL */
2651         }
2652 }
2653
2654 void
2655 ARDOUR_UI::start_clocking ()
2656 {
2657         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2658                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2659         } else {
2660                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2661         }
2662 }
2663
2664 void
2665 ARDOUR_UI::stop_clocking ()
2666 {
2667         clock_signal_connection.disconnect ();
2668 }
2669
2670 bool
2671 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2672 {
2673         char buf[256];
2674
2675         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2676
2677         label->set_text (buf);
2678         bar->set_fraction (fraction);
2679
2680         /* process events, redraws, etc. */
2681
2682         while (gtk_events_pending()) {
2683                 gtk_main_iteration ();
2684         }
2685
2686         return true; /* continue with save-as */
2687 }
2688
2689 void
2690 ARDOUR_UI::save_session_as ()
2691 {
2692         if (!_session) {
2693                 return;
2694         }
2695
2696         if (_session->dirty()) {
2697                 vector<string> actions;
2698                 actions.push_back (_("Abort save-as"));
2699                 actions.push_back (_("Don't save now, just save-as"));
2700                 actions.push_back (_("Save it first"));
2701                 switch (ask_about_saving_session(actions)) {
2702                         case -1:
2703                                 return;
2704                                 break;
2705                         case 1:
2706                                 if (save_state_canfail ("")) {
2707                                         MessageDialog msg (_main_window,
2708                                                         string_compose (_("\
2709 %1 was unable to save your session.\n\n\
2710 If you still wish to proceed, please use the\n\n\
2711 \"Don't save now\" option."), PROGRAM_NAME));
2712                                         pop_back_splash(msg);
2713                                         msg.run ();
2714                                         return;
2715                                 }
2716                                 /* fall through */
2717                         case 0:
2718                                 _session->remove_pending_capture_state ();
2719                                 break;
2720                 }
2721         }
2722
2723         if (!save_as_dialog) {
2724                 save_as_dialog = new SaveAsDialog;
2725         }
2726
2727         save_as_dialog->set_name (_session->name());
2728
2729         int response = save_as_dialog->run ();
2730
2731         save_as_dialog->hide ();
2732
2733         switch (response) {
2734         case Gtk::RESPONSE_OK:
2735                 break;
2736         default:
2737                 return;
2738         }
2739
2740
2741         Session::SaveAs sa;
2742
2743         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2744         sa.new_name = save_as_dialog->new_name ();
2745         sa.switch_to = save_as_dialog->switch_to();
2746         sa.copy_media = save_as_dialog->copy_media();
2747         sa.copy_external = save_as_dialog->copy_external();
2748         sa.include_media = save_as_dialog->include_media ();
2749
2750         /* Only bother with a progress dialog if we're going to copy
2751            media into the save-as target. Without that choice, this
2752            will be very fast because we're only talking about a few kB's to
2753            perhaps a couple of MB's of data.
2754         */
2755
2756         ArdourDialog progress_dialog (_("Save As"), true);
2757         ScopedConnection c;
2758
2759         if (sa.include_media && sa.copy_media) {
2760
2761                 Gtk::Label* label = manage (new Gtk::Label());
2762                 Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
2763
2764                 progress_dialog.get_vbox()->pack_start (*label);
2765                 progress_dialog.get_vbox()->pack_start (*progress_bar);
2766                 label->show ();
2767                 progress_bar->show ();
2768
2769                 /* this signal will be emitted from within this, the calling thread,
2770                  * after every file is copied. It provides information on percentage
2771                  * complete (in terms of total data to copy), the number of files
2772                  * copied so far, and the total number to copy.
2773                  */
2774
2775                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar));
2776
2777                 progress_dialog.show_all ();
2778                 progress_dialog.present ();
2779         }
2780
2781         if (_session->save_as (sa)) {
2782                 /* ERROR MESSAGE */
2783                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2784                 msg.run ();
2785         }
2786
2787         /* the logic here may seem odd: why isn't the condition sa.switch_to ?
2788          * the trick is this: if the new session was copy with media included,
2789          * then Session::save_as() will have already done a neat trick to avoid
2790          * us having to unload and load the new state. But if the media was not
2791          * included, then this is required (it avoids us having to otherwise
2792          * drop all references to media (sources).
2793          */
2794
2795         if (!sa.include_media && sa.switch_to) {
2796                 unload_session (false);
2797                 load_session (sa.final_session_folder_name, sa.new_name);
2798         }
2799 }
2800
2801 void
2802 ARDOUR_UI::archive_session ()
2803 {
2804         if (!_session) {
2805                 return;
2806         }
2807
2808         time_t n;
2809         time (&n);
2810         Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
2811
2812         SessionArchiveDialog sad;
2813         sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
2814         int response = sad.run ();
2815
2816         if (response != Gtk::RESPONSE_OK) {
2817                 sad.hide ();
2818                 return;
2819         }
2820
2821         if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.compression_level (), sad.only_used_sources (), &sad)) {
2822                 MessageDialog msg (_("Session Archiving failed."));
2823                 msg.run ();
2824         }
2825 }
2826
2827 void
2828 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2829 {
2830                 char timebuf[128];
2831                 time_t n;
2832                 struct tm local_time;
2833
2834                 time (&n);
2835                 localtime_r (&n, &local_time);
2836                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2837                 if (switch_to_it && _session->dirty ()) {
2838                         save_state_canfail ("");
2839                 }
2840
2841                 save_state (timebuf, switch_to_it);
2842 }
2843
2844
2845 bool
2846 ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
2847 {
2848         string snapname;
2849
2850         prompter.get_result (snapname);
2851
2852         bool do_save = (snapname.length() != 0);
2853
2854         if (do_save) {
2855                 char illegal = Session::session_name_is_legal(snapname);
2856                 if (illegal) {
2857                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2858                                                              "snapshot names may not contain a '%1' character"), illegal));
2859                         msg.run ();
2860                         return false;
2861                 }
2862         }
2863
2864         vector<std::string> p;
2865         get_state_files_in_directory (_session->session_directory().root_path(), p);
2866         vector<string> n = get_file_names_no_extension (p);
2867
2868         if (find (n.begin(), n.end(), snapname) != n.end()) {
2869
2870                 do_save = overwrite_file_dialog (prompter,
2871                                                  _("Confirm Snapshot Overwrite"),
2872                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2873         }
2874
2875         if (do_save) {
2876                 save_state (snapname, switch_to_it);
2877         }
2878         else {
2879                 return false;
2880         }
2881
2882         return true;
2883 }
2884
2885
2886 /** Ask the user for the name of a new snapshot and then take it.
2887  */
2888
2889 void
2890 ARDOUR_UI::snapshot_session (bool switch_to_it)
2891 {
2892         if (switch_to_it && _session->dirty()) {
2893                 vector<string> actions;
2894                 actions.push_back (_("Abort saving snapshot"));
2895                 actions.push_back (_("Don't save now, just snapshot"));
2896                 actions.push_back (_("Save it first"));
2897                 switch (ask_about_saving_session(actions)) {
2898                         case -1:
2899                                 return;
2900                                 break;
2901                         case 1:
2902                                 if (save_state_canfail ("")) {
2903                                         MessageDialog msg (_main_window,
2904                                                         string_compose (_("\
2905 %1 was unable to save your session.\n\n\
2906 If you still wish to proceed, please use the\n\n\
2907 \"Don't save now\" option."), PROGRAM_NAME));
2908                                         pop_back_splash(msg);
2909                                         msg.run ();
2910                                         return;
2911                                 }
2912                                 /* fall through */
2913                         case 0:
2914                                 _session->remove_pending_capture_state ();
2915                                 break;
2916                 }
2917         }
2918
2919         Prompter prompter (true);
2920         prompter.set_name ("Prompter");
2921         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2922         if (switch_to_it) {
2923                 prompter.set_title (_("Snapshot and switch"));
2924                 prompter.set_prompt (_("New session name"));
2925         } else {
2926                 prompter.set_title (_("Take Snapshot"));
2927                 prompter.set_prompt (_("Name of new snapshot"));
2928         }
2929
2930         if (switch_to_it) {
2931                 prompter.set_initial_text (_session->snap_name());
2932         } else {
2933                 Glib::DateTime tm (g_date_time_new_now_local ());
2934                 prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
2935         }
2936
2937         bool finished = false;
2938         while (!finished) {
2939                 switch (prompter.run()) {
2940                 case RESPONSE_ACCEPT:
2941                 {
2942                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2943                         break;
2944                 }
2945
2946                 default:
2947                         finished = true;
2948                         break;
2949                 }
2950         }
2951 }
2952
2953 /** Ask the user for a new session name and then rename the session to it.
2954  */
2955
2956 void
2957 ARDOUR_UI::rename_session ()
2958 {
2959         if (!_session) {
2960                 return;
2961         }
2962
2963         Prompter prompter (true);
2964         string name;
2965
2966         prompter.set_name ("Prompter");
2967         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2968         prompter.set_title (_("Rename Session"));
2969         prompter.set_prompt (_("New session name"));
2970
2971   again:
2972         switch (prompter.run()) {
2973         case RESPONSE_ACCEPT:
2974         {
2975                 prompter.get_result (name);
2976
2977                 bool do_rename = (name.length() != 0);
2978
2979                 if (do_rename) {
2980                         char illegal = Session::session_name_is_legal (name);
2981
2982                         if (illegal) {
2983                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2984                                                                      "session names may not contain a '%1' character"), illegal));
2985                                 msg.run ();
2986                                 goto again;
2987                         }
2988
2989                         switch (_session->rename (name)) {
2990                         case -1: {
2991                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2992                                 msg.set_position (WIN_POS_MOUSE);
2993                                 msg.run ();
2994                                 goto again;
2995                                 break;
2996                         }
2997                         case 0:
2998                                 break;
2999                         default: {
3000                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
3001                                 msg.set_position (WIN_POS_MOUSE);
3002                                 msg.run ();
3003                                 break;
3004                         }
3005                         }
3006                 }
3007
3008                 break;
3009         }
3010
3011         default:
3012                 break;
3013         }
3014 }
3015
3016 void
3017 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
3018 {
3019         if (!_session || _session->deletion_in_progress()) {
3020                 return;
3021         }
3022
3023         XMLNode* node = new XMLNode (X_("UI"));
3024
3025         WM::Manager::instance().add_state (*node);
3026
3027         node->add_child_nocopy (gui_object_state->get_state());
3028
3029         _session->add_extra_xml (*node);
3030
3031         if (export_video_dialog) {
3032                 _session->add_extra_xml (export_video_dialog->get_state());
3033         }
3034
3035         save_state_canfail (name, switch_to_it);
3036 }
3037
3038 int
3039 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
3040 {
3041         if (_session) {
3042                 int ret;
3043
3044                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
3045                         return ret;
3046                 }
3047         }
3048
3049         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
3050         return 0;
3051 }
3052
3053 void
3054 ARDOUR_UI::primary_clock_value_changed ()
3055 {
3056         if (_session) {
3057                 _session->request_locate (primary_clock->current_time ());
3058         }
3059 }
3060
3061 void
3062 ARDOUR_UI::big_clock_value_changed ()
3063 {
3064         if (_session) {
3065                 _session->request_locate (big_clock->current_time ());
3066         }
3067 }
3068
3069 void
3070 ARDOUR_UI::secondary_clock_value_changed ()
3071 {
3072         if (_session) {
3073                 _session->request_locate (secondary_clock->current_time ());
3074         }
3075 }
3076 void
3077 ARDOUR_UI::save_template_dialog_response (int response, SaveTemplateDialog* d)
3078 {
3079         if (response == RESPONSE_ACCEPT) {
3080                 const string name = d->get_template_name ();
3081                 const string desc = d->get_description ();
3082
3083                 int failed = _session->save_template (name, desc);
3084
3085                 if (failed == -2) { /* file already exists. */
3086                         bool overwrite = overwrite_file_dialog (*d,
3087                                                                 _("Confirm Template Overwrite"),
3088                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
3089
3090                         if (overwrite) {
3091                                 _session->save_template (name, desc, true);
3092                         }
3093                         else {
3094                                 d->show ();
3095                                 return;
3096                         }
3097                 }
3098         }
3099         delete d;
3100 }
3101
3102 void
3103 ARDOUR_UI::save_template ()
3104 {
3105         if (!check_audioengine (_main_window)) {
3106                 return;
3107         }
3108
3109         const std::string desc = SessionMetadata::Metadata()->description ();
3110         SaveTemplateDialog* d = new SaveTemplateDialog (_session->name (), desc);
3111         d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::save_template_dialog_response), d));
3112         d->show ();
3113 }
3114
3115 void ARDOUR_UI::manage_templates ()
3116 {
3117         TemplateDialog td;
3118         td.run();
3119 }
3120
3121 void
3122 ARDOUR_UI::edit_metadata ()
3123 {
3124         SessionMetadataEditor dialog;
3125         dialog.set_session (_session);
3126         dialog.grab_focus ();
3127         dialog.run ();
3128 }
3129
3130 void
3131 ARDOUR_UI::import_metadata ()
3132 {
3133         SessionMetadataImporter dialog;
3134         dialog.set_session (_session);
3135         dialog.run ();
3136 }
3137
3138 bool
3139 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
3140 {
3141         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
3142
3143         MessageDialog msg (str,
3144                            false,
3145                            Gtk::MESSAGE_WARNING,
3146                            Gtk::BUTTONS_YES_NO,
3147                            true);
3148
3149
3150         msg.set_name (X_("OpenExistingDialog"));
3151         msg.set_title (_("Open Existing Session"));
3152         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
3153         msg.set_position (Gtk::WIN_POS_CENTER);
3154         pop_back_splash (msg);
3155
3156         switch (msg.run()) {
3157         case RESPONSE_YES:
3158                 return true;
3159                 break;
3160         }
3161         return false;
3162 }
3163
3164 int
3165 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
3166 {
3167         BusProfile bus_profile;
3168
3169         if (nsm) {
3170                 bus_profile.master_out_channels = 2;
3171         } else {
3172                 /* get settings from advanced section of NSD */
3173                 bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
3174         }
3175
3176         // NULL profile: no master, no monitor
3177         if (build_session (session_path, session_name, bus_profile.master_out_channels > 0 ? &bus_profile : NULL)) {
3178                 return -1;
3179         }
3180
3181         return 0;
3182 }
3183
3184 void
3185 ARDOUR_UI::load_from_application_api (const std::string& path)
3186 {
3187         /* OS X El Capitan (and probably later) now somehow passes the command
3188            line arguments to an app via the openFile delegate protocol. Ardour
3189            already does its own command line processing, and having both
3190            pathways active causes crashes. So, if the command line was already
3191            set, do nothing here.
3192         */
3193
3194         if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3195                 return;
3196         }
3197
3198         ARDOUR_COMMAND_LINE::session_name = path;
3199
3200         /* Cancel SessionDialog if it's visible to make OSX delegates work.
3201          *
3202          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
3203          * race-condition:
3204          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
3205          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
3206          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
3207          *    -> SessionDialog is not displayed
3208          */
3209
3210         if (_session_dialog) {
3211                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3212                 std::string session_path = path;
3213                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
3214                         session_path = Glib::path_get_dirname (session_path);
3215                 }
3216                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
3217                 _session_dialog->set_provided_session (session_name, session_path);
3218                 _session_dialog->response (RESPONSE_NONE);
3219                 _session_dialog->hide();
3220                 return;
3221         }
3222
3223         int rv;
3224         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
3225                 /* /path/to/foo => /path/to/foo, foo */
3226                 rv = load_session (path, basename_nosuffix (path));
3227         } else {
3228                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3229                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3230         }
3231
3232         // if load_session fails -> pop up SessionDialog.
3233         if (rv) {
3234                 ARDOUR_COMMAND_LINE::session_name = "";
3235
3236                 if (get_session_parameters (true, false)) {
3237                         exit (1);
3238                 }
3239         }
3240 }
3241
3242 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3243 int
3244 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3245 {
3246         string session_name;
3247         string session_path;
3248         string template_name;
3249         int ret = -1;
3250         bool likely_new = false;
3251         bool cancel_not_quit;
3252
3253         /* deal with any existing DIRTY session now, rather than later. don't
3254          * treat a non-dirty session this way, so that it stays visible
3255          * as we bring up the new session dialog.
3256          */
3257
3258         if (_session && ARDOUR_UI::instance()->video_timeline) {
3259                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3260         }
3261
3262         /* if there is already a session, relabel the button
3263            on the SessionDialog so that we don't Quit directly
3264         */
3265         cancel_not_quit = (_session != 0) && !quit_on_cancel;
3266
3267         if (_session && _session->dirty()) {
3268                 if (unload_session (false)) {
3269                         /* unload cancelled by user */
3270                         return 0;
3271                 }
3272                 ARDOUR_COMMAND_LINE::session_name = "";
3273         }
3274
3275         if (!load_template.empty()) {
3276                 should_be_new = true;
3277                 template_name = load_template;
3278         }
3279
3280         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3281         session_path = ARDOUR_COMMAND_LINE::session_name;
3282
3283         if (!session_path.empty()) {
3284                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3285                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3286                                 /* session/snapshot file, change path to be dir */
3287                                 session_path = Glib::path_get_dirname (session_path);
3288                         }
3289                 }
3290         }
3291
3292         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3293
3294         _session_dialog = &session_dialog;
3295         while (ret != 0) {
3296
3297                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3298
3299                         /* if they named a specific statefile, use it, otherwise they are
3300                            just giving a session folder, and we want to use it as is
3301                            to find the session.
3302                         */
3303
3304                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3305
3306                         if (suffix != string::npos) {
3307                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3308                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3309                                 session_name = Glib::path_get_basename (session_name);
3310                         } else {
3311                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3312                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3313                         }
3314                 } else {
3315                         session_path = "";
3316                         session_name = "";
3317                         session_dialog.clear_given ();
3318                 }
3319
3320                 if (should_be_new || session_name.empty()) {
3321                         /* need the dialog to get info from user */
3322
3323                         cerr << "run dialog\n";
3324
3325                         switch (session_dialog.run()) {
3326                         case RESPONSE_ACCEPT:
3327                                 break;
3328                         case RESPONSE_NONE:
3329                                 /* this is used for async * app->ShouldLoad(). */
3330                                 continue; // while loop
3331                                 break;
3332                         default:
3333                                 if (quit_on_cancel) {
3334                                         ARDOUR_UI::finish ();
3335                                         Gtkmm2ext::Application::instance()->cleanup();
3336                                         ARDOUR::cleanup ();
3337                                         pthread_cancel_all ();
3338                                         return -1; // caller is responsible to call exit()
3339                                 } else {
3340                                         return ret;
3341                                 }
3342                         }
3343
3344                         session_dialog.hide ();
3345                 }
3346
3347                 /* if we run the startup dialog again, offer more than just "new session" */
3348
3349                 should_be_new = false;
3350
3351                 session_name = session_dialog.session_name (likely_new);
3352                 session_path = session_dialog.session_folder ();
3353
3354                 if (nsm) {
3355                         likely_new = true;
3356                 }
3357
3358                 if (!likely_new) {
3359                         int rv = ARDOUR::inflate_session (session_name,
3360                                         Config->get_default_session_parent_dir(), session_path, session_name);
3361                         if (rv < 0) {
3362                                 MessageDialog msg (session_dialog,
3363                                         string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
3364                                 msg.run ();
3365                                 continue;
3366                         }
3367                         else if (rv == 0) {
3368                                 session_dialog.set_provided_session (session_name, session_path);
3369                         }
3370                 }
3371
3372                 // XXX check archive, inflate
3373                 string::size_type suffix = session_name.find (statefile_suffix);
3374
3375                 if (suffix != string::npos) {
3376                         session_name = session_name.substr (0, suffix);
3377                 }
3378
3379                 /* this shouldn't happen, but we catch it just in case it does */
3380
3381                 if (session_name.empty()) {
3382                         continue;
3383                 }
3384
3385                 if (session_dialog.use_session_template()) {
3386                         template_name = session_dialog.session_template_name();
3387                         _session_is_new = true;
3388                 }
3389
3390                 if (session_name[0] == G_DIR_SEPARATOR ||
3391 #ifdef PLATFORM_WINDOWS
3392                    (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3393 #else
3394                    (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3395                    (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3396 #endif
3397                 )
3398                 {
3399
3400                         /* absolute path or cwd-relative path specified for session name: infer session folder
3401                            from what was given.
3402                         */
3403
3404                         session_path = Glib::path_get_dirname (session_name);
3405                         session_name = Glib::path_get_basename (session_name);
3406
3407                 } else {
3408
3409                         session_path = session_dialog.session_folder();
3410
3411                         char illegal = Session::session_name_is_legal (session_name);
3412
3413                         if (illegal) {
3414                                 MessageDialog msg (session_dialog,
3415                                                    string_compose (_("To ensure compatibility with various systems\n"
3416                                                                      "session names may not contain a '%1' character"),
3417                                                                    illegal));
3418                                 msg.run ();
3419                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3420                                 continue;
3421                         }
3422                 }
3423
3424                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3425
3426
3427                         if (likely_new && !nsm) {
3428
3429                                 std::string existing = Glib::build_filename (session_path, session_name);
3430
3431                                 if (!ask_about_loading_existing_session (existing)) {
3432                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3433                                         continue;
3434                                 }
3435                         }
3436
3437                         _session_is_new = false;
3438
3439                 } else {
3440
3441                         if (!likely_new) {
3442                                 pop_back_splash (session_dialog);
3443                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3444                                 msg.run ();
3445                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3446                                 continue;
3447                         }
3448
3449                         char illegal = Session::session_name_is_legal(session_name);
3450
3451                         if (illegal) {
3452                                 pop_back_splash (session_dialog);
3453                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3454                                                                                     "session names may not contain a '%1' character"), illegal));
3455                                 msg.run ();
3456                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3457                                 continue;
3458                         }
3459
3460                         _session_is_new = true;
3461                 }
3462
3463                 if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
3464
3465                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3466                         meta_session_setup (template_name.substr (11));
3467
3468                 } else if (likely_new && template_name.empty()) {
3469
3470                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3471
3472                 } else {
3473
3474                         ret = load_session (session_path, session_name, template_name);
3475
3476                         if (ret == -2) {
3477                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3478                                 exit (1);
3479                         }
3480
3481                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3482                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3483                                 exit (1);
3484                         }
3485
3486                         /* clear this to avoid endless attempts to load the
3487                            same session.
3488                         */
3489
3490                         ARDOUR_COMMAND_LINE::session_name = "";
3491                 }
3492         }
3493
3494         _session_dialog = NULL;
3495
3496         return ret;
3497 }
3498
3499 void
3500 ARDOUR_UI::close_session()
3501 {
3502         if (!check_audioengine (_main_window)) {
3503                 return;
3504         }
3505
3506         if (unload_session (true)) {
3507                 return;
3508         }
3509
3510         ARDOUR_COMMAND_LINE::session_name = "";
3511
3512         if (get_session_parameters (true, false)) {
3513                 exit (1);
3514         }
3515 }
3516
3517 /** @param snap_name Snapshot name (without .ardour suffix).
3518  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3519  */
3520 int
3521 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3522 {
3523         /* load_session calls flush_pending() which allows
3524          * GUI interaction and potentially loading another session
3525          * (that was easy via snapshot sidebar).
3526          * Recursing into load_session() from load_session() and recusive
3527          * event loops causes all kind of crashes.
3528          */
3529         assert (!session_load_in_progress);
3530         if (session_load_in_progress) {
3531                 return -1;
3532         }
3533         PBD::Unwinder<bool> lsu (session_load_in_progress, true);
3534
3535         Session *new_session;
3536         int unload_status;
3537         int retval = -1;
3538
3539         if (_session) {
3540                 unload_status = unload_session ();
3541
3542                 if (unload_status < 0) {
3543                         goto out;
3544                 } else if (unload_status > 0) {
3545                         retval = 0;
3546                         goto out;
3547                 }
3548         }
3549
3550         session_loaded = false;
3551
3552         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3553
3554         try {
3555                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3556         }
3557
3558         /* this one is special */
3559
3560         catch (AudioEngine::PortRegistrationFailure const& err) {
3561
3562                 MessageDialog msg (err.what(),
3563                                    true,
3564                                    Gtk::MESSAGE_INFO,
3565                                    Gtk::BUTTONS_CLOSE);
3566
3567                 msg.set_title (_("Port Registration Error"));
3568                 msg.set_secondary_text (_("Click the Close button to try again."));
3569                 msg.set_position (Gtk::WIN_POS_CENTER);
3570                 pop_back_splash (msg);
3571                 msg.present ();
3572
3573                 int response = msg.run ();
3574
3575                 msg.hide ();
3576
3577                 switch (response) {
3578                 case RESPONSE_CANCEL:
3579                         exit (1);
3580                 default:
3581                         break;
3582                 }
3583                 goto out;
3584         }
3585         catch (SessionException const& e) {
3586                 MessageDialog msg (string_compose(
3587                                            _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
3588                                            path, snap_name, e.what()),
3589                                    true,
3590                                    Gtk::MESSAGE_INFO,
3591                                    BUTTONS_OK);
3592
3593                 msg.set_title (_("Loading Error"));
3594                 msg.set_position (Gtk::WIN_POS_CENTER);
3595                 pop_back_splash (msg);
3596                 msg.present ();
3597
3598                 dump_errors (cerr);
3599
3600                 (void) msg.run ();
3601                 msg.hide ();
3602
3603                 goto out;
3604         }
3605         catch (...) {
3606
3607                 MessageDialog msg (string_compose(
3608                                            _("Session \"%1 (snapshot %2)\" did not load successfully."),
3609                                            path, snap_name),
3610                                    true,
3611                                    Gtk::MESSAGE_INFO,
3612                                    BUTTONS_OK);
3613
3614                 msg.set_title (_("Loading Error"));
3615                 msg.set_position (Gtk::WIN_POS_CENTER);
3616                 pop_back_splash (msg);
3617                 msg.present ();
3618
3619                 dump_errors (cerr);
3620
3621                 (void) msg.run ();
3622                 msg.hide ();
3623
3624                 goto out;
3625         }
3626
3627         {
3628                 list<string> const u = new_session->unknown_processors ();
3629                 if (!u.empty()) {
3630                         MissingPluginDialog d (_session, u);
3631                         d.run ();
3632                 }
3633         }
3634
3635         if (!new_session->writable()) {
3636                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3637                                    true,
3638                                    Gtk::MESSAGE_INFO,
3639                                    BUTTONS_OK);
3640
3641                 msg.set_title (_("Read-only Session"));
3642                 msg.set_position (Gtk::WIN_POS_CENTER);
3643                 pop_back_splash (msg);
3644                 msg.present ();
3645                 (void) msg.run ();
3646                 msg.hide ();
3647         }
3648
3649
3650         /* Now the session been created, add the transport controls */
3651         new_session->add_controllable(roll_controllable);
3652         new_session->add_controllable(stop_controllable);
3653         new_session->add_controllable(goto_start_controllable);
3654         new_session->add_controllable(goto_end_controllable);
3655         new_session->add_controllable(auto_loop_controllable);
3656         new_session->add_controllable(play_selection_controllable);
3657         new_session->add_controllable(rec_controllable);
3658
3659         set_session (new_session);
3660
3661         session_loaded = true;
3662
3663         if (_session) {
3664                 _session->set_clean ();
3665         }
3666
3667 #ifdef WINDOWS_VST_SUPPORT
3668         fst_stop_threading();
3669 #endif
3670
3671         {
3672                 Timers::TimerSuspender t;
3673                 flush_pending (10);
3674         }
3675
3676 #ifdef WINDOWS_VST_SUPPORT
3677         fst_start_threading();
3678 #endif
3679         retval = 0;
3680
3681         if (!mix_template.empty ()) {
3682                 /* if mix_template is given, assume this is a new session */
3683                 string metascript = Glib::build_filename (mix_template, "template.lua");
3684                 meta_session_setup (metascript);
3685         }
3686
3687
3688   out:
3689         /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
3690          * which is queued by set_session().
3691          * If session-loading fails we hide it explicitly.
3692          * This covers both cases in a central place.
3693          */
3694         if (retval) {
3695                 hide_splash ();
3696         }
3697         return retval;
3698 }
3699
3700 int
3701 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile* bus_profile)
3702 {
3703         Session *new_session;
3704         int x;
3705
3706         session_loaded = false;
3707         x = unload_session ();
3708
3709         if (x < 0) {
3710                 return -1;
3711         } else if (x > 0) {
3712                 return 0;
3713         }
3714
3715         _session_is_new = true;
3716
3717         try {
3718                 new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
3719         }
3720
3721         catch (SessionException const& e) {
3722                 cerr << "Here are the errors associated with this failed session:\n";
3723                 dump_errors (cerr);
3724                 cerr << "---------\n";
3725                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3726                 msg.set_title (_("Loading Error"));
3727                 msg.set_position (Gtk::WIN_POS_CENTER);
3728                 pop_back_splash (msg);
3729                 msg.run ();
3730                 return -1;
3731         }
3732         catch (...) {
3733                 cerr << "Here are the errors associated with this failed session:\n";
3734                 dump_errors (cerr);
3735                 cerr << "---------\n";
3736                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3737                 msg.set_title (_("Loading Error"));
3738                 msg.set_position (Gtk::WIN_POS_CENTER);
3739                 pop_back_splash (msg);
3740                 msg.run ();
3741                 return -1;
3742         }
3743
3744         /* Give the new session the default GUI state, if such things exist */
3745
3746         XMLNode* n;
3747         n = Config->instant_xml (X_("Editor"));
3748         if (n) {
3749                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3750                 new_session->add_instant_xml (*n, false);
3751         }
3752         n = Config->instant_xml (X_("Mixer"));
3753         if (n) {
3754                 new_session->add_instant_xml (*n, false);
3755         }
3756
3757         n = Config->instant_xml (X_("Preferences"));
3758         if (n) {
3759                 new_session->add_instant_xml (*n, false);
3760         }
3761
3762         /* Put the playhead at 0 and scroll fully left */
3763         n = new_session->instant_xml (X_("Editor"));
3764         if (n) {
3765                 n->set_property (X_("playhead"), X_("0"));
3766                 n->set_property (X_("left-frame"), X_("0"));
3767         }
3768
3769         set_session (new_session);
3770
3771         session_loaded = true;
3772
3773         new_session->save_state(new_session->name());
3774
3775         return 0;
3776 }
3777
3778
3779 static void _lua_print (std::string s) {
3780 #ifndef NDEBUG
3781         std::cout << "LuaInstance: " << s << "\n";
3782 #endif
3783         PBD::info << "LuaInstance: " << s << endmsg;
3784 }
3785
3786 std::map<std::string, std::string>
3787 ARDOUR_UI::route_setup_info (const std::string& script_path)
3788 {
3789         std::map<std::string, std::string> rv;
3790
3791         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3792                 return rv;
3793         }
3794
3795         LuaState lua;
3796         lua.Print.connect (&_lua_print);
3797         lua.sandbox (true);
3798
3799         lua_State* L = lua.getState();
3800         LuaInstance::register_classes (L);
3801         LuaBindings::set_session (L, _session);
3802         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3803         lua_setglobal (L, "Editor");
3804
3805         lua.do_command ("function ardour () end");
3806         lua.do_file (script_path);
3807
3808         try {
3809                 luabridge::LuaRef fn = luabridge::getGlobal (L, "route_setup");
3810                 if (!fn.isFunction ()) {
3811                         return rv;
3812                 }
3813                 luabridge::LuaRef rs = fn ();
3814                 if (!rs.isTable ()) {
3815                         return rv;
3816                 }
3817                 for (luabridge::Iterator i(rs); !i.isNil (); ++i) {
3818                         if (!i.key().isString()) {
3819                                 continue;
3820                         }
3821                         std::string key = i.key().tostring();
3822                         if (i.value().isString() || i.value().isNumber() || i.value().isBoolean()) {
3823                                 rv[key] = i.value().tostring();
3824                         }
3825                 }
3826         } catch (luabridge::LuaException const& e) {
3827                 cerr << "LuaException:" << e.what () << endl;
3828         } catch (...) { }
3829         return rv;
3830 }
3831
3832 void
3833 ARDOUR_UI::meta_route_setup (const std::string& script_path)
3834 {
3835         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3836                 return;
3837         }
3838         assert (add_route_dialog);
3839
3840         int count;
3841         if ((count = add_route_dialog->count()) <= 0) {
3842                 return;
3843         }
3844
3845         LuaState lua;
3846         lua.Print.connect (&_lua_print);
3847         lua.sandbox (true);
3848
3849         lua_State* L = lua.getState();
3850         LuaInstance::register_classes (L);
3851         LuaBindings::set_session (L, _session);
3852         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3853         lua_setglobal (L, "Editor");
3854
3855         lua.do_command ("function ardour () end");
3856         lua.do_file (script_path);
3857
3858         luabridge::LuaRef args (luabridge::newTable (L));
3859
3860         args["name"]       = add_route_dialog->name_template ();
3861         args["insert_at"]  = translate_order (add_route_dialog->insert_at());
3862         args["group"]      = add_route_dialog->route_group ();
3863         args["strict_io"]  = add_route_dialog->use_strict_io ();
3864         args["instrument"] = add_route_dialog->requested_instrument ();
3865         args["track_mode"] = add_route_dialog->mode ();
3866         args["channels"]   = add_route_dialog->channel_count ();
3867         args["how_many"]   = count;
3868
3869         try {
3870                 luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
3871                 if (fn.isFunction()) {
3872                         fn (args)();
3873                 }
3874         } catch (luabridge::LuaException const& e) {
3875                 cerr << "LuaException:" << e.what () << endl;
3876         } catch (...) {
3877                 display_insufficient_ports_message ();
3878         }
3879 }
3880
3881 void
3882 ARDOUR_UI::meta_session_setup (const std::string& script_path)
3883 {
3884         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3885                 return;
3886         }
3887
3888         LuaState lua;
3889         lua.Print.connect (&_lua_print);
3890         lua.sandbox (true);
3891
3892         lua_State* L = lua.getState();
3893         LuaInstance::register_classes (L);
3894         LuaBindings::set_session (L, _session);
3895         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3896         lua_setglobal (L, "Editor");
3897
3898         lua.do_command ("function ardour () end");
3899         lua.do_file (script_path);
3900
3901         try {
3902                 luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
3903                 if (fn.isFunction()) {
3904                         fn ()();
3905                 }
3906         } catch (luabridge::LuaException const& e) {
3907                 cerr << "LuaException:" << e.what () << endl;
3908         } catch (...) {
3909                 display_insufficient_ports_message ();
3910         }
3911 }
3912
3913 void
3914 ARDOUR_UI::launch_chat ()
3915 {
3916         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3917
3918         dialog.set_title (_("About the Chat"));
3919         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."));
3920
3921         switch (dialog.run()) {
3922         case RESPONSE_OK:
3923                 open_uri("http://webchat.freenode.net/?channels=ardour");
3924                 break;
3925         default:
3926                 break;
3927         }
3928 }
3929
3930 void
3931 ARDOUR_UI::launch_manual ()
3932 {
3933         PBD::open_uri (Config->get_tutorial_manual_url());
3934 }
3935
3936 void
3937 ARDOUR_UI::launch_reference ()
3938 {
3939         PBD::open_uri (Config->get_reference_manual_url());
3940 }
3941
3942 void
3943 ARDOUR_UI::launch_tracker ()
3944 {
3945         PBD::open_uri ("http://tracker.ardour.org");
3946 }
3947
3948 void
3949 ARDOUR_UI::launch_subscribe ()
3950 {
3951         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3952 }
3953
3954 void
3955 ARDOUR_UI::launch_cheat_sheet ()
3956 {
3957 #ifdef __APPLE__
3958         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3959 #else
3960         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3961 #endif
3962 }
3963
3964 void
3965 ARDOUR_UI::launch_website ()
3966 {
3967         PBD::open_uri ("http://ardour.org");
3968 }
3969
3970 void
3971 ARDOUR_UI::launch_website_dev ()
3972 {
3973         PBD::open_uri ("http://ardour.org/development.html");
3974 }
3975
3976 void
3977 ARDOUR_UI::launch_forums ()
3978 {
3979         PBD::open_uri ("https://community.ardour.org/forums");
3980 }
3981
3982 void
3983 ARDOUR_UI::launch_howto_report ()
3984 {
3985         PBD::open_uri ("http://ardour.org/reporting_bugs");
3986 }
3987
3988 void
3989 ARDOUR_UI::loading_message (const std::string& msg)
3990 {
3991         if (ARDOUR_COMMAND_LINE::no_splash) {
3992                 return;
3993         }
3994
3995         if (!splash) {
3996                 show_splash ();
3997         }
3998
3999         splash->message (msg);
4000 }
4001
4002 void
4003 ARDOUR_UI::show_splash ()
4004 {
4005         if (splash == 0) {
4006                 try {
4007                         splash = new Splash;
4008                 } catch (...) {
4009                         return;
4010                 }
4011         }
4012
4013         splash->display ();
4014 }
4015
4016 void
4017 ARDOUR_UI::hide_splash ()
4018 {
4019         delete splash;
4020         splash = 0;
4021 }
4022
4023 void
4024 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
4025 {
4026         size_t removed;
4027
4028         removed = rep.paths.size();
4029
4030         if (removed == 0) {
4031                 MessageDialog msgd (_main_window,
4032                                     _("No files were ready for clean-up"),
4033                                     true,
4034                                     Gtk::MESSAGE_INFO,
4035                                     Gtk::BUTTONS_OK);
4036                 msgd.set_title (_("Clean-up"));
4037                 msgd.set_secondary_text (_("If this seems surprising, \n\
4038 check for any existing snapshots.\n\
4039 These may still include regions that\n\
4040 require some unused files to continue to exist."));
4041
4042                 msgd.run ();
4043                 return;
4044         }
4045
4046         ArdourDialog results (_("Clean-up"), true, false);
4047
4048         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
4049                 CleanupResultsModelColumns() {
4050                         add (visible_name);
4051                         add (fullpath);
4052                 }
4053                 Gtk::TreeModelColumn<std::string> visible_name;
4054                 Gtk::TreeModelColumn<std::string> fullpath;
4055         };
4056
4057
4058         CleanupResultsModelColumns results_columns;
4059         Glib::RefPtr<Gtk::ListStore> results_model;
4060         Gtk::TreeView results_display;
4061
4062         results_model = ListStore::create (results_columns);
4063         results_display.set_model (results_model);
4064         results_display.append_column (list_title, results_columns.visible_name);
4065
4066         results_display.set_name ("CleanupResultsList");
4067         results_display.set_headers_visible (true);
4068         results_display.set_headers_clickable (false);
4069         results_display.set_reorderable (false);
4070
4071         Gtk::ScrolledWindow list_scroller;
4072         Gtk::Label txt;
4073         Gtk::VBox dvbox;
4074         Gtk::HBox dhbox;  // the hbox for the image and text
4075         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
4076         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
4077
4078         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
4079
4080         const string dead_directory = _session->session_directory().dead_path();
4081
4082         /* subst:
4083            %1 - number of files removed
4084            %2 - location of "dead"
4085            %3 - size of files affected
4086            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
4087         */
4088
4089         const char* bprefix;
4090         double space_adjusted = 0;
4091
4092         if (rep.space < 1000) {
4093                 bprefix = X_("");
4094                 space_adjusted = rep.space;
4095         } else if (rep.space < 1000000) {
4096                 bprefix = _("kilo");
4097                 space_adjusted = floorf((float)rep.space / 1000.0);
4098         } else if (rep.space < 1000000 * 1000) {
4099                 bprefix = _("mega");
4100                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
4101         } else {
4102                 bprefix = _("giga");
4103                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
4104         }
4105
4106         if (msg_delete) {
4107                 txt.set_markup (string_compose (P_("\
4108 The following file was deleted from %2,\n\
4109 releasing %3 %4bytes of disk space", "\
4110 The following %1 files were deleted from %2,\n\
4111 releasing %3 %4bytes of disk space", removed),
4112                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4113         } else {
4114                 txt.set_markup (string_compose (P_("\
4115 The following file was not in use and \n\
4116 has been moved to: %2\n\n\
4117 After a restart of %5\n\n\
4118 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4119 will release an additional %3 %4bytes of disk space.\n", "\
4120 The following %1 files were not in use and \n\
4121 have been moved to: %2\n\n\
4122 After a restart of %5\n\n\
4123 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4124 will release an additional %3 %4bytes of disk space.\n", removed),
4125                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4126         }
4127
4128         dhbox.pack_start (*dimage, true, false, 5);
4129         dhbox.pack_start (txt, true, false, 5);
4130
4131         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
4132                 TreeModel::Row row = *(results_model->append());
4133                 row[results_columns.visible_name] = *i;
4134                 row[results_columns.fullpath] = *i;
4135         }
4136
4137         list_scroller.add (results_display);
4138         list_scroller.set_size_request (-1, 150);
4139         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
4140
4141         dvbox.pack_start (dhbox, true, false, 5);
4142         dvbox.pack_start (list_scroller, true, false, 5);
4143         ddhbox.pack_start (dvbox, true, false, 5);
4144
4145         results.get_vbox()->pack_start (ddhbox, true, false, 5);
4146         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
4147         results.set_default_response (RESPONSE_CLOSE);
4148         results.set_position (Gtk::WIN_POS_MOUSE);
4149
4150         results_display.show();
4151         list_scroller.show();
4152         txt.show();
4153         dvbox.show();
4154         dhbox.show();
4155         ddhbox.show();
4156         dimage->show();
4157
4158         //results.get_vbox()->show();
4159         results.set_resizable (false);
4160
4161         results.run ();
4162
4163 }
4164
4165 void
4166 ARDOUR_UI::cleanup ()
4167 {
4168         if (_session == 0) {
4169                 /* shouldn't happen: menu item is insensitive */
4170                 return;
4171         }
4172
4173
4174         MessageDialog checker (_("Are you sure you want to clean-up?"),
4175                                 true,
4176                                 Gtk::MESSAGE_QUESTION,
4177                                 Gtk::BUTTONS_NONE);
4178
4179         checker.set_title (_("Clean-up"));
4180
4181         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
4182 ALL undo/redo information will be lost if you clean-up.\n\
4183 Clean-up will move all unused files to a \"dead\" location."));
4184
4185         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
4186         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
4187         checker.set_default_response (RESPONSE_CANCEL);
4188
4189         checker.set_name (_("CleanupDialog"));
4190         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
4191         checker.set_position (Gtk::WIN_POS_MOUSE);
4192
4193         switch (checker.run()) {
4194         case RESPONSE_ACCEPT:
4195                 break;
4196         default:
4197                 return;
4198         }
4199
4200         ARDOUR::CleanupReport rep;
4201
4202         editor->prepare_for_cleanup ();
4203
4204         /* do not allow flush until a session is reloaded */
4205
4206         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
4207         if (act) {
4208                 act->set_sensitive (false);
4209         }
4210
4211         if (_session->cleanup_sources (rep)) {
4212                 editor->finish_cleanup ();
4213                 return;
4214         }
4215
4216         editor->finish_cleanup ();
4217
4218         checker.hide();
4219         display_cleanup_results (rep, _("Cleaned Files"), false);
4220 }
4221
4222 void
4223 ARDOUR_UI::flush_trash ()
4224 {
4225         if (_session == 0) {
4226                 /* shouldn't happen: menu item is insensitive */
4227                 return;
4228         }
4229
4230         ARDOUR::CleanupReport rep;
4231
4232         if (_session->cleanup_trash_sources (rep)) {
4233                 return;
4234         }
4235
4236         display_cleanup_results (rep, _("deleted file"), true);
4237 }
4238
4239 void
4240 ARDOUR_UI::cleanup_peakfiles ()
4241 {
4242         if (_session == 0) {
4243                 /* shouldn't happen: menu item is insensitive */
4244                 return;
4245         }
4246
4247         if (! _session->can_cleanup_peakfiles ()) {
4248                 return;
4249         }
4250
4251         // get all region-views in this session
4252         RegionSelection rs;
4253         TrackViewList empty;
4254         empty.clear();
4255         editor->get_regions_after(rs, (samplepos_t) 0, empty);
4256         std::list<RegionView*> views = rs.by_layer();
4257
4258         // remove displayed audio-region-views waveforms
4259         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4260                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4261                 if (!arv) { continue ; }
4262                 arv->delete_waves();
4263         }
4264
4265         // cleanup peak files:
4266         // - stop pending peakfile threads
4267         // - close peakfiles if any
4268         // - remove peak dir in session
4269         // - setup peakfiles (background thread)
4270         _session->cleanup_peakfiles ();
4271
4272         // re-add waves to ARV
4273         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4274                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4275                 if (!arv) { continue ; }
4276                 arv->create_waves();
4277         }
4278 }
4279
4280 PresentationInfo::order_t
4281 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
4282 {
4283         if (editor->get_selection().tracks.empty()) {
4284                 return place == RouteDialogs::First ? 0 : PresentationInfo::max_order;
4285         }
4286
4287         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
4288
4289         /*
4290           we want the new routes to have their order keys set starting from
4291           the highest order key in the selection + 1 (if available).
4292         */
4293
4294         if (place == RouteDialogs::AfterSelection) {
4295                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
4296                 if (rtav) {
4297                         order_hint = rtav->route()->presentation_info().order();
4298                         order_hint++;
4299                 }
4300         } else if (place == RouteDialogs::BeforeSelection) {
4301                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
4302                 if (rtav) {
4303                         order_hint = rtav->route()->presentation_info().order();
4304                 }
4305         } else if (place == RouteDialogs::First) {
4306                 order_hint = 0;
4307         } else {
4308                 /* leave order_hint at max_order */
4309         }
4310
4311         return order_hint;
4312 }
4313
4314 void
4315 ARDOUR_UI::start_duplicate_routes ()
4316 {
4317         if (!duplicate_routes_dialog) {
4318                 duplicate_routes_dialog = new DuplicateRouteDialog;
4319         }
4320
4321         if (duplicate_routes_dialog->restart (_session)) {
4322                 return;
4323         }
4324
4325         duplicate_routes_dialog->present ();
4326 }
4327
4328 void
4329 ARDOUR_UI::add_route ()
4330 {
4331         if (!add_route_dialog.get (false)) {
4332                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
4333         }
4334
4335         if (!_session) {
4336                 return;
4337         }
4338
4339         if (add_route_dialog->is_visible()) {
4340                 /* we're already doing this */
4341                 return;
4342         }
4343
4344         add_route_dialog->set_position (WIN_POS_MOUSE);
4345         add_route_dialog->present();
4346 }
4347
4348 void
4349 ARDOUR_UI::add_route_dialog_response (int r)
4350 {
4351         if (!_session) {
4352                 warning << _("You cannot add tracks or busses without a session already loaded.") << endmsg;
4353                 return;
4354         }
4355
4356         int count;
4357
4358         switch (r) {
4359         case AddRouteDialog::Add:
4360                 add_route_dialog->reset_name_edited ();
4361                 break;
4362         case AddRouteDialog::AddAndClose:
4363                 add_route_dialog->ArdourDialog::on_response (r);
4364                 break;
4365         default:
4366                 add_route_dialog->ArdourDialog::on_response (r);
4367                 return;
4368         }
4369
4370         std::string template_path = add_route_dialog->get_template_path();
4371         if (!template_path.empty() && template_path.substr (0, 11) == "urn:ardour:") {
4372                 meta_route_setup (template_path.substr (11));
4373                 return;
4374         }
4375
4376         if ((count = add_route_dialog->count()) <= 0) {
4377                 return;
4378         }
4379
4380         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
4381         const string name_template = add_route_dialog->name_template ();
4382         DisplaySuspender ds;
4383
4384         if (!template_path.empty ()) {
4385                 if (add_route_dialog->name_template_is_default ()) {
4386                         _session->new_route_from_template (count, order, template_path, string ());
4387                 } else {
4388                         _session->new_route_from_template (count, order, template_path, name_template);
4389                 }
4390                 return;
4391         }
4392
4393         ChanCount input_chan= add_route_dialog->channels ();
4394         ChanCount output_chan;
4395         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4396         RouteGroup* route_group = add_route_dialog->route_group ();
4397         AutoConnectOption oac = Config->get_output_auto_connect();
4398         bool strict_io = add_route_dialog->use_strict_io ();
4399
4400         if (oac & AutoConnectMaster) {
4401                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4402                 output_chan.set (DataType::MIDI, 0);
4403         } else {
4404                 output_chan = input_chan;
4405         }
4406
4407         /* XXX do something with name template */
4408
4409         Session::ProcessorChangeBlocker pcb (_session);
4410
4411         switch (add_route_dialog->type_wanted()) {
4412         case AddRouteDialog::AudioTrack:
4413                 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);
4414                 break;
4415         case AddRouteDialog::MidiTrack:
4416                 session_add_midi_route (true, route_group, count, name_template, strict_io, instrument, 0, order);
4417                 break;
4418         case AddRouteDialog::MixedTrack:
4419                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4420                 break;
4421         case AddRouteDialog::AudioBus:
4422                 session_add_audio_route (false, input_chan.n_audio(), output_chan.n_audio(), ARDOUR::Normal, route_group, count, name_template, strict_io, order);
4423                 break;
4424         case AddRouteDialog::MidiBus:
4425                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4426                 break;
4427         case AddRouteDialog::VCAMaster:
4428                 _session->vca_manager().create_vca (count, name_template);
4429                 break;
4430         case AddRouteDialog::ListenBus:
4431                 session_add_listen_bus (count, name_template);
4432                 break;
4433         }
4434 }
4435
4436 void
4437 ARDOUR_UI::stop_video_server (bool ask_confirm)
4438 {
4439         if (!video_server_process && ask_confirm) {
4440                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4441         }
4442         if (video_server_process) {
4443                 if(ask_confirm) {
4444                         ArdourDialog confirm (_("Stop Video-Server"), true);
4445                         Label m (_("Do you really want to stop the Video Server?"));
4446                         confirm.get_vbox()->pack_start (m, true, true);
4447                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4448                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4449                         confirm.show_all ();
4450                         if (confirm.run() == RESPONSE_CANCEL) {
4451                                 return;
4452                         }
4453                 }
4454                 delete video_server_process;
4455                 video_server_process =0;
4456         }
4457 }
4458
4459 void
4460 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4461 {
4462   ARDOUR_UI::start_video_server( float_window, true);
4463 }
4464
4465 bool
4466 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4467 {
4468         if (!_session) {
4469                 return false;
4470         }
4471         if (popup_msg) {
4472                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4473                         if (video_server_process) {
4474                                 popup_error(_("The Video Server is already started."));
4475                         } else {
4476                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4477                         }
4478                 }
4479         }
4480
4481         int firsttime = 0;
4482         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4483                 if (firsttime++) {
4484                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4485                 }
4486                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4487                 if (float_window) {
4488                         video_server_dialog->set_transient_for (*float_window);
4489                 }
4490
4491                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4492                         video_server_dialog->hide();
4493                 } else {
4494                         ResponseType r = (ResponseType) video_server_dialog->run ();
4495                         video_server_dialog->hide();
4496                         if (r != RESPONSE_ACCEPT) { return false; }
4497                         if (video_server_dialog->show_again()) {
4498                                 Config->set_show_video_server_dialog(false);
4499                         }
4500                 }
4501
4502                 std::string icsd_exec = video_server_dialog->get_exec_path();
4503                 std::string icsd_docroot = video_server_dialog->get_docroot();
4504 #ifndef PLATFORM_WINDOWS
4505                 if (icsd_docroot.empty()) {
4506                         icsd_docroot = VideoUtils::video_get_docroot (Config);
4507                 }
4508 #endif
4509
4510                 GStatBuf sb;
4511 #ifdef PLATFORM_WINDOWS
4512                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4513                         /* OK, allow all drive letters */
4514                 } else
4515 #endif
4516                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4517                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4518                         continue;
4519                 }
4520 #ifndef PLATFORM_WINDOWS
4521                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4522                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4523                         warning << _("Given Video Server is not an executable file.") << endmsg;
4524                         continue;
4525                 }
4526 #else
4527                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4528                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4529                         warning << _("Given Video Server is not an executable file.") << endmsg;
4530                         continue;
4531                 }
4532 #endif
4533
4534                 char **argp;
4535                 argp=(char**) calloc(9,sizeof(char*));
4536                 argp[0] = strdup(icsd_exec.c_str());
4537                 argp[1] = strdup("-P");
4538                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4539                 argp[3] = strdup("-p");
4540                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4541                 argp[5] = strdup("-C");
4542                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4543                 argp[7] = strdup(icsd_docroot.c_str());
4544                 argp[8] = 0;
4545                 stop_video_server();
4546
4547 #ifdef PLATFORM_WINDOWS
4548                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4549                         /* OK, allow all drive letters */
4550                 } else
4551 #endif
4552                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4553                         Config->set_video_advanced_setup(false);
4554                 } else {
4555                         std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/";
4556                         Config->set_video_server_url(url_str);
4557                         Config->set_video_server_docroot(icsd_docroot);
4558                         Config->set_video_advanced_setup(true);
4559                 }
4560
4561                 if (video_server_process) {
4562                         delete video_server_process;
4563                 }
4564
4565                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4566                 if (video_server_process->start()) {
4567                         warning << _("Cannot launch the video-server") << endmsg;
4568                         continue;
4569                 }
4570                 int timeout = 120; // 6 sec
4571                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4572                         Glib::usleep (50000);
4573                         gui_idle_handler();
4574                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4575                 }
4576                 if (timeout <= 0) {
4577                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4578                 } else {
4579                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4580                                 delete video_server_process;
4581                                 video_server_process = 0;
4582                         }
4583                 }
4584         }
4585         return true;
4586 }
4587
4588 void
4589 ARDOUR_UI::add_video (Gtk::Window* float_window)
4590 {
4591         if (!_session) {
4592                 return;
4593         }
4594
4595         if (!start_video_server(float_window, false)) {
4596                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4597                 return;
4598         }
4599
4600         if (float_window) {
4601                 add_video_dialog->set_transient_for (*float_window);
4602         }
4603
4604         if (add_video_dialog->is_visible()) {
4605                 /* we're already doing this */
4606                 return;
4607         }
4608
4609         ResponseType r = (ResponseType) add_video_dialog->run ();
4610         add_video_dialog->hide();
4611         if (r != RESPONSE_ACCEPT) { return; }
4612
4613         bool local_file, orig_local_file;
4614         std::string path = add_video_dialog->file_name(local_file);
4615
4616         std::string orig_path = path;
4617         orig_local_file = local_file;
4618
4619         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4620
4621         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4622                 warning << string_compose(_("could not open %1"), path) << endmsg;
4623                 return;
4624         }
4625         if (!local_file && path.length() == 0) {
4626                 warning << _("no video-file selected") << endmsg;
4627                 return;
4628         }
4629
4630         std::string audio_from_video;
4631         bool detect_ltc = false;
4632
4633         switch (add_video_dialog->import_option()) {
4634                 case VTL_IMPORT_TRANSCODE:
4635                         {
4636                                 TranscodeVideoDialog *transcode_video_dialog;
4637                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4638                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4639                                 transcode_video_dialog->hide();
4640                                 if (r != RESPONSE_ACCEPT) {
4641                                         delete transcode_video_dialog;
4642                                         return;
4643                                 }
4644
4645                                 audio_from_video = transcode_video_dialog->get_audiofile();
4646
4647                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4648                                         detect_ltc = true;
4649                                 }
4650                                 else if (!audio_from_video.empty()) {
4651                                         editor->embed_audio_from_video(
4652                                                         audio_from_video,
4653                                                         video_timeline->get_offset(),
4654                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4655                                                         );
4656                                 }
4657                                 switch (transcode_video_dialog->import_option()) {
4658                                         case VTL_IMPORT_TRANSCODED:
4659                                                 path = transcode_video_dialog->get_filename();
4660                                                 local_file = true;
4661                                                 break;
4662                                         case VTL_IMPORT_REFERENCE:
4663                                                 break;
4664                                         default:
4665                                                 delete transcode_video_dialog;
4666                                                 return;
4667                                 }
4668                                 delete transcode_video_dialog;
4669                         }
4670                         break;
4671                 default:
4672                 case VTL_IMPORT_NONE:
4673                         break;
4674         }
4675
4676         /* strip _session->session_directory().video_path() from video file if possible */
4677         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4678                  path=path.substr(_session->session_directory().video_path().size());
4679                  if (path.at(0) == G_DIR_SEPARATOR) {
4680                          path=path.substr(1);
4681                  }
4682         }
4683
4684         video_timeline->set_update_session_fps(auto_set_session_fps);
4685
4686         if (video_timeline->video_file_info(path, local_file)) {
4687                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4688                 node->set_property (X_("Filename"), path);
4689                 node->set_property (X_("AutoFPS"), auto_set_session_fps);
4690                 node->set_property (X_("LocalFile"), local_file);
4691                 if (orig_local_file) {
4692                         node->set_property (X_("OriginalVideoFile"), orig_path);
4693                 } else {
4694                         node->remove_property (X_("OriginalVideoFile"));
4695                 }
4696                 _session->add_extra_xml (*node);
4697                 _session->set_dirty ();
4698
4699                 if (!audio_from_video.empty() && detect_ltc) {
4700                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4701
4702                         try {
4703                                 /* TODO ask user about TV standard (LTC alignment if any) */
4704                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4705                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4706
4707                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC samples to decode*/ 15);
4708
4709                                 /* TODO seek near end of file, and read LTC until end.
4710                                  * if it fails to find any LTC samples, scan complete file
4711                                  *
4712                                  * calculate drift of LTC compared to video-duration,
4713                                  * ask user for reference (timecode from start/mid/end)
4714                                  */
4715                         } catch (...) {
4716                                 // LTCFileReader will have written error messages
4717                         }
4718
4719                         ::g_unlink(audio_from_video.c_str());
4720
4721                         if (ltc_seq.size() == 0) {
4722                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4723                         } else {
4724                                 /* the very first TC in the file is somteimes not aligned properly */
4725                                 int i = ltc_seq.size() -1;
4726                                 ARDOUR::sampleoffset_t video_start_offset =
4727                                         _session->nominal_sample_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4728                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4729                                 video_timeline->set_offset(video_start_offset);
4730                         }
4731                 }
4732
4733                 _session->maybe_update_session_range(
4734                         std::max(video_timeline->get_offset(), (ARDOUR::sampleoffset_t) 0),
4735                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::sampleoffset_t) 0));
4736
4737
4738                 if (add_video_dialog->launch_xjadeo() && local_file) {
4739                         editor->set_xjadeo_sensitive(true);
4740                         editor->toggle_xjadeo_proc(1);
4741                 } else {
4742                         editor->toggle_xjadeo_proc(0);
4743                 }
4744                 editor->toggle_ruler_video(true);
4745         }
4746 }
4747
4748 void
4749 ARDOUR_UI::remove_video ()
4750 {
4751         video_timeline->close_session();
4752         editor->toggle_ruler_video(false);
4753
4754         /* reset state */
4755         video_timeline->set_offset_locked(false);
4756         video_timeline->set_offset(0);
4757
4758         /* delete session state */
4759         XMLNode* node = new XMLNode(X_("Videotimeline"));
4760         _session->add_extra_xml(*node);
4761         node = new XMLNode(X_("Videomonitor"));
4762         _session->add_extra_xml(*node);
4763         node = new XMLNode(X_("Videoexport"));
4764         _session->add_extra_xml(*node);
4765         stop_video_server();
4766 }
4767
4768 void
4769 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4770 {
4771         if (localcacheonly) {
4772                 video_timeline->vmon_update();
4773         } else {
4774                 video_timeline->flush_cache();
4775         }
4776         editor->queue_visual_videotimeline_update();
4777 }
4778
4779 void
4780 ARDOUR_UI::export_video (bool range)
4781 {
4782         if (ARDOUR::Config->get_show_video_export_info()) {
4783                 ExportVideoInfobox infobox (_session);
4784                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4785                 if (infobox.show_again()) {
4786                         ARDOUR::Config->set_show_video_export_info(false);
4787                 }
4788                 switch (rv) {
4789                         case GTK_RESPONSE_YES:
4790                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4791                                 break;
4792                         default:
4793                                 break;
4794                 }
4795         }
4796         export_video_dialog->set_session (_session);
4797         export_video_dialog->apply_state(editor->get_selection().time, range);
4798         export_video_dialog->run ();
4799         export_video_dialog->hide ();
4800 }
4801
4802 XMLNode*
4803 ARDOUR_UI::preferences_settings () const
4804 {
4805         XMLNode* node = 0;
4806
4807         if (_session) {
4808                 node = _session->instant_xml(X_("Preferences"));
4809         } else {
4810                 node = Config->instant_xml(X_("Preferences"));
4811         }
4812
4813         if (!node) {
4814                 node = new XMLNode (X_("Preferences"));
4815         }
4816
4817         return node;
4818 }
4819
4820 XMLNode*
4821 ARDOUR_UI::mixer_settings () const
4822 {
4823         XMLNode* node = 0;
4824
4825         if (_session) {
4826                 node = _session->instant_xml(X_("Mixer"));
4827         } else {
4828                 node = Config->instant_xml(X_("Mixer"));
4829         }
4830
4831         if (!node) {
4832                 node = new XMLNode (X_("Mixer"));
4833         }
4834
4835         return node;
4836 }
4837
4838 XMLNode*
4839 ARDOUR_UI::main_window_settings () const
4840 {
4841         XMLNode* node = 0;
4842
4843         if (_session) {
4844                 node = _session->instant_xml(X_("Main"));
4845         } else {
4846                 node = Config->instant_xml(X_("Main"));
4847         }
4848
4849         if (!node) {
4850                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4851                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4852                 }
4853         }
4854
4855         if (!node) {
4856                 node = new XMLNode (X_("Main"));
4857         }
4858
4859         return node;
4860 }
4861
4862 XMLNode*
4863 ARDOUR_UI::editor_settings () const
4864 {
4865         XMLNode* node = 0;
4866
4867         if (_session) {
4868                 node = _session->instant_xml(X_("Editor"));
4869         } else {
4870                 node = Config->instant_xml(X_("Editor"));
4871         }
4872
4873         if (!node) {
4874                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4875                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4876                 }
4877         }
4878
4879         if (!node) {
4880                 node = new XMLNode (X_("Editor"));
4881         }
4882
4883         return node;
4884 }
4885
4886 XMLNode*
4887 ARDOUR_UI::keyboard_settings () const
4888 {
4889         XMLNode* node = 0;
4890
4891         node = Config->extra_xml(X_("Keyboard"));
4892
4893         if (!node) {
4894                 node = new XMLNode (X_("Keyboard"));
4895         }
4896
4897         return node;
4898 }
4899
4900 void
4901 ARDOUR_UI::create_xrun_marker (samplepos_t where)
4902 {
4903         if (_session) {
4904                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark, 0);
4905                 _session->locations()->add (location);
4906         }
4907 }
4908
4909 void
4910 ARDOUR_UI::halt_on_xrun_message ()
4911 {
4912         cerr << "HALT on xrun\n";
4913         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4914         msg.run ();
4915 }
4916
4917 void
4918 ARDOUR_UI::xrun_handler (samplepos_t where)
4919 {
4920         if (!_session) {
4921                 return;
4922         }
4923
4924         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4925
4926         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4927                 create_xrun_marker(where);
4928         }
4929
4930         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4931                 halt_on_xrun_message ();
4932         }
4933 }
4934
4935 void
4936 ARDOUR_UI::disk_overrun_handler ()
4937 {
4938         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4939
4940         if (!have_disk_speed_dialog_displayed) {
4941                 have_disk_speed_dialog_displayed = true;
4942                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4943 The disk system on your computer\n\
4944 was not able to keep up with %1.\n\
4945 \n\
4946 Specifically, it failed to write data to disk\n\
4947 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4948                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4949                 msg->show ();
4950         }
4951 }
4952
4953
4954 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4955 static MessageDialog *scan_dlg = NULL;
4956 static ProgressBar   *scan_pbar = NULL;
4957 static HBox          *scan_tbox = NULL;
4958 static Gtk::Button   *scan_timeout_button;
4959
4960 void
4961 ARDOUR_UI::cancel_plugin_scan ()
4962 {
4963         PluginManager::instance().cancel_plugin_scan();
4964 }
4965
4966 void
4967 ARDOUR_UI::cancel_plugin_timeout ()
4968 {
4969         PluginManager::instance().cancel_plugin_timeout();
4970         scan_timeout_button->set_sensitive (false);
4971 }
4972
4973 void
4974 ARDOUR_UI::plugin_scan_timeout (int timeout)
4975 {
4976         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4977                 return;
4978         }
4979         if (timeout > 0) {
4980                 scan_pbar->set_sensitive (false);
4981                 scan_timeout_button->set_sensitive (true);
4982                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4983                 scan_tbox->show();
4984         } else {
4985                 scan_pbar->set_sensitive (false);
4986                 scan_timeout_button->set_sensitive (false);
4987         }
4988         gui_idle_handler();
4989 }
4990
4991 void
4992 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4993 {
4994         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4995                 return;
4996         }
4997
4998         const bool cancelled = PluginManager::instance().cancelled();
4999         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
5000                 if (cancelled && scan_dlg->is_mapped()) {
5001                         scan_dlg->hide();
5002                         gui_idle_handler();
5003                         return;
5004                 }
5005                 if (cancelled || !can_cancel) {
5006                         return;
5007                 }
5008         }
5009
5010         static Gtk::Button *cancel_button;
5011         if (!scan_dlg) {
5012                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
5013                 VBox* vbox = scan_dlg->get_vbox();
5014                 vbox->set_size_request(400,-1);
5015                 scan_dlg->set_title (_("Scanning for plugins"));
5016
5017                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
5018                 cancel_button->set_name ("EditorGTKButton");
5019                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
5020                 cancel_button->show();
5021
5022                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
5023
5024                 scan_tbox = manage( new HBox() );
5025
5026                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
5027                 scan_timeout_button->set_name ("EditorGTKButton");
5028                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
5029                 scan_timeout_button->show();
5030
5031                 scan_pbar = manage(new ProgressBar());
5032                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
5033                 scan_pbar->set_text(_("Scan Timeout"));
5034                 scan_pbar->show();
5035
5036                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
5037                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
5038
5039                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
5040         }
5041
5042         assert(scan_dlg && scan_tbox && cancel_button);
5043
5044         if (type == X_("closeme")) {
5045                 scan_tbox->hide();
5046                 scan_dlg->hide();
5047         } else {
5048                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
5049                 scan_dlg->show();
5050         }
5051         if (!can_cancel || !cancelled) {
5052                 scan_timeout_button->set_sensitive(false);
5053         }
5054         cancel_button->set_sensitive(can_cancel && !cancelled);
5055
5056         gui_idle_handler();
5057 }
5058
5059 void
5060 ARDOUR_UI::gui_idle_handler ()
5061 {
5062         int timeout = 30;
5063         /* due to idle calls, gtk_events_pending() may always return true */
5064         while (gtk_events_pending() && --timeout) {
5065                 gtk_main_iteration ();
5066         }
5067 }
5068
5069 void
5070 ARDOUR_UI::disk_underrun_handler ()
5071 {
5072         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
5073
5074         if (!have_disk_speed_dialog_displayed) {
5075                 have_disk_speed_dialog_displayed = true;
5076                 MessageDialog* msg = new MessageDialog (
5077                         _main_window, string_compose (_("The disk system on your computer\n\
5078 was not able to keep up with %1.\n\
5079 \n\
5080 Specifically, it failed to read data from disk\n\
5081 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
5082                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
5083                 msg->show ();
5084         }
5085 }
5086
5087 void
5088 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
5089 {
5090         have_disk_speed_dialog_displayed = false;
5091         delete msg;
5092 }
5093
5094 void
5095 ARDOUR_UI::session_dialog (std::string msg)
5096 {
5097         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
5098
5099         MessageDialog* d;
5100
5101         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
5102         d->show_all ();
5103         d->run ();
5104         delete d;
5105 }
5106
5107 int
5108 ARDOUR_UI::pending_state_dialog ()
5109 {
5110         HBox* hbox = manage (new HBox());
5111         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
5112         ArdourDialog dialog (_("Crash Recovery"), true);
5113         Label  message (string_compose (_("\
5114 This session appears to have been in the\n\
5115 middle of recording when %1 or\n\
5116 the computer was shutdown.\n\
5117 \n\
5118 %1 can recover any captured audio for\n\
5119 you, or it can ignore it. Please decide\n\
5120 what you would like to do.\n"), PROGRAM_NAME));
5121         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5122         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5123         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5124         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5125         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
5126         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
5127         dialog.set_default_response (RESPONSE_ACCEPT);
5128         dialog.set_position (WIN_POS_CENTER);
5129         message.show();
5130         image->show();
5131         hbox->show();
5132
5133         switch (dialog.run ()) {
5134         case RESPONSE_ACCEPT:
5135                 return 1;
5136         default:
5137                 return 0;
5138         }
5139 }
5140
5141 int
5142 ARDOUR_UI::sr_mismatch_dialog (samplecnt_t desired, samplecnt_t actual)
5143 {
5144         HBox* hbox = new HBox();
5145         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
5146         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
5147         Label  message (string_compose (_("\
5148 This session was created with a sample rate of %1 Hz, but\n\
5149 %2 is currently running at %3 Hz.  If you load this session,\n\
5150 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
5151
5152         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5153         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5154         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5155         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5156         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
5157         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
5158         dialog.set_default_response (RESPONSE_ACCEPT);
5159         dialog.set_position (WIN_POS_CENTER);
5160         message.show();
5161         image->show();
5162         hbox->show();
5163
5164         switch (dialog.run()) {
5165         case RESPONSE_ACCEPT:
5166                 return 0;
5167         default:
5168                 break;
5169         }
5170
5171         return 1;
5172 }
5173
5174 void
5175 ARDOUR_UI::sr_mismatch_message (samplecnt_t desired, samplecnt_t actual)
5176 {
5177         MessageDialog msg (string_compose (_("\
5178 This session was created with a sample rate of %1 Hz, but\n\
5179 %2 is currently running at %3 Hz.\n\
5180 Audio will be recorded and played at the wrong sample rate.\n\
5181 Re-Configure the Audio Engine in\n\
5182 Menu > Window > Audio/Midi Setup"),
5183                                 desired, PROGRAM_NAME, actual),
5184                         true,
5185                         Gtk::MESSAGE_WARNING);
5186         msg.run ();
5187 }
5188
5189 void
5190 ARDOUR_UI::use_config ()
5191 {
5192         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
5193         if (node) {
5194                 set_transport_controllable_state (*node);
5195         }
5196 }
5197
5198 void
5199 ARDOUR_UI::update_transport_clocks (samplepos_t pos)
5200 {
5201         switch (UIConfiguration::instance().get_primary_clock_delta_mode()) {
5202                 case NoDelta:
5203                         primary_clock->set (pos);
5204                         break;
5205                 case DeltaEditPoint:
5206                         primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5207                         break;
5208                 case DeltaOriginMarker:
5209                         {
5210                                 Location* loc = _session->locations()->clock_origin_location ();
5211                                 primary_clock->set (pos, false, loc ? loc->start() : 0);
5212                         }
5213                         break;
5214         }
5215
5216         switch (UIConfiguration::instance().get_secondary_clock_delta_mode()) {
5217                 case NoDelta:
5218                         secondary_clock->set (pos);
5219                         break;
5220                 case DeltaEditPoint:
5221                         secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5222                         break;
5223                 case DeltaOriginMarker:
5224                         {
5225                                 Location* loc = _session->locations()->clock_origin_location ();
5226                                 secondary_clock->set (pos, false, loc ? loc->start() : 0);
5227                         }
5228                         break;
5229         }
5230
5231         if (big_clock_window) {
5232                 big_clock->set (pos);
5233         }
5234         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
5235 }
5236
5237
5238 void
5239 ARDOUR_UI::record_state_changed ()
5240 {
5241         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
5242
5243         if (!_session) {
5244                 /* why bother - the clock isn't visible */
5245                 return;
5246         }
5247
5248         ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording());
5249
5250         if (big_clock_window) {
5251                 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
5252                         big_clock->set_active (true);
5253                 } else {
5254                         big_clock->set_active (false);
5255                 }
5256         }
5257
5258 }
5259
5260 bool
5261 ARDOUR_UI::first_idle ()
5262 {
5263         if (_session) {
5264                 _session->allow_auto_play (true);
5265         }
5266
5267         if (editor) {
5268                 editor->first_idle();
5269         }
5270
5271         /* in 1 second, hide the splash screen
5272          *
5273          * Consider hiding it *now*. If a user opens opens a dialog
5274          * during that one second while the splash is still visible,
5275          * the dialog will push-back the splash.
5276          * Closing the dialog later will pop it back.
5277          */
5278         Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
5279
5280         Keyboard::set_can_save_keybindings (true);
5281         return false;
5282 }
5283
5284 void
5285 ARDOUR_UI::store_clock_modes ()
5286 {
5287         XMLNode* node = new XMLNode(X_("ClockModes"));
5288
5289         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
5290                 XMLNode* child = new XMLNode (X_("Clock"));
5291
5292                 child->set_property (X_("name"), (*x)->name());
5293                 child->set_property (X_("mode"), (*x)->mode());
5294                 child->set_property (X_("on"), (*x)->on());
5295
5296                 node->add_child_nocopy (*child);
5297         }
5298
5299         _session->add_extra_xml (*node);
5300         _session->set_dirty ();
5301 }
5302
5303 void
5304 ARDOUR_UI::setup_profile ()
5305 {
5306         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5307                 Profile->set_small_screen ();
5308         }
5309
5310         if (g_getenv ("TRX")) {
5311                 Profile->set_trx ();
5312         }
5313
5314         if (g_getenv ("MIXBUS")) {
5315                 Profile->set_mixbus ();
5316         }
5317 }
5318
5319 int
5320 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5321 {
5322         MissingFileDialog dialog (s, str, type);
5323
5324         dialog.show ();
5325         dialog.present ();
5326
5327         int result = dialog.run ();
5328         dialog.hide ();
5329
5330         switch (result) {
5331         case RESPONSE_OK:
5332                 break;
5333         default:
5334                 return 1; // quit entire session load
5335         }
5336
5337         result = dialog.get_action ();
5338
5339         return result;
5340 }
5341
5342 int
5343 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5344 {
5345         AmbiguousFileDialog dialog (file, hits);
5346
5347         dialog.show ();
5348         dialog.present ();
5349
5350         dialog.run ();
5351
5352         return dialog.get_which ();
5353 }
5354
5355 /** Allocate our thread-local buffers */
5356 void
5357 ARDOUR_UI::get_process_buffers ()
5358 {
5359         _process_thread->get_buffers ();
5360 }
5361
5362 /** Drop our thread-local buffers */
5363 void
5364 ARDOUR_UI::drop_process_buffers ()
5365 {
5366         _process_thread->drop_buffers ();
5367 }
5368
5369 void
5370 ARDOUR_UI::feedback_detected ()
5371 {
5372         _feedback_exists = true;
5373 }
5374
5375 void
5376 ARDOUR_UI::successful_graph_sort ()
5377 {
5378         _feedback_exists = false;
5379 }
5380
5381 void
5382 ARDOUR_UI::midi_panic ()
5383 {
5384         if (_session) {
5385                 _session->midi_panic();
5386         }
5387 }
5388
5389 void
5390 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5391 {
5392         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5393         const char* end_big = "</span>";
5394         const char* start_mono = "<tt>";
5395         const char* end_mono = "</tt>";
5396
5397         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5398                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5399                                              "From now on, use the backup copy with older versions of %3"),
5400                                            xml_path, backup_path, PROGRAM_NAME,
5401                                            start_big, end_big,
5402                                            start_mono, end_mono), true);
5403
5404         msg.run ();
5405 }
5406
5407 void
5408 ARDOUR_UI::add_editor_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
5409 {
5410         using namespace Menu_Helpers;
5411
5412         items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (editor_meter, &LevelMeterHBox::set_meter_type), type)));
5413         RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
5414         i->set_active (editor_meter->meter_type () == type);
5415 }
5416
5417 void
5418 ARDOUR_UI::popup_editor_meter_menu (GdkEventButton* ev)
5419 {
5420         using namespace Gtk::Menu_Helpers;
5421
5422         Gtk::Menu* m = manage (new Menu);
5423         MenuList& items = m->items ();
5424
5425         RadioMenuItem::Group group;
5426
5427         _suspend_editor_meter_callbacks = true;
5428         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
5429         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak0dB), MeterPeak0dB);
5430         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterKrms),  MeterKrms);
5431         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
5432         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
5433         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
5434         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
5435         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
5436         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
5437         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12);
5438         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU),  MeterVU);
5439
5440         m->popup (ev->button, ev->time);
5441         _suspend_editor_meter_callbacks = false;
5442 }
5443
5444 bool
5445 ARDOUR_UI::editor_meter_button_press (GdkEventButton* ev)
5446 {
5447         if (ev->button == 3 && editor_meter) {
5448                 popup_editor_meter_menu (ev);
5449                 return true;
5450         }
5451         return false;
5452 }
5453
5454 void
5455 ARDOUR_UI::reset_peak_display ()
5456 {
5457         if (!_session || !_session->master_out() || !editor_meter) return;
5458         editor_meter->clear_meters();
5459         editor_meter_max_peak = -INFINITY;
5460         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5461 }
5462
5463 void
5464 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5465 {
5466         if (!_session || !_session->master_out()) return;
5467         if (group == _session->master_out()->route_group()) {
5468                 reset_peak_display ();
5469         }
5470 }
5471
5472 void
5473 ARDOUR_UI::reset_route_peak_display (Route* route)
5474 {
5475         if (!_session || !_session->master_out()) return;
5476         if (_session->master_out().get() == route) {
5477                 reset_peak_display ();
5478         }
5479 }
5480
5481 int
5482 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5483 {
5484         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5485         audio_midi_setup->set_position (WIN_POS_CENTER);
5486
5487         if (desired_sample_rate != 0) {
5488                 if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5489                         audio_midi_setup->try_autostart ();
5490                         if (ARDOUR::AudioEngine::instance()->running()) {
5491                                 return 0;
5492                         }
5493                 }
5494         }
5495
5496         while (true) {
5497                 int response = audio_midi_setup->run();
5498                 switch (response) {
5499                 case Gtk::RESPONSE_DELETE_EVENT:
5500                         // after latency callibration engine may run,
5501                         // Running() signal was emitted, but dialog will not
5502                         // have emitted a response. The user needs to close
5503                         // the dialog -> Gtk::RESPONSE_DELETE_EVENT
5504                         if (!AudioEngine::instance()->running()) {
5505                                 return -1;
5506                         }
5507                         // fall through
5508                 default:
5509                         if (!AudioEngine::instance()->running()) {
5510                                 continue;
5511                         }
5512                         audio_midi_setup->hide ();
5513                         return 0;
5514                 }
5515         }
5516 }
5517
5518
5519 gint
5520 ARDOUR_UI::transport_numpad_timeout ()
5521 {
5522         _numpad_locate_happening = false;
5523         if (_numpad_timeout_connection.connected() )
5524                 _numpad_timeout_connection.disconnect();
5525         return 1;
5526 }
5527
5528 void
5529 ARDOUR_UI::transport_numpad_decimal ()
5530 {
5531         _numpad_timeout_connection.disconnect();
5532
5533         if (_numpad_locate_happening) {
5534                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5535                 _numpad_locate_happening = false;
5536         } else {
5537                 _pending_locate_num = 0;
5538                 _numpad_locate_happening = true;
5539                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5540         }
5541 }
5542
5543 void
5544 ARDOUR_UI::transport_numpad_event (int num)
5545 {
5546         if ( _numpad_locate_happening ) {
5547                 _pending_locate_num = _pending_locate_num*10 + num;
5548         } else {
5549                 switch (num) {
5550                         case 0:  toggle_roll(false, false);             break;
5551                         case 1:  transport_rewind(1);                           break;
5552                         case 2:  transport_forward(1);                          break;
5553                         case 3:  transport_record(true);                        break;
5554                         case 4:  toggle_session_auto_loop();            break;
5555                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5556                         case 6:  toggle_punch();                                        break;
5557                         case 7:  toggle_click();                                break;
5558                         case 8:  toggle_auto_return();                  break;
5559                         case 9:  toggle_follow_edits();         break;
5560                 }
5561         }
5562 }
5563
5564 void
5565 ARDOUR_UI::set_flat_buttons ()
5566 {
5567         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5568 }
5569
5570 void
5571 ARDOUR_UI::audioengine_became_silent ()
5572 {
5573         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5574                            true,
5575                            Gtk::MESSAGE_WARNING,
5576                            Gtk::BUTTONS_NONE,
5577                            true);
5578
5579         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5580
5581         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5582         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5583         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5584         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5585         Gtk::HBox pay_button_box;
5586         Gtk::HBox subscribe_button_box;
5587
5588         pay_button_box.pack_start (pay_button, true, false);
5589         subscribe_button_box.pack_start (subscribe_button, true, false);
5590
5591         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 */
5592
5593         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5594         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5595
5596         msg.get_vbox()->pack_start (pay_label);
5597         msg.get_vbox()->pack_start (pay_button_box);
5598         msg.get_vbox()->pack_start (subscribe_label);
5599         msg.get_vbox()->pack_start (subscribe_button_box);
5600
5601         msg.get_vbox()->show_all ();
5602
5603         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5604         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5605         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5606
5607         int r = msg.run ();
5608
5609         switch (r) {
5610         case Gtk::RESPONSE_YES:
5611                 AudioEngine::instance()->reset_silence_countdown ();
5612                 break;
5613
5614         case Gtk::RESPONSE_NO:
5615                 /* save and quit */
5616                 save_state_canfail ("");
5617                 exit (0);
5618                 break;
5619
5620         case Gtk::RESPONSE_CANCEL:
5621         default:
5622                 /* don't reset, save session and exit */
5623                 break;
5624         }
5625 }
5626
5627 void
5628 ARDOUR_UI::hide_application ()
5629 {
5630         Application::instance ()-> hide ();
5631 }
5632
5633 void
5634 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5635 {
5636         /* icons, titles, WM stuff */
5637
5638         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5639
5640         if (window_icons.empty()) {
5641                 Glib::RefPtr<Gdk::Pixbuf> icon;
5642                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
5643                         window_icons.push_back (icon);
5644                 }
5645                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
5646                         window_icons.push_back (icon);
5647                 }
5648                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
5649                         window_icons.push_back (icon);
5650                 }
5651                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
5652                         window_icons.push_back (icon);
5653                 }
5654         }
5655
5656         if (!window_icons.empty()) {
5657                 window.set_default_icon_list (window_icons);
5658         }
5659
5660         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5661
5662         if (!name.empty()) {
5663                 title += name;
5664         }
5665
5666         window.set_title (title.get_string());
5667         window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
5668
5669         window.set_flags (CAN_FOCUS);
5670         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5671
5672         /* This is a hack to ensure that GTK-accelerators continue to
5673          * work. Once we switch over to entirely native bindings, this will be
5674          * unnecessary and should be removed
5675          */
5676         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5677
5678         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5679         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5680         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5681         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5682 }
5683
5684 bool
5685 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5686 {
5687         Gtkmm2ext::Bindings* bindings = 0;
5688         Gtk::Window* window = 0;
5689
5690         /* until we get ardour bindings working, we are not handling key
5691          * releases yet.
5692          */
5693
5694         if (ev->type != GDK_KEY_PRESS) {
5695                 return false;
5696         }
5697
5698         if (event_window == &_main_window) {
5699
5700                 window = event_window;
5701
5702                 /* find current tab contents */
5703
5704                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5705
5706                 /* see if it uses the ardour binding system */
5707
5708                 if (w) {
5709                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5710                 }
5711
5712                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5713
5714         } else {
5715
5716                 window = event_window;
5717
5718                 /* see if window uses ardour binding system */
5719
5720                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5721         }
5722
5723         /* An empty binding set is treated as if it doesn't exist */
5724
5725         if (bindings && bindings->empty()) {
5726                 bindings = 0;
5727         }
5728
5729         return key_press_focus_accelerator_handler (*window, ev, bindings);
5730 }
5731
5732 static Gtkmm2ext::Bindings*
5733 get_bindings_from_widget_heirarchy (GtkWidget** w)
5734 {
5735         void* p = NULL;
5736
5737         while (*w) {
5738                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
5739                         break;
5740                 }
5741                 *w = gtk_widget_get_parent (*w);
5742         }
5743
5744         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5745 }
5746
5747 bool
5748 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5749 {
5750         GtkWindow* win = window.gobj();
5751         GtkWidget* focus = gtk_window_get_focus (win);
5752         GtkWidget* binding_widget = focus;
5753         bool special_handling_of_unmodified_accelerators = false;
5754         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5755
5756         if (focus) {
5757
5758                 /* some widget has keyboard focus */
5759
5760                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5761
5762                         /* A particular kind of focusable widget currently has keyboard
5763                          * focus. All unmodified key events should go to that widget
5764                          * first and not be used as an accelerator by default
5765                          */
5766
5767                         special_handling_of_unmodified_accelerators = true;
5768
5769                 } else {
5770
5771                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5772                         if (focus_bindings) {
5773                                 bindings = focus_bindings;
5774                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5775                         }
5776                 }
5777         }
5778
5779         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",
5780                                                           win,
5781                                                           ev->keyval,
5782                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
5783                                                           special_handling_of_unmodified_accelerators,
5784                                                           Keyboard::some_magic_widget_has_focus(),
5785                                                           focus,
5786                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5787                                                           ((ev->state & mask) ? "yes" : "no"),
5788                                                           window.get_title()));
5789
5790         /* This exists to allow us to override the way GTK handles
5791            key events. The normal sequence is:
5792
5793            a) event is delivered to a GtkWindow
5794            b) accelerators/mnemonics are activated
5795            c) if (b) didn't handle the event, propagate to
5796                the focus widget and/or focus chain
5797
5798            The problem with this is that if the accelerators include
5799            keys without modifiers, such as the space bar or the
5800            letter "e", then pressing the key while typing into
5801            a text entry widget results in the accelerator being
5802            activated, instead of the desired letter appearing
5803            in the text entry.
5804
5805            There is no good way of fixing this, but this
5806            represents a compromise. The idea is that
5807            key events involving modifiers (not Shift)
5808            get routed into the activation pathway first, then
5809            get propagated to the focus widget if necessary.
5810
5811            If the key event doesn't involve modifiers,
5812            we deliver to the focus widget first, thus allowing
5813            it to get "normal text" without interference
5814            from acceleration.
5815
5816            Of course, this can also be problematic: if there
5817            is a widget with focus, then it will swallow
5818            all "normal text" accelerators.
5819         */
5820
5821
5822         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5823
5824                 /* no special handling or there are modifiers in effect: accelerate first */
5825
5826                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5827                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5828                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5829
5830                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5831                 KeyboardKey k (ev->state, ev->keyval);
5832
5833                 while (bindings) {
5834
5835                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5836
5837                         if (bindings->activate (k, Bindings::Press)) {
5838                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5839                                 return true;
5840                         }
5841
5842                         if (binding_widget) {
5843                                 binding_widget = gtk_widget_get_parent (binding_widget);
5844                                 if (binding_widget) {
5845                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5846                                 } else {
5847                                         bindings = 0;
5848                                 }
5849                         } else {
5850                                 bindings = 0;
5851                         }
5852                 }
5853
5854                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5855
5856                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5857                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5858                         return true;
5859                 }
5860
5861                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5862
5863                 if (gtk_window_propagate_key_event (win, ev)) {
5864                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5865                         return true;
5866                 }
5867
5868         } else {
5869
5870                 /* no modifiers, propagate first */
5871
5872                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5873
5874                 if (gtk_window_propagate_key_event (win, ev)) {
5875                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5876                         return true;
5877                 }
5878
5879                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5880                 KeyboardKey k (ev->state, ev->keyval);
5881
5882                 while (bindings) {
5883
5884                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5885
5886
5887                         if (bindings->activate (k, Bindings::Press)) {
5888                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5889                                 return true;
5890                         }
5891
5892                         if (binding_widget) {
5893                                 binding_widget = gtk_widget_get_parent (binding_widget);
5894                                 if (binding_widget) {
5895                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5896                                 } else {
5897                                         bindings = 0;
5898                                 }
5899                         } else {
5900                                 bindings = 0;
5901                         }
5902                 }
5903
5904                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5905
5906                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5907                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5908                         return true;
5909                 }
5910         }
5911
5912         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5913         return true;
5914 }
5915
5916 void
5917 ARDOUR_UI::load_bindings ()
5918 {
5919         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5920                 error << _("Global keybindings are missing") << endmsg;
5921         }
5922 }
5923
5924 void
5925 ARDOUR_UI::cancel_solo ()
5926 {
5927         if (_session) {
5928                 _session->cancel_all_solo ();
5929         }
5930 }
5931
5932 void
5933 ARDOUR_UI::reset_focus (Gtk::Widget* w)
5934 {
5935         /* this resets focus to the first focusable parent of the given widget,
5936          * or, if there is no focusable parent, cancels focus in the toplevel
5937          * window that the given widget is packed into (if there is one).
5938          */
5939
5940         if (!w) {
5941                 return;
5942         }
5943
5944         Gtk::Widget* top = w->get_toplevel();
5945
5946         if (!top || !top->is_toplevel()) {
5947                 return;
5948         }
5949
5950         w = w->get_parent ();
5951
5952         while (w) {
5953
5954                 if (w->is_toplevel()) {
5955                         /* Setting the focus widget to a Gtk::Window causes all
5956                          * subsequent calls to ::has_focus() on the nominal
5957                          * focus widget in that window to return
5958                          * false. Workaround: never set focus to the toplevel
5959                          * itself.
5960                          */
5961                         break;
5962                 }
5963
5964                 if (w->get_can_focus ()) {
5965                         Gtk::Window* win = dynamic_cast<Gtk::Window*> (top);
5966                         win->set_focus (*w);
5967                         return;
5968                 }
5969                 w = w->get_parent ();
5970         }
5971
5972         if (top == &_main_window) {
5973
5974         }
5975
5976         /* no focusable parent found, cancel focus in top level window.
5977            C++ API cannot be used for this. Thanks, references.
5978         */
5979
5980         gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
5981
5982 }