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