(Source List) Fix drag-n-drop.
[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 (session_name.empty()) {
3347                         /* need the dialog to get the name (at least) from the user */
3348                         switch (session_dialog.run()) {
3349                         case RESPONSE_ACCEPT:
3350                                 break;
3351                         case RESPONSE_NONE:
3352                                 /* this is used for async * app->ShouldLoad(). */
3353                                 continue; // while loop
3354                                 break;
3355                         default:
3356                                 if (quit_on_cancel) {
3357                                         ARDOUR_UI::finish ();
3358                                         Gtkmm2ext::Application::instance()->cleanup();
3359                                         ARDOUR::cleanup ();
3360                                         pthread_cancel_all ();
3361                                         return -1; // caller is responsible to call exit()
3362                                 } else {
3363                                         return ret;
3364                                 }
3365                         }
3366
3367                         session_dialog.hide ();
3368                 }
3369
3370                 /* if we run the startup dialog again, offer more than just "new session" */
3371
3372                 should_be_new = false;
3373
3374                 session_name = session_dialog.session_name (likely_new);
3375                 session_path = session_dialog.session_folder ();
3376
3377                 if (nsm) {
3378                         likely_new = true;
3379                 }
3380
3381                 if (!likely_new) {
3382                         int rv = ARDOUR::inflate_session (session_name,
3383                                         Config->get_default_session_parent_dir(), session_path, session_name);
3384                         if (rv < 0) {
3385                                 MessageDialog msg (session_dialog,
3386                                         string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
3387                                 msg.run ();
3388                                 continue;
3389                         }
3390                         else if (rv == 0) {
3391                                 session_dialog.set_provided_session (session_name, session_path);
3392                         }
3393                 }
3394
3395                 // XXX check archive, inflate
3396                 string::size_type suffix = session_name.find (statefile_suffix);
3397
3398                 if (suffix != string::npos) {
3399                         session_name = session_name.substr (0, suffix);
3400                 }
3401
3402                 /* this shouldn't happen, but we catch it just in case it does */
3403
3404                 if (session_name.empty()) {
3405                         continue;
3406                 }
3407
3408                 if (session_dialog.use_session_template()) {
3409                         template_name = session_dialog.session_template_name();
3410                         _session_is_new = true;
3411                 }
3412
3413                 if (session_name[0] == G_DIR_SEPARATOR ||
3414 #ifdef PLATFORM_WINDOWS
3415                    (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3416 #else
3417                    (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3418                    (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3419 #endif
3420                 )
3421                 {
3422
3423                         /* absolute path or cwd-relative path specified for session name: infer session folder
3424                            from what was given.
3425                         */
3426
3427                         session_path = Glib::path_get_dirname (session_name);
3428                         session_name = Glib::path_get_basename (session_name);
3429
3430                 } else {
3431
3432                         session_path = session_dialog.session_folder();
3433
3434                         char illegal = Session::session_name_is_legal (session_name);
3435
3436                         if (illegal) {
3437                                 MessageDialog msg (session_dialog,
3438                                                    string_compose (_("To ensure compatibility with various systems\n"
3439                                                                      "session names may not contain a '%1' character"),
3440                                                                    illegal));
3441                                 msg.run ();
3442                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3443                                 continue;
3444                         }
3445                 }
3446
3447                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3448
3449
3450                         if (likely_new && !nsm) {
3451
3452                                 std::string existing = Glib::build_filename (session_path, session_name);
3453
3454                                 if (!ask_about_loading_existing_session (existing)) {
3455                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3456                                         continue;
3457                                 }
3458                         }
3459
3460                         _session_is_new = false;
3461
3462                 } else {
3463
3464                         if (!likely_new) {
3465                                 pop_back_splash (session_dialog);
3466                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3467                                 msg.run ();
3468                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3469                                 continue;
3470                         }
3471
3472                         char illegal = Session::session_name_is_legal(session_name);
3473
3474                         if (illegal) {
3475                                 pop_back_splash (session_dialog);
3476                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3477                                                                                     "session names may not contain a '%1' character"), illegal));
3478                                 msg.run ();
3479                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3480                                 continue;
3481                         }
3482
3483                         _session_is_new = true;
3484                 }
3485
3486                 if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
3487
3488                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3489                         meta_session_setup (template_name.substr (11));
3490
3491                 } else if (likely_new && template_name.empty()) {
3492
3493                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3494
3495                 } else {
3496
3497                         ret = load_session (session_path, session_name, template_name);
3498
3499                         if (ret == -2) {
3500                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3501                                 exit (EXIT_FAILURE);
3502                         }
3503
3504                         /* clear this to avoid endless attempts to load the
3505                            same session.
3506                         */
3507
3508                         ARDOUR_COMMAND_LINE::session_name = "";
3509                 }
3510         }
3511
3512         _session_dialog = NULL;
3513
3514         return ret;
3515 }
3516
3517 void
3518 ARDOUR_UI::close_session()
3519 {
3520         if (!check_audioengine (_main_window)) {
3521                 return;
3522         }
3523
3524         if (unload_session (true)) {
3525                 return;
3526         }
3527
3528         ARDOUR_COMMAND_LINE::session_name = "";
3529
3530         if (get_session_parameters (true, false)) {
3531                 exit (EXIT_FAILURE);
3532         }
3533 }
3534
3535 /** @param snap_name Snapshot name (without .ardour suffix).
3536  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3537  */
3538 int
3539 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3540 {
3541         /* load_session calls flush_pending() which allows
3542          * GUI interaction and potentially loading another session
3543          * (that was easy via snapshot sidebar).
3544          * Recursing into load_session() from load_session() and recusive
3545          * event loops causes all kind of crashes.
3546          */
3547         assert (!session_load_in_progress);
3548         if (session_load_in_progress) {
3549                 return -1;
3550         }
3551         PBD::Unwinder<bool> lsu (session_load_in_progress, true);
3552
3553         Session *new_session;
3554         int unload_status;
3555         int retval = -1;
3556
3557         if (_session) {
3558                 unload_status = unload_session ();
3559
3560                 if (unload_status < 0) {
3561                         goto out;
3562                 } else if (unload_status > 0) {
3563                         retval = 0;
3564                         goto out;
3565                 }
3566         }
3567
3568         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3569
3570         try {
3571                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3572         }
3573
3574         /* this one is special */
3575
3576         catch (AudioEngine::PortRegistrationFailure const& err) {
3577
3578                 MessageDialog msg (err.what(),
3579                                    true,
3580                                    Gtk::MESSAGE_INFO,
3581                                    Gtk::BUTTONS_CLOSE);
3582
3583                 msg.set_title (_("Port Registration Error"));
3584                 msg.set_secondary_text (_("Click the Close button to try again."));
3585                 msg.set_position (Gtk::WIN_POS_CENTER);
3586                 pop_back_splash (msg);
3587                 msg.present ();
3588
3589                 int response = msg.run ();
3590
3591                 msg.hide ();
3592
3593                 switch (response) {
3594                 case RESPONSE_CANCEL:
3595                         exit (EXIT_FAILURE);
3596                 default:
3597                         break;
3598                 }
3599                 goto out;
3600         }
3601         catch (SessionException const& e) {
3602                 MessageDialog msg (string_compose(
3603                                            _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
3604                                            path, snap_name, e.what()),
3605                                    true,
3606                                    Gtk::MESSAGE_INFO,
3607                                    BUTTONS_OK);
3608
3609                 msg.set_title (_("Loading Error"));
3610                 msg.set_position (Gtk::WIN_POS_CENTER);
3611                 pop_back_splash (msg);
3612                 msg.present ();
3613
3614                 dump_errors (cerr);
3615
3616                 (void) msg.run ();
3617                 msg.hide ();
3618
3619                 goto out;
3620         }
3621         catch (...) {
3622
3623                 MessageDialog msg (string_compose(
3624                                            _("Session \"%1 (snapshot %2)\" did not load successfully."),
3625                                            path, snap_name),
3626                                    true,
3627                                    Gtk::MESSAGE_INFO,
3628                                    BUTTONS_OK);
3629
3630                 msg.set_title (_("Loading Error"));
3631                 msg.set_position (Gtk::WIN_POS_CENTER);
3632                 pop_back_splash (msg);
3633                 msg.present ();
3634
3635                 dump_errors (cerr);
3636
3637                 (void) msg.run ();
3638                 msg.hide ();
3639
3640                 goto out;
3641         }
3642
3643         {
3644                 list<string> const u = new_session->unknown_processors ();
3645                 if (!u.empty()) {
3646                         MissingPluginDialog d (_session, u);
3647                         d.run ();
3648                 }
3649         }
3650
3651         if (!new_session->writable()) {
3652                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3653                                    true,
3654                                    Gtk::MESSAGE_INFO,
3655                                    BUTTONS_OK);
3656
3657                 msg.set_title (_("Read-only Session"));
3658                 msg.set_position (Gtk::WIN_POS_CENTER);
3659                 pop_back_splash (msg);
3660                 msg.present ();
3661                 (void) msg.run ();
3662                 msg.hide ();
3663         }
3664
3665
3666         /* Now the session been created, add the transport controls */
3667         new_session->add_controllable(roll_controllable);
3668         new_session->add_controllable(stop_controllable);
3669         new_session->add_controllable(goto_start_controllable);
3670         new_session->add_controllable(goto_end_controllable);
3671         new_session->add_controllable(auto_loop_controllable);
3672         new_session->add_controllable(play_selection_controllable);
3673         new_session->add_controllable(rec_controllable);
3674
3675         set_session (new_session);
3676
3677         if (_session) {
3678                 _session->set_clean ();
3679         }
3680
3681 #ifdef WINDOWS_VST_SUPPORT
3682         fst_stop_threading();
3683 #endif
3684
3685         {
3686                 Timers::TimerSuspender t;
3687                 flush_pending (10);
3688         }
3689
3690 #ifdef WINDOWS_VST_SUPPORT
3691         fst_start_threading();
3692 #endif
3693         retval = 0;
3694
3695         if (!mix_template.empty ()) {
3696                 /* if mix_template is given, assume this is a new session */
3697                 string metascript = Glib::build_filename (mix_template, "template.lua");
3698                 meta_session_setup (metascript);
3699         }
3700
3701
3702   out:
3703         /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
3704          * which is queued by set_session().
3705          * If session-loading fails we hide it explicitly.
3706          * This covers both cases in a central place.
3707          */
3708         if (retval) {
3709                 hide_splash ();
3710         }
3711         return retval;
3712 }
3713
3714 int
3715 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile* bus_profile)
3716 {
3717         Session *new_session;
3718         int x;
3719
3720         x = unload_session ();
3721
3722         if (x < 0) {
3723                 return -1;
3724         } else if (x > 0) {
3725                 return 0;
3726         }
3727
3728         _session_is_new = true;
3729
3730         try {
3731                 new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
3732         }
3733
3734         catch (SessionException const& e) {
3735                 cerr << "Here are the errors associated with this failed session:\n";
3736                 dump_errors (cerr);
3737                 cerr << "---------\n";
3738                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3739                 msg.set_title (_("Loading Error"));
3740                 msg.set_position (Gtk::WIN_POS_CENTER);
3741                 pop_back_splash (msg);
3742                 msg.run ();
3743                 return -1;
3744         }
3745         catch (...) {
3746                 cerr << "Here are the errors associated with this failed session:\n";
3747                 dump_errors (cerr);
3748                 cerr << "---------\n";
3749                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3750                 msg.set_title (_("Loading Error"));
3751                 msg.set_position (Gtk::WIN_POS_CENTER);
3752                 pop_back_splash (msg);
3753                 msg.run ();
3754                 return -1;
3755         }
3756
3757         /* Give the new session the default GUI state, if such things exist */
3758
3759         XMLNode* n;
3760         n = Config->instant_xml (X_("Editor"));
3761         if (n) {
3762                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3763                 new_session->add_instant_xml (*n, false);
3764         }
3765         n = Config->instant_xml (X_("Mixer"));
3766         if (n) {
3767                 new_session->add_instant_xml (*n, false);
3768         }
3769
3770         n = Config->instant_xml (X_("Preferences"));
3771         if (n) {
3772                 new_session->add_instant_xml (*n, false);
3773         }
3774
3775         /* Put the playhead at 0 and scroll fully left */
3776         n = new_session->instant_xml (X_("Editor"));
3777         if (n) {
3778                 n->set_property (X_("playhead"), X_("0"));
3779                 n->set_property (X_("left-frame"), X_("0"));
3780         }
3781
3782         set_session (new_session);
3783
3784         new_session->save_state(new_session->name());
3785
3786         return 0;
3787 }
3788
3789
3790 static void _lua_print (std::string s) {
3791 #ifndef NDEBUG
3792         std::cout << "LuaInstance: " << s << "\n";
3793 #endif
3794         PBD::info << "LuaInstance: " << s << endmsg;
3795 }
3796
3797 std::map<std::string, std::string>
3798 ARDOUR_UI::route_setup_info (const std::string& script_path)
3799 {
3800         std::map<std::string, std::string> rv;
3801
3802         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3803                 return rv;
3804         }
3805
3806         LuaState lua;
3807         lua.Print.connect (&_lua_print);
3808         lua.sandbox (true);
3809
3810         lua_State* L = lua.getState();
3811         LuaInstance::register_classes (L);
3812         LuaBindings::set_session (L, _session);
3813         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3814         lua_setglobal (L, "Editor");
3815
3816         lua.do_command ("function ardour () end");
3817         lua.do_file (script_path);
3818
3819         try {
3820                 luabridge::LuaRef fn = luabridge::getGlobal (L, "route_setup");
3821                 if (!fn.isFunction ()) {
3822                         return rv;
3823                 }
3824                 luabridge::LuaRef rs = fn ();
3825                 if (!rs.isTable ()) {
3826                         return rv;
3827                 }
3828                 for (luabridge::Iterator i(rs); !i.isNil (); ++i) {
3829                         if (!i.key().isString()) {
3830                                 continue;
3831                         }
3832                         std::string key = i.key().tostring();
3833                         if (i.value().isString() || i.value().isNumber() || i.value().isBoolean()) {
3834                                 rv[key] = i.value().tostring();
3835                         }
3836                 }
3837         } catch (luabridge::LuaException const& e) {
3838                 cerr << "LuaException:" << e.what () << endl;
3839         } catch (...) { }
3840         return rv;
3841 }
3842
3843 void
3844 ARDOUR_UI::meta_route_setup (const std::string& script_path)
3845 {
3846         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3847                 return;
3848         }
3849         assert (add_route_dialog);
3850
3851         int count;
3852         if ((count = add_route_dialog->count()) <= 0) {
3853                 return;
3854         }
3855
3856         LuaState lua;
3857         lua.Print.connect (&_lua_print);
3858         lua.sandbox (true);
3859
3860         lua_State* L = lua.getState();
3861         LuaInstance::register_classes (L);
3862         LuaBindings::set_session (L, _session);
3863         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3864         lua_setglobal (L, "Editor");
3865
3866         lua.do_command ("function ardour () end");
3867         lua.do_file (script_path);
3868
3869         luabridge::LuaRef args (luabridge::newTable (L));
3870
3871         args["name"]       = add_route_dialog->name_template ();
3872         args["insert_at"]  = translate_order (add_route_dialog->insert_at());
3873         args["group"]      = add_route_dialog->route_group ();
3874         args["strict_io"]  = add_route_dialog->use_strict_io ();
3875         args["instrument"] = add_route_dialog->requested_instrument ();
3876         args["track_mode"] = add_route_dialog->mode ();
3877         args["channels"]   = add_route_dialog->channel_count ();
3878         args["how_many"]   = count;
3879
3880         try {
3881                 luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
3882                 if (fn.isFunction()) {
3883                         fn (args)();
3884                 }
3885         } catch (luabridge::LuaException const& e) {
3886                 cerr << "LuaException:" << e.what () << endl;
3887         } catch (...) {
3888                 display_insufficient_ports_message ();
3889         }
3890 }
3891
3892 void
3893 ARDOUR_UI::meta_session_setup (const std::string& script_path)
3894 {
3895         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3896                 return;
3897         }
3898
3899         LuaState lua;
3900         lua.Print.connect (&_lua_print);
3901         lua.sandbox (true);
3902
3903         lua_State* L = lua.getState();
3904         LuaInstance::register_classes (L);
3905         LuaBindings::set_session (L, _session);
3906         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3907         lua_setglobal (L, "Editor");
3908
3909         lua.do_command ("function ardour () end");
3910         lua.do_file (script_path);
3911
3912         try {
3913                 luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
3914                 if (fn.isFunction()) {
3915                         fn ()();
3916                 }
3917         } catch (luabridge::LuaException const& e) {
3918                 cerr << "LuaException:" << e.what () << endl;
3919         } catch (...) {
3920                 display_insufficient_ports_message ();
3921         }
3922 }
3923
3924 void
3925 ARDOUR_UI::launch_chat ()
3926 {
3927         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3928
3929         dialog.set_title (_("About the Chat"));
3930         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."));
3931
3932         switch (dialog.run()) {
3933         case RESPONSE_OK:
3934                 open_uri("http://webchat.freenode.net/?channels=ardour");
3935                 break;
3936         default:
3937                 break;
3938         }
3939 }
3940
3941 void
3942 ARDOUR_UI::launch_manual ()
3943 {
3944         PBD::open_uri (Config->get_tutorial_manual_url());
3945 }
3946
3947 void
3948 ARDOUR_UI::launch_reference ()
3949 {
3950         PBD::open_uri (Config->get_reference_manual_url());
3951 }
3952
3953 void
3954 ARDOUR_UI::launch_tracker ()
3955 {
3956         PBD::open_uri ("http://tracker.ardour.org");
3957 }
3958
3959 void
3960 ARDOUR_UI::launch_subscribe ()
3961 {
3962         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3963 }
3964
3965 void
3966 ARDOUR_UI::launch_cheat_sheet ()
3967 {
3968 #ifdef __APPLE__
3969         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3970 #else
3971         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3972 #endif
3973 }
3974
3975 void
3976 ARDOUR_UI::launch_website ()
3977 {
3978         PBD::open_uri ("http://ardour.org");
3979 }
3980
3981 void
3982 ARDOUR_UI::launch_website_dev ()
3983 {
3984         PBD::open_uri ("http://ardour.org/development.html");
3985 }
3986
3987 void
3988 ARDOUR_UI::launch_forums ()
3989 {
3990         PBD::open_uri ("https://community.ardour.org/forums");
3991 }
3992
3993 void
3994 ARDOUR_UI::launch_howto_report ()
3995 {
3996         PBD::open_uri ("http://ardour.org/reporting_bugs");
3997 }
3998
3999 void
4000 ARDOUR_UI::loading_message (const std::string& msg)
4001 {
4002         if (ARDOUR_COMMAND_LINE::no_splash) {
4003                 return;
4004         }
4005
4006         if (!splash) {
4007                 show_splash ();
4008         }
4009
4010         splash->message (msg);
4011 }
4012
4013 void
4014 ARDOUR_UI::show_splash ()
4015 {
4016         if (splash == 0) {
4017                 try {
4018                         splash = new Splash;
4019                 } catch (...) {
4020                         return;
4021                 }
4022         }
4023
4024         splash->display ();
4025 }
4026
4027 void
4028 ARDOUR_UI::hide_splash ()
4029 {
4030         delete splash;
4031         splash = 0;
4032 }
4033
4034 void
4035 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
4036 {
4037         size_t removed;
4038
4039         removed = rep.paths.size();
4040
4041         if (removed == 0) {
4042                 MessageDialog msgd (_main_window,
4043                                     _("No files were ready for clean-up"),
4044                                     true,
4045                                     Gtk::MESSAGE_INFO,
4046                                     Gtk::BUTTONS_OK);
4047                 msgd.set_title (_("Clean-up"));
4048                 msgd.set_secondary_text (_("If this seems surprising, \n\
4049 check for any existing snapshots.\n\
4050 These may still include regions that\n\
4051 require some unused files to continue to exist."));
4052
4053                 msgd.run ();
4054                 return;
4055         }
4056
4057         ArdourDialog results (_("Clean-up"), true, false);
4058
4059         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
4060                 CleanupResultsModelColumns() {
4061                         add (visible_name);
4062                         add (fullpath);
4063                 }
4064                 Gtk::TreeModelColumn<std::string> visible_name;
4065                 Gtk::TreeModelColumn<std::string> fullpath;
4066         };
4067
4068
4069         CleanupResultsModelColumns results_columns;
4070         Glib::RefPtr<Gtk::ListStore> results_model;
4071         Gtk::TreeView results_display;
4072
4073         results_model = ListStore::create (results_columns);
4074         results_display.set_model (results_model);
4075         results_display.append_column (list_title, results_columns.visible_name);
4076
4077         results_display.set_name ("CleanupResultsList");
4078         results_display.set_headers_visible (true);
4079         results_display.set_headers_clickable (false);
4080         results_display.set_reorderable (false);
4081
4082         Gtk::ScrolledWindow list_scroller;
4083         Gtk::Label txt;
4084         Gtk::VBox dvbox;
4085         Gtk::HBox dhbox;  // the hbox for the image and text
4086         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
4087         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
4088
4089         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
4090
4091         const string dead_directory = _session->session_directory().dead_path();
4092
4093         /* subst:
4094            %1 - number of files removed
4095            %2 - location of "dead"
4096            %3 - size of files affected
4097            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
4098         */
4099
4100         const char* bprefix;
4101         double space_adjusted = 0;
4102
4103         if (rep.space < 1000) {
4104                 bprefix = X_("");
4105                 space_adjusted = rep.space;
4106         } else if (rep.space < 1000000) {
4107                 bprefix = _("kilo");
4108                 space_adjusted = floorf((float)rep.space / 1000.0);
4109         } else if (rep.space < 1000000 * 1000) {
4110                 bprefix = _("mega");
4111                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
4112         } else {
4113                 bprefix = _("giga");
4114                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
4115         }
4116
4117         if (msg_delete) {
4118                 txt.set_markup (string_compose (P_("\
4119 The following file was deleted from %2,\n\
4120 releasing %3 %4bytes of disk space", "\
4121 The following %1 files were deleted from %2,\n\
4122 releasing %3 %4bytes of disk space", removed),
4123                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4124         } else {
4125                 txt.set_markup (string_compose (P_("\
4126 The following file was not in use and \n\
4127 has been moved to: %2\n\n\
4128 After a restart of %5\n\n\
4129 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4130 will release an additional %3 %4bytes of disk space.\n", "\
4131 The following %1 files were not in use and \n\
4132 have been moved to: %2\n\n\
4133 After a restart of %5\n\n\
4134 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4135 will release an additional %3 %4bytes of disk space.\n", removed),
4136                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4137         }
4138
4139         dhbox.pack_start (*dimage, true, false, 5);
4140         dhbox.pack_start (txt, true, false, 5);
4141
4142         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
4143                 TreeModel::Row row = *(results_model->append());
4144                 row[results_columns.visible_name] = *i;
4145                 row[results_columns.fullpath] = *i;
4146         }
4147
4148         list_scroller.add (results_display);
4149         list_scroller.set_size_request (-1, 150);
4150         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
4151
4152         dvbox.pack_start (dhbox, true, false, 5);
4153         dvbox.pack_start (list_scroller, true, false, 5);
4154         ddhbox.pack_start (dvbox, true, false, 5);
4155
4156         results.get_vbox()->pack_start (ddhbox, true, false, 5);
4157         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
4158         results.set_default_response (RESPONSE_CLOSE);
4159         results.set_position (Gtk::WIN_POS_MOUSE);
4160
4161         results_display.show();
4162         list_scroller.show();
4163         txt.show();
4164         dvbox.show();
4165         dhbox.show();
4166         ddhbox.show();
4167         dimage->show();
4168
4169         //results.get_vbox()->show();
4170         results.set_resizable (false);
4171
4172         results.run ();
4173
4174 }
4175
4176 void
4177 ARDOUR_UI::cleanup ()
4178 {
4179         if (_session == 0) {
4180                 /* shouldn't happen: menu item is insensitive */
4181                 return;
4182         }
4183
4184
4185         MessageDialog checker (_("Are you sure you want to clean-up?"),
4186                                 true,
4187                                 Gtk::MESSAGE_QUESTION,
4188                                 Gtk::BUTTONS_NONE);
4189
4190         checker.set_title (_("Clean-up"));
4191
4192         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
4193 ALL undo/redo information will be lost if you clean-up.\n\
4194 Clean-up will move all unused files to a \"dead\" location."));
4195
4196         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
4197         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
4198         checker.set_default_response (RESPONSE_CANCEL);
4199
4200         checker.set_name (_("CleanupDialog"));
4201         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
4202         checker.set_position (Gtk::WIN_POS_MOUSE);
4203
4204         switch (checker.run()) {
4205         case RESPONSE_ACCEPT:
4206                 break;
4207         default:
4208                 return;
4209         }
4210         checker.hide();
4211
4212         ARDOUR::CleanupReport rep;
4213
4214         editor->prepare_for_cleanup ();
4215
4216         /* do not allow flush until a session is reloaded */
4217         ActionManager::get_action (X_("Main"), X_("FlushWastebasket"))->set_sensitive (false);
4218
4219         if (_session->cleanup_sources (rep)) {
4220                 editor->finish_cleanup ();
4221                 return;
4222         }
4223
4224         editor->finish_cleanup ();
4225
4226         display_cleanup_results (rep, _("Cleaned Files"), false);
4227 }
4228
4229 void
4230 ARDOUR_UI::flush_trash ()
4231 {
4232         if (_session == 0) {
4233                 /* shouldn't happen: menu item is insensitive */
4234                 return;
4235         }
4236
4237         ARDOUR::CleanupReport rep;
4238
4239         if (_session->cleanup_trash_sources (rep)) {
4240                 return;
4241         }
4242
4243         display_cleanup_results (rep, _("deleted file"), true);
4244 }
4245
4246 void
4247 ARDOUR_UI::cleanup_peakfiles ()
4248 {
4249         if (_session == 0) {
4250                 /* shouldn't happen: menu item is insensitive */
4251                 return;
4252         }
4253
4254         if (! _session->can_cleanup_peakfiles ()) {
4255                 return;
4256         }
4257
4258         // get all region-views in this session
4259         RegionSelection rs;
4260         TrackViewList empty;
4261         empty.clear();
4262         editor->get_regions_after(rs, (samplepos_t) 0, empty);
4263         std::list<RegionView*> views = rs.by_layer();
4264
4265         // remove displayed audio-region-views waveforms
4266         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4267                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4268                 if (!arv) { continue ; }
4269                 arv->delete_waves();
4270         }
4271
4272         // cleanup peak files:
4273         // - stop pending peakfile threads
4274         // - close peakfiles if any
4275         // - remove peak dir in session
4276         // - setup peakfiles (background thread)
4277         _session->cleanup_peakfiles ();
4278
4279         // re-add waves to ARV
4280         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4281                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4282                 if (!arv) { continue ; }
4283                 arv->create_waves();
4284         }
4285 }
4286
4287 PresentationInfo::order_t
4288 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
4289 {
4290         if (editor->get_selection().tracks.empty()) {
4291                 return place == RouteDialogs::First ? 0 : PresentationInfo::max_order;
4292         }
4293
4294         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
4295
4296         /*
4297           we want the new routes to have their order keys set starting from
4298           the highest order key in the selection + 1 (if available).
4299         */
4300
4301         if (place == RouteDialogs::AfterSelection) {
4302                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
4303                 if (rtav) {
4304                         order_hint = rtav->route()->presentation_info().order();
4305                         order_hint++;
4306                 }
4307         } else if (place == RouteDialogs::BeforeSelection) {
4308                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
4309                 if (rtav) {
4310                         order_hint = rtav->route()->presentation_info().order();
4311                 }
4312         } else if (place == RouteDialogs::First) {
4313                 order_hint = 0;
4314         } else {
4315                 /* leave order_hint at max_order */
4316         }
4317
4318         return order_hint;
4319 }
4320
4321 void
4322 ARDOUR_UI::start_duplicate_routes ()
4323 {
4324         if (!duplicate_routes_dialog) {
4325                 duplicate_routes_dialog = new DuplicateRouteDialog;
4326         }
4327
4328         if (duplicate_routes_dialog->restart (_session)) {
4329                 return;
4330         }
4331
4332         duplicate_routes_dialog->present ();
4333 }
4334
4335 void
4336 ARDOUR_UI::add_route ()
4337 {
4338         if (!add_route_dialog.get (false)) {
4339                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
4340         }
4341
4342         if (!_session) {
4343                 return;
4344         }
4345
4346         if (add_route_dialog->is_visible()) {
4347                 /* we're already doing this */
4348                 return;
4349         }
4350
4351         add_route_dialog->set_position (WIN_POS_MOUSE);
4352         add_route_dialog->present();
4353 }
4354
4355 void
4356 ARDOUR_UI::add_route_dialog_response (int r)
4357 {
4358         if (!_session) {
4359                 warning << _("You cannot add tracks or busses without a session already loaded.") << endmsg;
4360                 return;
4361         }
4362
4363         if (!AudioEngine::instance()->running ()) {
4364                 switch (r) {
4365                         case AddRouteDialog::Add:
4366                         case AddRouteDialog::AddAndClose:
4367                                 break;
4368                         default:
4369                                 return;
4370                 }
4371                 add_route_dialog->ArdourDialog::on_response (r);
4372                 ARDOUR_UI_UTILS::engine_is_running ();
4373                 return;
4374         }
4375
4376         int count;
4377
4378         switch (r) {
4379         case AddRouteDialog::Add:
4380                 add_route_dialog->reset_name_edited ();
4381                 break;
4382         case AddRouteDialog::AddAndClose:
4383                 add_route_dialog->ArdourDialog::on_response (r);
4384                 break;
4385         default:
4386                 add_route_dialog->ArdourDialog::on_response (r);
4387                 return;
4388         }
4389
4390         std::string template_path = add_route_dialog->get_template_path();
4391         if (!template_path.empty() && template_path.substr (0, 11) == "urn:ardour:") {
4392                 meta_route_setup (template_path.substr (11));
4393                 return;
4394         }
4395
4396         if ((count = add_route_dialog->count()) <= 0) {
4397                 return;
4398         }
4399
4400         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
4401         const string name_template = add_route_dialog->name_template ();
4402         DisplaySuspender ds;
4403
4404         if (!template_path.empty ()) {
4405                 if (add_route_dialog->name_template_is_default ()) {
4406                         _session->new_route_from_template (count, order, template_path, string ());
4407                 } else {
4408                         _session->new_route_from_template (count, order, template_path, name_template);
4409                 }
4410                 return;
4411         }
4412
4413         ChanCount input_chan= add_route_dialog->channels ();
4414         ChanCount output_chan;
4415         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4416         RouteGroup* route_group = add_route_dialog->route_group ();
4417         AutoConnectOption oac = Config->get_output_auto_connect();
4418         bool strict_io = add_route_dialog->use_strict_io ();
4419
4420         if (oac & AutoConnectMaster) {
4421                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4422                 output_chan.set (DataType::MIDI, 0);
4423         } else {
4424                 output_chan = input_chan;
4425         }
4426
4427         /* XXX do something with name template */
4428
4429         Session::ProcessorChangeBlocker pcb (_session);
4430
4431         switch (add_route_dialog->type_wanted()) {
4432         case AddRouteDialog::AudioTrack:
4433                 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);
4434                 break;
4435         case AddRouteDialog::MidiTrack:
4436                 session_add_midi_route (true, route_group, count, name_template, strict_io, instrument, 0, order);
4437                 break;
4438         case AddRouteDialog::MixedTrack:
4439                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4440                 break;
4441         case AddRouteDialog::AudioBus:
4442                 session_add_audio_route (false, input_chan.n_audio(), output_chan.n_audio(), ARDOUR::Normal, route_group, count, name_template, strict_io, order);
4443                 break;
4444         case AddRouteDialog::MidiBus:
4445                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4446                 break;
4447         case AddRouteDialog::VCAMaster:
4448                 _session->vca_manager().create_vca (count, name_template);
4449                 break;
4450         case AddRouteDialog::FoldbackBus:
4451                 session_add_foldback_bus (count, name_template);
4452                 break;
4453         }
4454 }
4455
4456 void
4457 ARDOUR_UI::stop_video_server (bool ask_confirm)
4458 {
4459         if (!video_server_process && ask_confirm) {
4460                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4461         }
4462         if (video_server_process) {
4463                 if(ask_confirm) {
4464                         ArdourDialog confirm (_("Stop Video-Server"), true);
4465                         Label m (_("Do you really want to stop the Video Server?"));
4466                         confirm.get_vbox()->pack_start (m, true, true);
4467                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4468                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4469                         confirm.show_all ();
4470                         if (confirm.run() == RESPONSE_CANCEL) {
4471                                 return;
4472                         }
4473                 }
4474                 delete video_server_process;
4475                 video_server_process =0;
4476         }
4477 }
4478
4479 void
4480 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4481 {
4482   ARDOUR_UI::start_video_server( float_window, true);
4483 }
4484
4485 bool
4486 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4487 {
4488         if (!_session) {
4489                 return false;
4490         }
4491         if (popup_msg) {
4492                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4493                         if (video_server_process) {
4494                                 popup_error(_("The Video Server is already started."));
4495                         } else {
4496                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4497                         }
4498                 }
4499         }
4500
4501         int firsttime = 0;
4502         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4503                 if (firsttime++) {
4504                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4505                 }
4506                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4507                 if (float_window) {
4508                         video_server_dialog->set_transient_for (*float_window);
4509                 }
4510
4511                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4512                         video_server_dialog->hide();
4513                 } else {
4514                         ResponseType r = (ResponseType) video_server_dialog->run ();
4515                         video_server_dialog->hide();
4516                         if (r != RESPONSE_ACCEPT) { return false; }
4517                         if (video_server_dialog->show_again()) {
4518                                 Config->set_show_video_server_dialog(false);
4519                         }
4520                 }
4521
4522                 std::string icsd_exec = video_server_dialog->get_exec_path();
4523                 std::string icsd_docroot = video_server_dialog->get_docroot();
4524 #ifndef PLATFORM_WINDOWS
4525                 if (icsd_docroot.empty()) {
4526                         icsd_docroot = VideoUtils::video_get_docroot (Config);
4527                 }
4528 #endif
4529
4530                 GStatBuf sb;
4531 #ifdef PLATFORM_WINDOWS
4532                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4533                         /* OK, allow all drive letters */
4534                 } else
4535 #endif
4536                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4537                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4538                         continue;
4539                 }
4540 #ifndef PLATFORM_WINDOWS
4541                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4542                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4543                         warning << _("Given Video Server is not an executable file.") << endmsg;
4544                         continue;
4545                 }
4546 #else
4547                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4548                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4549                         warning << _("Given Video Server is not an executable file.") << endmsg;
4550                         continue;
4551                 }
4552 #endif
4553
4554                 char **argp;
4555                 argp=(char**) calloc(9,sizeof(char*));
4556                 argp[0] = strdup(icsd_exec.c_str());
4557                 argp[1] = strdup("-P");
4558                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4559                 argp[3] = strdup("-p");
4560                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4561                 argp[5] = strdup("-C");
4562                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4563                 argp[7] = strdup(icsd_docroot.c_str());
4564                 argp[8] = 0;
4565                 stop_video_server();
4566
4567 #ifdef PLATFORM_WINDOWS
4568                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4569                         /* OK, allow all drive letters */
4570                 } else
4571 #endif
4572                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4573                         Config->set_video_advanced_setup(false);
4574                 } else {
4575                         std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/";
4576                         Config->set_video_server_url(url_str);
4577                         Config->set_video_server_docroot(icsd_docroot);
4578                         Config->set_video_advanced_setup(true);
4579                 }
4580
4581                 if (video_server_process) {
4582                         delete video_server_process;
4583                 }
4584
4585                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4586                 if (video_server_process->start()) {
4587                         warning << _("Cannot launch the video-server") << endmsg;
4588                         continue;
4589                 }
4590                 int timeout = 120; // 6 sec
4591                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4592                         Glib::usleep (50000);
4593                         gui_idle_handler();
4594                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4595                 }
4596                 if (timeout <= 0) {
4597                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4598                 } else {
4599                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4600                                 delete video_server_process;
4601                                 video_server_process = 0;
4602                         }
4603                 }
4604         }
4605         return true;
4606 }
4607
4608 void
4609 ARDOUR_UI::add_video (Gtk::Window* float_window)
4610 {
4611         if (!_session) {
4612                 return;
4613         }
4614
4615         if (!start_video_server(float_window, false)) {
4616                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4617                 return;
4618         }
4619
4620         if (float_window) {
4621                 add_video_dialog->set_transient_for (*float_window);
4622         }
4623
4624         if (add_video_dialog->is_visible()) {
4625                 /* we're already doing this */
4626                 return;
4627         }
4628
4629         ResponseType r = (ResponseType) add_video_dialog->run ();
4630         add_video_dialog->hide();
4631         if (r != RESPONSE_ACCEPT) { return; }
4632
4633         bool local_file, orig_local_file;
4634         std::string path = add_video_dialog->file_name(local_file);
4635
4636         std::string orig_path = path;
4637         orig_local_file = local_file;
4638
4639         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4640
4641         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4642                 warning << string_compose(_("could not open %1"), path) << endmsg;
4643                 return;
4644         }
4645         if (!local_file && path.length() == 0) {
4646                 warning << _("no video-file selected") << endmsg;
4647                 return;
4648         }
4649
4650         std::string audio_from_video;
4651         bool detect_ltc = false;
4652
4653         switch (add_video_dialog->import_option()) {
4654                 case VTL_IMPORT_TRANSCODE:
4655                         {
4656                                 TranscodeVideoDialog *transcode_video_dialog;
4657                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4658                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4659                                 transcode_video_dialog->hide();
4660                                 if (r != RESPONSE_ACCEPT) {
4661                                         delete transcode_video_dialog;
4662                                         return;
4663                                 }
4664
4665                                 audio_from_video = transcode_video_dialog->get_audiofile();
4666
4667                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4668                                         detect_ltc = true;
4669                                 }
4670                                 else if (!audio_from_video.empty()) {
4671                                         editor->embed_audio_from_video(
4672                                                         audio_from_video,
4673                                                         video_timeline->get_offset(),
4674                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4675                                                         );
4676                                 }
4677                                 switch (transcode_video_dialog->import_option()) {
4678                                         case VTL_IMPORT_TRANSCODED:
4679                                                 path = transcode_video_dialog->get_filename();
4680                                                 local_file = true;
4681                                                 break;
4682                                         case VTL_IMPORT_REFERENCE:
4683                                                 break;
4684                                         default:
4685                                                 delete transcode_video_dialog;
4686                                                 return;
4687                                 }
4688                                 delete transcode_video_dialog;
4689                         }
4690                         break;
4691                 default:
4692                 case VTL_IMPORT_NONE:
4693                         break;
4694         }
4695
4696         /* strip _session->session_directory().video_path() from video file if possible */
4697         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4698                  path=path.substr(_session->session_directory().video_path().size());
4699                  if (path.at(0) == G_DIR_SEPARATOR) {
4700                          path=path.substr(1);
4701                  }
4702         }
4703
4704         video_timeline->set_update_session_fps(auto_set_session_fps);
4705
4706         if (video_timeline->video_file_info(path, local_file)) {
4707                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4708                 node->set_property (X_("Filename"), path);
4709                 node->set_property (X_("AutoFPS"), auto_set_session_fps);
4710                 node->set_property (X_("LocalFile"), local_file);
4711                 if (orig_local_file) {
4712                         node->set_property (X_("OriginalVideoFile"), orig_path);
4713                 } else {
4714                         node->remove_property (X_("OriginalVideoFile"));
4715                 }
4716                 _session->add_extra_xml (*node);
4717                 _session->set_dirty ();
4718
4719                 if (!audio_from_video.empty() && detect_ltc) {
4720                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4721
4722                         try {
4723                                 /* TODO ask user about TV standard (LTC alignment if any) */
4724                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4725                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4726
4727                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC samples to decode*/ 15);
4728
4729                                 /* TODO seek near end of file, and read LTC until end.
4730                                  * if it fails to find any LTC samples, scan complete file
4731                                  *
4732                                  * calculate drift of LTC compared to video-duration,
4733                                  * ask user for reference (timecode from start/mid/end)
4734                                  */
4735                         } catch (...) {
4736                                 // LTCFileReader will have written error messages
4737                         }
4738
4739                         ::g_unlink(audio_from_video.c_str());
4740
4741                         if (ltc_seq.size() == 0) {
4742                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4743                         } else {
4744                                 /* the very first TC in the file is somteimes not aligned properly */
4745                                 int i = ltc_seq.size() -1;
4746                                 ARDOUR::sampleoffset_t video_start_offset =
4747                                         _session->nominal_sample_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4748                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4749                                 video_timeline->set_offset(video_start_offset);
4750                         }
4751                 }
4752
4753                 _session->maybe_update_session_range(
4754                         std::max(video_timeline->get_offset(), (ARDOUR::sampleoffset_t) 0),
4755                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::sampleoffset_t) 0));
4756
4757
4758                 if (add_video_dialog->launch_xjadeo() && local_file) {
4759                         editor->set_xjadeo_sensitive(true);
4760                         editor->toggle_xjadeo_proc(1);
4761                 } else {
4762                         editor->toggle_xjadeo_proc(0);
4763                 }
4764                 editor->toggle_ruler_video(true);
4765         }
4766 }
4767
4768 void
4769 ARDOUR_UI::remove_video ()
4770 {
4771         video_timeline->close_session();
4772         editor->toggle_ruler_video(false);
4773
4774         /* reset state */
4775         video_timeline->set_offset_locked(false);
4776         video_timeline->set_offset(0);
4777
4778         /* delete session state */
4779         XMLNode* node = new XMLNode(X_("Videotimeline"));
4780         _session->add_extra_xml(*node);
4781         node = new XMLNode(X_("Videomonitor"));
4782         _session->add_extra_xml(*node);
4783         node = new XMLNode(X_("Videoexport"));
4784         _session->add_extra_xml(*node);
4785         stop_video_server();
4786 }
4787
4788 void
4789 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4790 {
4791         if (localcacheonly) {
4792                 video_timeline->vmon_update();
4793         } else {
4794                 video_timeline->flush_cache();
4795         }
4796         editor->queue_visual_videotimeline_update();
4797 }
4798
4799 void
4800 ARDOUR_UI::export_video (bool range)
4801 {
4802         if (ARDOUR::Config->get_show_video_export_info()) {
4803                 ExportVideoInfobox infobox (_session);
4804                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4805                 if (infobox.show_again()) {
4806                         ARDOUR::Config->set_show_video_export_info(false);
4807                 }
4808                 switch (rv) {
4809                         case GTK_RESPONSE_YES:
4810                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4811                                 break;
4812                         default:
4813                                 break;
4814                 }
4815         }
4816         export_video_dialog->set_session (_session);
4817         export_video_dialog->apply_state(editor->get_selection().time, range);
4818         export_video_dialog->run ();
4819         export_video_dialog->hide ();
4820 }
4821
4822 XMLNode*
4823 ARDOUR_UI::preferences_settings () const
4824 {
4825         XMLNode* node = 0;
4826
4827         if (_session) {
4828                 node = _session->instant_xml(X_("Preferences"));
4829         } else {
4830                 node = Config->instant_xml(X_("Preferences"));
4831         }
4832
4833         if (!node) {
4834                 node = new XMLNode (X_("Preferences"));
4835         }
4836
4837         return node;
4838 }
4839
4840 XMLNode*
4841 ARDOUR_UI::mixer_settings () const
4842 {
4843         XMLNode* node = 0;
4844
4845         if (_session) {
4846                 node = _session->instant_xml(X_("Mixer"));
4847         } else {
4848                 node = Config->instant_xml(X_("Mixer"));
4849         }
4850
4851         if (!node) {
4852                 node = new XMLNode (X_("Mixer"));
4853         }
4854
4855         return node;
4856 }
4857
4858 XMLNode*
4859 ARDOUR_UI::main_window_settings () const
4860 {
4861         XMLNode* node = 0;
4862
4863         if (_session) {
4864                 node = _session->instant_xml(X_("Main"));
4865         } else {
4866                 node = Config->instant_xml(X_("Main"));
4867         }
4868
4869         if (!node) {
4870                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4871                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4872                 }
4873         }
4874
4875         if (!node) {
4876                 node = new XMLNode (X_("Main"));
4877         }
4878
4879         return node;
4880 }
4881
4882 XMLNode*
4883 ARDOUR_UI::editor_settings () const
4884 {
4885         XMLNode* node = 0;
4886
4887         if (_session) {
4888                 node = _session->instant_xml(X_("Editor"));
4889         } else {
4890                 node = Config->instant_xml(X_("Editor"));
4891         }
4892
4893         if (!node) {
4894                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4895                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4896                 }
4897         }
4898
4899         if (!node) {
4900                 node = new XMLNode (X_("Editor"));
4901         }
4902
4903         return node;
4904 }
4905
4906 XMLNode*
4907 ARDOUR_UI::keyboard_settings () const
4908 {
4909         XMLNode* node = 0;
4910
4911         node = Config->extra_xml(X_("Keyboard"));
4912
4913         if (!node) {
4914                 node = new XMLNode (X_("Keyboard"));
4915         }
4916
4917         return node;
4918 }
4919
4920 void
4921 ARDOUR_UI::create_xrun_marker (samplepos_t where)
4922 {
4923         if (_session) {
4924                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark, 0);
4925                 _session->locations()->add (location);
4926         }
4927 }
4928
4929 void
4930 ARDOUR_UI::halt_on_xrun_message ()
4931 {
4932         cerr << "HALT on xrun\n";
4933         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4934         msg.run ();
4935 }
4936
4937 void
4938 ARDOUR_UI::xrun_handler (samplepos_t where)
4939 {
4940         if (!_session) {
4941                 return;
4942         }
4943
4944         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4945
4946         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4947                 create_xrun_marker(where);
4948         }
4949
4950         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4951                 halt_on_xrun_message ();
4952         }
4953 }
4954
4955 void
4956 ARDOUR_UI::disk_overrun_handler ()
4957 {
4958         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4959
4960         if (!have_disk_speed_dialog_displayed) {
4961                 have_disk_speed_dialog_displayed = true;
4962                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4963 The disk system on your computer\n\
4964 was not able to keep up with %1.\n\
4965 \n\
4966 Specifically, it failed to write data to disk\n\
4967 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4968                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4969                 msg->show ();
4970         }
4971 }
4972
4973
4974 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4975 static MessageDialog *scan_dlg = NULL;
4976 static ProgressBar   *scan_pbar = NULL;
4977 static HBox          *scan_tbox = NULL;
4978 static Gtk::Button   *scan_timeout_button;
4979
4980 void
4981 ARDOUR_UI::cancel_plugin_scan ()
4982 {
4983         PluginManager::instance().cancel_plugin_scan();
4984 }
4985
4986 void
4987 ARDOUR_UI::cancel_plugin_timeout ()
4988 {
4989         PluginManager::instance().cancel_plugin_timeout();
4990         scan_timeout_button->set_sensitive (false);
4991 }
4992
4993 void
4994 ARDOUR_UI::plugin_scan_timeout (int timeout)
4995 {
4996         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4997                 return;
4998         }
4999         if (timeout > 0) {
5000                 scan_pbar->set_sensitive (false);
5001                 scan_timeout_button->set_sensitive (true);
5002                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
5003                 scan_tbox->show();
5004         } else {
5005                 scan_pbar->set_sensitive (false);
5006                 scan_timeout_button->set_sensitive (false);
5007         }
5008         gui_idle_handler();
5009 }
5010
5011 void
5012 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
5013 {
5014         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
5015                 return;
5016         }
5017
5018         const bool cancelled = PluginManager::instance().cancelled();
5019         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
5020                 if (cancelled && scan_dlg->is_mapped()) {
5021                         scan_dlg->hide();
5022                         gui_idle_handler();
5023                         return;
5024                 }
5025                 if (cancelled || !can_cancel) {
5026                         return;
5027                 }
5028         }
5029
5030         static Gtk::Button *cancel_button;
5031         if (!scan_dlg) {
5032                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
5033                 VBox* vbox = scan_dlg->get_vbox();
5034                 vbox->set_size_request(400,-1);
5035                 scan_dlg->set_title (_("Scanning for plugins"));
5036
5037                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
5038                 cancel_button->set_name ("EditorGTKButton");
5039                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
5040                 cancel_button->show();
5041
5042                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
5043
5044                 scan_tbox = manage( new HBox() );
5045
5046                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
5047                 scan_timeout_button->set_name ("EditorGTKButton");
5048                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
5049                 scan_timeout_button->show();
5050
5051                 scan_pbar = manage(new ProgressBar());
5052                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
5053                 scan_pbar->set_text(_("Scan Timeout"));
5054                 scan_pbar->show();
5055
5056                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
5057                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
5058
5059                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
5060         }
5061
5062         assert(scan_dlg && scan_tbox && cancel_button);
5063
5064         if (type == X_("closeme")) {
5065                 scan_tbox->hide();
5066                 scan_dlg->hide();
5067         } else {
5068                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
5069                 scan_dlg->show();
5070         }
5071         if (!can_cancel || !cancelled) {
5072                 scan_timeout_button->set_sensitive(false);
5073         }
5074         cancel_button->set_sensitive(can_cancel && !cancelled);
5075
5076         gui_idle_handler();
5077 }
5078
5079 void
5080 ARDOUR_UI::gui_idle_handler ()
5081 {
5082         int timeout = 30;
5083         /* due to idle calls, gtk_events_pending() may always return true */
5084         while (gtk_events_pending() && --timeout) {
5085                 gtk_main_iteration ();
5086         }
5087 }
5088
5089 void
5090 ARDOUR_UI::disk_underrun_handler ()
5091 {
5092         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
5093
5094         if (!have_disk_speed_dialog_displayed) {
5095                 have_disk_speed_dialog_displayed = true;
5096                 MessageDialog* msg = new MessageDialog (
5097                         _main_window, string_compose (_("The disk system on your computer\n\
5098 was not able to keep up with %1.\n\
5099 \n\
5100 Specifically, it failed to read data from disk\n\
5101 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
5102                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
5103                 msg->show ();
5104         }
5105 }
5106
5107 void
5108 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
5109 {
5110         have_disk_speed_dialog_displayed = false;
5111         delete msg;
5112 }
5113
5114 void
5115 ARDOUR_UI::session_dialog (std::string msg)
5116 {
5117         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
5118
5119         MessageDialog* d;
5120
5121         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
5122         d->show_all ();
5123         d->run ();
5124         delete d;
5125 }
5126
5127 int
5128 ARDOUR_UI::pending_state_dialog ()
5129 {
5130         HBox* hbox = manage (new HBox());
5131         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
5132         ArdourDialog dialog (_("Crash Recovery"), true);
5133         Label  message (string_compose (_("\
5134 This session appears to have been in the\n\
5135 middle of recording when %1 or\n\
5136 the computer was shutdown.\n\
5137 \n\
5138 %1 can recover any captured audio for\n\
5139 you, or it can ignore it. Please decide\n\
5140 what you would like to do.\n"), PROGRAM_NAME));
5141         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5142         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5143         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5144         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5145         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
5146         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
5147         dialog.set_default_response (RESPONSE_ACCEPT);
5148         dialog.set_position (WIN_POS_CENTER);
5149         message.show();
5150         image->show();
5151         hbox->show();
5152
5153         switch (dialog.run ()) {
5154         case RESPONSE_ACCEPT:
5155                 return 1;
5156         default:
5157                 return 0;
5158         }
5159 }
5160
5161 int
5162 ARDOUR_UI::sr_mismatch_dialog (samplecnt_t desired, samplecnt_t actual)
5163 {
5164         HBox* hbox = new HBox();
5165         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
5166         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
5167         Label  message (string_compose (_("\
5168 This session was created with a sample rate of %1 Hz, but\n\
5169 %2 is currently running at %3 Hz.  If you load this session,\n\
5170 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
5171
5172         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5173         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5174         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5175         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5176         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
5177         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
5178         dialog.set_default_response (RESPONSE_ACCEPT);
5179         dialog.set_position (WIN_POS_CENTER);
5180         message.show();
5181         image->show();
5182         hbox->show();
5183
5184         switch (dialog.run()) {
5185         case RESPONSE_ACCEPT:
5186                 return 0;
5187         default:
5188                 break;
5189         }
5190
5191         return 1;
5192 }
5193
5194 void
5195 ARDOUR_UI::sr_mismatch_message (samplecnt_t desired, samplecnt_t actual)
5196 {
5197         MessageDialog msg (string_compose (_("\
5198 This session was created with a sample rate of %1 Hz, but\n\
5199 %2 is currently running at %3 Hz.\n\
5200 Audio will be recorded and played at the wrong sample rate.\n\
5201 Re-Configure the Audio Engine in\n\
5202 Menu > Window > Audio/Midi Setup"),
5203                                 desired, PROGRAM_NAME, actual),
5204                         true,
5205                         Gtk::MESSAGE_WARNING);
5206         msg.run ();
5207 }
5208
5209 void
5210 ARDOUR_UI::use_config ()
5211 {
5212         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
5213         if (node) {
5214                 set_transport_controllable_state (*node);
5215         }
5216 }
5217
5218 void
5219 ARDOUR_UI::update_transport_clocks (samplepos_t pos)
5220 {
5221         switch (UIConfiguration::instance().get_primary_clock_delta_mode()) {
5222                 case NoDelta:
5223                         primary_clock->set (pos);
5224                         break;
5225                 case DeltaEditPoint:
5226                         primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5227                         break;
5228                 case DeltaOriginMarker:
5229                         {
5230                                 Location* loc = _session->locations()->clock_origin_location ();
5231                                 primary_clock->set (pos, false, loc ? loc->start() : 0);
5232                         }
5233                         break;
5234         }
5235
5236         switch (UIConfiguration::instance().get_secondary_clock_delta_mode()) {
5237                 case NoDelta:
5238                         secondary_clock->set (pos);
5239                         break;
5240                 case DeltaEditPoint:
5241                         secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5242                         break;
5243                 case DeltaOriginMarker:
5244                         {
5245                                 Location* loc = _session->locations()->clock_origin_location ();
5246                                 secondary_clock->set (pos, false, loc ? loc->start() : 0);
5247                         }
5248                         break;
5249         }
5250
5251         if (big_clock_window) {
5252                 big_clock->set (pos);
5253         }
5254         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
5255 }
5256
5257
5258 void
5259 ARDOUR_UI::record_state_changed ()
5260 {
5261         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
5262
5263         if (!_session) {
5264                 /* why bother - the clock isn't visible */
5265                 return;
5266         }
5267
5268         ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording());
5269
5270         if (big_clock_window) {
5271                 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
5272                         big_clock->set_active (true);
5273                 } else {
5274                         big_clock->set_active (false);
5275                 }
5276         }
5277
5278 }
5279
5280 bool
5281 ARDOUR_UI::first_idle ()
5282 {
5283         if (_session) {
5284                 _session->allow_auto_play (true);
5285         }
5286
5287         if (editor) {
5288                 editor->first_idle();
5289         }
5290
5291         /* in 1 second, hide the splash screen
5292          *
5293          * Consider hiding it *now*. If a user opens opens a dialog
5294          * during that one second while the splash is still visible,
5295          * the dialog will push-back the splash.
5296          * Closing the dialog later will pop it back.
5297          */
5298         Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
5299
5300         Keyboard::set_can_save_keybindings (true);
5301         return false;
5302 }
5303
5304 void
5305 ARDOUR_UI::store_clock_modes ()
5306 {
5307         XMLNode* node = new XMLNode(X_("ClockModes"));
5308
5309         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
5310                 XMLNode* child = new XMLNode (X_("Clock"));
5311
5312                 child->set_property (X_("name"), (*x)->name());
5313                 child->set_property (X_("mode"), (*x)->mode());
5314                 child->set_property (X_("on"), (*x)->on());
5315
5316                 node->add_child_nocopy (*child);
5317         }
5318
5319         _session->add_extra_xml (*node);
5320         _session->set_dirty ();
5321 }
5322
5323 void
5324 ARDOUR_UI::setup_profile ()
5325 {
5326         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5327                 Profile->set_small_screen ();
5328         }
5329
5330         if (g_getenv ("TRX")) {
5331                 Profile->set_trx ();
5332         }
5333
5334         if (g_getenv ("MIXBUS")) {
5335                 Profile->set_mixbus ();
5336         }
5337 }
5338
5339 int
5340 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5341 {
5342         MissingFileDialog dialog (s, str, type);
5343
5344         dialog.show ();
5345         dialog.present ();
5346
5347         int result = dialog.run ();
5348         dialog.hide ();
5349
5350         switch (result) {
5351         case RESPONSE_OK:
5352                 break;
5353         default:
5354                 return 1; // quit entire session load
5355         }
5356
5357         result = dialog.get_action ();
5358
5359         return result;
5360 }
5361
5362 int
5363 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5364 {
5365         AmbiguousFileDialog dialog (file, hits);
5366
5367         dialog.show ();
5368         dialog.present ();
5369
5370         dialog.run ();
5371
5372         return dialog.get_which ();
5373 }
5374
5375 /** Allocate our thread-local buffers */
5376 void
5377 ARDOUR_UI::get_process_buffers ()
5378 {
5379         _process_thread->get_buffers ();
5380 }
5381
5382 /** Drop our thread-local buffers */
5383 void
5384 ARDOUR_UI::drop_process_buffers ()
5385 {
5386         _process_thread->drop_buffers ();
5387 }
5388
5389 void
5390 ARDOUR_UI::feedback_detected ()
5391 {
5392         _feedback_exists = true;
5393 }
5394
5395 void
5396 ARDOUR_UI::successful_graph_sort ()
5397 {
5398         _feedback_exists = false;
5399 }
5400
5401 void
5402 ARDOUR_UI::midi_panic ()
5403 {
5404         if (_session) {
5405                 _session->midi_panic();
5406         }
5407 }
5408
5409 void
5410 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5411 {
5412         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5413         const char* end_big = "</span>";
5414         const char* start_mono = "<tt>";
5415         const char* end_mono = "</tt>";
5416
5417         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5418                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5419                                              "From now on, use the backup copy with older versions of %3"),
5420                                            xml_path, backup_path, PROGRAM_NAME,
5421                                            start_big, end_big,
5422                                            start_mono, end_mono), true);
5423
5424         msg.run ();
5425 }
5426
5427 void
5428 ARDOUR_UI::reset_peak_display ()
5429 {
5430         if (!_session || !_session->master_out() || !editor_meter) return;
5431         editor_meter->clear_meters();
5432         editor_meter_max_peak = -INFINITY;
5433         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5434 }
5435
5436 void
5437 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5438 {
5439         if (!_session || !_session->master_out()) return;
5440         if (group == _session->master_out()->route_group()) {
5441                 reset_peak_display ();
5442         }
5443 }
5444
5445 void
5446 ARDOUR_UI::reset_route_peak_display (Route* route)
5447 {
5448         if (!_session || !_session->master_out()) return;
5449         if (_session->master_out().get() == route) {
5450                 reset_peak_display ();
5451         }
5452 }
5453
5454 int
5455 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5456 {
5457         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5458         audio_midi_setup->set_position (WIN_POS_CENTER);
5459
5460         if (desired_sample_rate != 0) {
5461                 if (Config->get_try_autostart_engine () || g_getenv ("ARDOUR_TRY_AUTOSTART_ENGINE")) {
5462                         audio_midi_setup->try_autostart ();
5463                         if (ARDOUR::AudioEngine::instance()->running()) {
5464                                 return 0;
5465                         }
5466                 }
5467         }
5468
5469         while (true) {
5470                 int response = audio_midi_setup->run();
5471                 switch (response) {
5472                 case Gtk::RESPONSE_DELETE_EVENT:
5473                         // after latency callibration engine may run,
5474                         // Running() signal was emitted, but dialog will not
5475                         // have emitted a response. The user needs to close
5476                         // the dialog -> Gtk::RESPONSE_DELETE_EVENT
5477                         if (!AudioEngine::instance()->running()) {
5478                                 return -1;
5479                         }
5480                         // fall through
5481                 default:
5482                         if (!AudioEngine::instance()->running()) {
5483                                 continue;
5484                         }
5485                         audio_midi_setup->hide ();
5486                         return 0;
5487                 }
5488         }
5489 }
5490
5491
5492 gint
5493 ARDOUR_UI::transport_numpad_timeout ()
5494 {
5495         _numpad_locate_happening = false;
5496         if (_numpad_timeout_connection.connected() )
5497                 _numpad_timeout_connection.disconnect();
5498         return 1;
5499 }
5500
5501 void
5502 ARDOUR_UI::transport_numpad_decimal ()
5503 {
5504         _numpad_timeout_connection.disconnect();
5505
5506         if (_numpad_locate_happening) {
5507                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5508                 _numpad_locate_happening = false;
5509         } else {
5510                 _pending_locate_num = 0;
5511                 _numpad_locate_happening = true;
5512                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5513         }
5514 }
5515
5516 void
5517 ARDOUR_UI::transport_numpad_event (int num)
5518 {
5519         if ( _numpad_locate_happening ) {
5520                 _pending_locate_num = _pending_locate_num*10 + num;
5521         } else {
5522                 switch (num) {
5523                         case 0: toggle_roll(false, false);                           break;
5524                         case 1: transport_rewind(1);                                 break;
5525                         case 2: transport_forward(1);                                break;
5526                         case 3: transport_record(true);                              break;
5527                         case 4: toggle_session_auto_loop();                          break;
5528                         case 5: transport_record(false); toggle_session_auto_loop(); break;
5529                         case 6: toggle_punch();                                      break;
5530                         case 7: toggle_click();                                      break;
5531                         case 8: toggle_auto_return();                                break;
5532                         case 9: toggle_follow_edits();                               break;
5533                 }
5534         }
5535 }
5536
5537 void
5538 ARDOUR_UI::set_flat_buttons ()
5539 {
5540         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5541 }
5542
5543 void
5544 ARDOUR_UI::audioengine_became_silent ()
5545 {
5546         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5547                            true,
5548                            Gtk::MESSAGE_WARNING,
5549                            Gtk::BUTTONS_NONE,
5550                            true);
5551
5552         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5553
5554         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5555         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5556         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5557         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5558         Gtk::HBox pay_button_box;
5559         Gtk::HBox subscribe_button_box;
5560
5561         pay_button_box.pack_start (pay_button, true, false);
5562         subscribe_button_box.pack_start (subscribe_button, true, false);
5563
5564         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 */
5565
5566         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5567         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5568
5569         msg.get_vbox()->pack_start (pay_label);
5570         msg.get_vbox()->pack_start (pay_button_box);
5571         msg.get_vbox()->pack_start (subscribe_label);
5572         msg.get_vbox()->pack_start (subscribe_button_box);
5573
5574         msg.get_vbox()->show_all ();
5575
5576         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5577         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5578         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5579
5580         int r = msg.run ();
5581
5582         switch (r) {
5583         case Gtk::RESPONSE_YES:
5584                 AudioEngine::instance()->reset_silence_countdown ();
5585                 break;
5586
5587         case Gtk::RESPONSE_NO:
5588                 /* save and quit */
5589                 save_state_canfail ("");
5590                 exit (EXIT_SUCCESS);
5591                 break;
5592
5593         case Gtk::RESPONSE_CANCEL:
5594         default:
5595                 /* don't reset, save session and exit */
5596                 break;
5597         }
5598 }
5599
5600 void
5601 ARDOUR_UI::hide_application ()
5602 {
5603         Application::instance ()-> hide ();
5604 }
5605
5606 void
5607 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5608 {
5609         /* icons, titles, WM stuff */
5610
5611         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5612
5613         if (window_icons.empty()) {
5614                 Glib::RefPtr<Gdk::Pixbuf> icon;
5615                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
5616                         window_icons.push_back (icon);
5617                 }
5618                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
5619                         window_icons.push_back (icon);
5620                 }
5621                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
5622                         window_icons.push_back (icon);
5623                 }
5624                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
5625                         window_icons.push_back (icon);
5626                 }
5627         }
5628
5629         if (!window_icons.empty()) {
5630                 window.set_default_icon_list (window_icons);
5631         }
5632
5633         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5634
5635         if (!name.empty()) {
5636                 title += name;
5637         }
5638
5639         window.set_title (title.get_string());
5640         window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
5641
5642         window.set_flags (CAN_FOCUS);
5643         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5644
5645         /* This is a hack to ensure that GTK-accelerators continue to
5646          * work. Once we switch over to entirely native bindings, this will be
5647          * unnecessary and should be removed
5648          */
5649         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5650
5651         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5652         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5653         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5654         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5655 }
5656
5657 bool
5658 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5659 {
5660         Gtkmm2ext::Bindings* bindings = 0;
5661         Gtk::Window* window = 0;
5662
5663         /* until we get ardour bindings working, we are not handling key
5664          * releases yet.
5665          */
5666
5667         if (ev->type != GDK_KEY_PRESS) {
5668                 return false;
5669         }
5670
5671         if (event_window == &_main_window) {
5672
5673                 window = event_window;
5674
5675                 /* find current tab contents */
5676
5677                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5678
5679                 /* see if it uses the ardour binding system */
5680
5681                 if (w) {
5682                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5683                 }
5684
5685                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5686
5687         } else {
5688
5689                 window = event_window;
5690
5691                 /* see if window uses ardour binding system */
5692
5693                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5694         }
5695
5696         /* An empty binding set is treated as if it doesn't exist */
5697
5698         if (bindings && bindings->empty()) {
5699                 bindings = 0;
5700         }
5701
5702         return key_press_focus_accelerator_handler (*window, ev, bindings);
5703 }
5704
5705 static Gtkmm2ext::Bindings*
5706 get_bindings_from_widget_heirarchy (GtkWidget** w)
5707 {
5708         void* p = NULL;
5709
5710         while (*w) {
5711                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
5712                         break;
5713                 }
5714                 *w = gtk_widget_get_parent (*w);
5715         }
5716
5717         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5718 }
5719
5720 bool
5721 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5722 {
5723         GtkWindow* win = window.gobj();
5724         GtkWidget* focus = gtk_window_get_focus (win);
5725         GtkWidget* binding_widget = focus;
5726         bool special_handling_of_unmodified_accelerators = false;
5727         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5728
5729         if (focus) {
5730
5731                 /* some widget has keyboard focus */
5732
5733                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5734
5735                         /* A particular kind of focusable widget currently has keyboard
5736                          * focus. All unmodified key events should go to that widget
5737                          * first and not be used as an accelerator by default
5738                          */
5739
5740                         special_handling_of_unmodified_accelerators = true;
5741
5742                 } else {
5743
5744                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5745                         if (focus_bindings) {
5746                                 bindings = focus_bindings;
5747                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5748                         }
5749                 }
5750         }
5751
5752         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",
5753                                                           win,
5754                                                           ev->keyval,
5755                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
5756                                                           special_handling_of_unmodified_accelerators,
5757                                                           Keyboard::some_magic_widget_has_focus(),
5758                                                           focus,
5759                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5760                                                           ((ev->state & mask) ? "yes" : "no"),
5761                                                           window.get_title()));
5762
5763         /* This exists to allow us to override the way GTK handles
5764            key events. The normal sequence is:
5765
5766            a) event is delivered to a GtkWindow
5767            b) accelerators/mnemonics are activated
5768            c) if (b) didn't handle the event, propagate to
5769                the focus widget and/or focus chain
5770
5771            The problem with this is that if the accelerators include
5772            keys without modifiers, such as the space bar or the
5773            letter "e", then pressing the key while typing into
5774            a text entry widget results in the accelerator being
5775            activated, instead of the desired letter appearing
5776            in the text entry.
5777
5778            There is no good way of fixing this, but this
5779            represents a compromise. The idea is that
5780            key events involving modifiers (not Shift)
5781            get routed into the activation pathway first, then
5782            get propagated to the focus widget if necessary.
5783
5784            If the key event doesn't involve modifiers,
5785            we deliver to the focus widget first, thus allowing
5786            it to get "normal text" without interference
5787            from acceleration.
5788
5789            Of course, this can also be problematic: if there
5790            is a widget with focus, then it will swallow
5791            all "normal text" accelerators.
5792         */
5793
5794
5795         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5796
5797                 /* no special handling or there are modifiers in effect: accelerate first */
5798
5799                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5800                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5801                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5802
5803                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5804                 KeyboardKey k (ev->state, ev->keyval);
5805
5806                 while (bindings) {
5807
5808                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5809
5810                         if (bindings->activate (k, Bindings::Press)) {
5811                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5812                                 return true;
5813                         }
5814
5815                         if (binding_widget) {
5816                                 binding_widget = gtk_widget_get_parent (binding_widget);
5817                                 if (binding_widget) {
5818                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5819                                 } else {
5820                                         bindings = 0;
5821                                 }
5822                         } else {
5823                                 bindings = 0;
5824                         }
5825                 }
5826
5827                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
5828
5829                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5830                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5831                         return true;
5832                 }
5833
5834                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5835
5836                 if (gtk_window_propagate_key_event (win, ev)) {
5837                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5838                         return true;
5839                 }
5840
5841         } else {
5842
5843                 /* no modifiers, propagate first */
5844
5845                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5846
5847                 if (gtk_window_propagate_key_event (win, ev)) {
5848                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5849                         return true;
5850                 }
5851
5852                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5853                 KeyboardKey k (ev->state, ev->keyval);
5854
5855                 while (bindings) {
5856
5857                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5858
5859
5860                         if (bindings->activate (k, Bindings::Press)) {
5861                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5862                                 return true;
5863                         }
5864
5865                         if (binding_widget) {
5866                                 binding_widget = gtk_widget_get_parent (binding_widget);
5867                                 if (binding_widget) {
5868                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5869                                 } else {
5870                                         bindings = 0;
5871                                 }
5872                         } else {
5873                                 bindings = 0;
5874                         }
5875                 }
5876
5877                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
5878
5879                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5880                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5881                         return true;
5882                 }
5883         }
5884
5885         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5886         return true;
5887 }
5888
5889 void
5890 ARDOUR_UI::cancel_solo ()
5891 {
5892         if (_session) {
5893                 _session->cancel_all_solo ();
5894         }
5895 }
5896
5897 void
5898 ARDOUR_UI::reset_focus (Gtk::Widget* w)
5899 {
5900         /* this resets focus to the first focusable parent of the given widget,
5901          * or, if there is no focusable parent, cancels focus in the toplevel
5902          * window that the given widget is packed into (if there is one).
5903          */
5904
5905         if (!w) {
5906                 return;
5907         }
5908
5909         Gtk::Widget* top = w->get_toplevel();
5910
5911         if (!top || !top->is_toplevel()) {
5912                 return;
5913         }
5914
5915         w = w->get_parent ();
5916
5917         while (w) {
5918
5919                 if (w->is_toplevel()) {
5920                         /* Setting the focus widget to a Gtk::Window causes all
5921                          * subsequent calls to ::has_focus() on the nominal
5922                          * focus widget in that window to return
5923                          * false. Workaround: never set focus to the toplevel
5924                          * itself.
5925                          */
5926                         break;
5927                 }
5928
5929                 if (w->get_can_focus ()) {
5930                         Gtk::Window* win = dynamic_cast<Gtk::Window*> (top);
5931                         win->set_focus (*w);
5932                         return;
5933                 }
5934                 w = w->get_parent ();
5935         }
5936
5937         if (top == &_main_window) {
5938
5939         }
5940
5941         /* no focusable parent found, cancel focus in top level window.
5942            C++ API cannot be used for this. Thanks, references.
5943         */
5944
5945         gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
5946
5947 }
5948
5949 void
5950 ARDOUR_UI::monitor_dim_all ()
5951 {
5952         boost::shared_ptr<Route> mon = _session->monitor_out ();
5953         if (!mon) {
5954                 return;
5955         }
5956         boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
5957
5958         Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-dim-all");
5959         _monitor->set_dim_all (tact->get_active());
5960 }
5961
5962 void
5963 ARDOUR_UI::monitor_cut_all ()
5964 {
5965         boost::shared_ptr<Route> mon = _session->monitor_out ();
5966         if (!mon) {
5967                 return;
5968         }
5969         boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
5970
5971         Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-cut-all");
5972         _monitor->set_cut_all (tact->get_active());
5973 }
5974
5975 void
5976 ARDOUR_UI::monitor_mono ()
5977 {
5978         boost::shared_ptr<Route> mon = _session->monitor_out ();
5979         if (!mon) {
5980                 return;
5981         }
5982         boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
5983
5984         Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-mono");
5985         _monitor->set_mono (tact->get_active());
5986 }
5987
5988 Gtk::Menu*
5989 ARDOUR_UI::shared_popup_menu ()
5990 {
5991         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::shared_popup_menu, ignored);
5992
5993         assert (!_shared_popup_menu || !_shared_popup_menu->is_visible());
5994         delete _shared_popup_menu;
5995         _shared_popup_menu = new Gtk::Menu;
5996         return _shared_popup_menu;
5997 }