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