Revert "Show VCA pane whan adding a VCA"
[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         , secondary_clock_spacer (0)
291         , auto_input_button (ArdourButton::led_default_elements)
292         , time_info_box (0)
293         , auto_return_button (ArdourButton::led_default_elements)
294         , follow_edits_button (ArdourButton::led_default_elements)
295         , auditioning_alert_button (_("Audition"))
296         , solo_alert_button (_("Solo"))
297         , feedback_alert_button (_("Feedback"))
298         , error_alert_button ( ArdourButton::just_led_default_elements )
299         , editor_meter_peak_display()
300         , editor_meter(0)
301         , _suspend_editor_meter_callbacks (false)
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 (0);
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 (0);
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).substr (10, string::npos);
775                         output << "</kbd></th><td>" << *l << "</td></tr>" << endl;
776                 }
777                 output << "  </tbody>\n  </table>" << endl;
778
779                 // output this mess to a browser for easiest X-platform use
780                 // it is not pretty HTML, but it works and it's main purpose
781                 // is to create raw html to fit in Ardour's manual with no editing
782                 gchar* file_name;
783                 GError *err = NULL;
784                 gint fd;
785
786                 if ((fd = g_file_open_tmp ("list-of-menu-actionsXXXXXX.html", &file_name, &err)) < 0) {
787                         if (err) {
788                                 error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg;
789                                 g_error_free (err);
790                         }
791                         return;
792                 }
793
794 #ifdef PLATFORM_WINDOWS
795                 ::close (fd);
796 #endif
797
798                 err = NULL;
799
800                 if (!g_file_set_contents (file_name, output.str().c_str(), output.str().size(), &err)) {
801 #ifndef PLATFORM_WINDOWS
802                         ::close (fd);
803 #endif
804                         g_unlink (file_name);
805                         if (err) {
806                                 error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg;
807                                 g_error_free (err);
808                         }
809                         return;
810                 }
811
812 #ifndef PLATFORM_WINDOWS
813                 ::close (fd);
814 #endif
815
816                 PBD::open_uri (string_compose ("file:///%1", file_name));
817
818                 halt_connection.disconnect ();
819                 AudioEngine::instance()->stop ();
820                 exit (0);
821         }
822
823         /* this being a GUI and all, we want peakfiles */
824
825         AudioFileSource::set_build_peakfiles (true);
826         AudioFileSource::set_build_missing_peakfiles (true);
827
828         /* set default clock modes */
829
830         primary_clock->set_mode (AudioClock::Timecode);
831         secondary_clock->set_mode (AudioClock::BBT);
832
833         /* start the time-of-day-clock */
834
835 #ifndef __APPLE__
836         /* OS X provides a nearly-always visible wallclock, so don't be stupid */
837         update_wall_clock ();
838         Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1);
839 #endif
840
841         {
842                 DisplaySuspender ds;
843                 Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
844                 boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
845                 Config->map_parameters (pc);
846
847                 UIConfiguration::instance().map_parameters (pc);
848         }
849 }
850
851 ARDOUR_UI::~ARDOUR_UI ()
852 {
853         UIConfiguration::instance().save_state();
854
855         stop_video_server();
856
857         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
858                 // don't bother at 'real' exit. the OS cleans up for us.
859                 delete big_clock; big_clock = 0;
860                 delete primary_clock; primary_clock = 0;
861                 delete secondary_clock; secondary_clock = 0;
862                 delete _process_thread; _process_thread = 0;
863                 delete time_info_box; time_info_box = 0;
864                 delete meterbridge; meterbridge = 0;
865                 delete luawindow; luawindow = 0;
866                 delete editor; editor = 0;
867                 delete mixer; mixer = 0;
868                 delete rc_option_editor; rc_option_editor = 0; // failed to wrap object warning
869                 delete nsm; nsm = 0;
870                 delete gui_object_state; gui_object_state = 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 (0);
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 (1);
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 (1);
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 (1);
3487                         }
3488
3489                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3490                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3491                                 exit (1);
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 (1);
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 (1);
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
4201         ARDOUR::CleanupReport rep;
4202
4203         editor->prepare_for_cleanup ();
4204
4205         /* do not allow flush until a session is reloaded */
4206
4207         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
4208         if (act) {
4209                 act->set_sensitive (false);
4210         }
4211
4212         if (_session->cleanup_sources (rep)) {
4213                 editor->finish_cleanup ();
4214                 return;
4215         }
4216
4217         editor->finish_cleanup ();
4218
4219         checker.hide();
4220         display_cleanup_results (rep, _("Cleaned Files"), false);
4221 }
4222
4223 void
4224 ARDOUR_UI::flush_trash ()
4225 {
4226         if (_session == 0) {
4227                 /* shouldn't happen: menu item is insensitive */
4228                 return;
4229         }
4230
4231         ARDOUR::CleanupReport rep;
4232
4233         if (_session->cleanup_trash_sources (rep)) {
4234                 return;
4235         }
4236
4237         display_cleanup_results (rep, _("deleted file"), true);
4238 }
4239
4240 void
4241 ARDOUR_UI::cleanup_peakfiles ()
4242 {
4243         if (_session == 0) {
4244                 /* shouldn't happen: menu item is insensitive */
4245                 return;
4246         }
4247
4248         if (! _session->can_cleanup_peakfiles ()) {
4249                 return;
4250         }
4251
4252         // get all region-views in this session
4253         RegionSelection rs;
4254         TrackViewList empty;
4255         empty.clear();
4256         editor->get_regions_after(rs, (samplepos_t) 0, empty);
4257         std::list<RegionView*> views = rs.by_layer();
4258
4259         // remove displayed audio-region-views waveforms
4260         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4261                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4262                 if (!arv) { continue ; }
4263                 arv->delete_waves();
4264         }
4265
4266         // cleanup peak files:
4267         // - stop pending peakfile threads
4268         // - close peakfiles if any
4269         // - remove peak dir in session
4270         // - setup peakfiles (background thread)
4271         _session->cleanup_peakfiles ();
4272
4273         // re-add waves to ARV
4274         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4275                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4276                 if (!arv) { continue ; }
4277                 arv->create_waves();
4278         }
4279 }
4280
4281 PresentationInfo::order_t
4282 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
4283 {
4284         if (editor->get_selection().tracks.empty()) {
4285                 return place == RouteDialogs::First ? 0 : PresentationInfo::max_order;
4286         }
4287
4288         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
4289
4290         /*
4291           we want the new routes to have their order keys set starting from
4292           the highest order key in the selection + 1 (if available).
4293         */
4294
4295         if (place == RouteDialogs::AfterSelection) {
4296                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
4297                 if (rtav) {
4298                         order_hint = rtav->route()->presentation_info().order();
4299                         order_hint++;
4300                 }
4301         } else if (place == RouteDialogs::BeforeSelection) {
4302                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
4303                 if (rtav) {
4304                         order_hint = rtav->route()->presentation_info().order();
4305                 }
4306         } else if (place == RouteDialogs::First) {
4307                 order_hint = 0;
4308         } else {
4309                 /* leave order_hint at max_order */
4310         }
4311
4312         return order_hint;
4313 }
4314
4315 void
4316 ARDOUR_UI::start_duplicate_routes ()
4317 {
4318         if (!duplicate_routes_dialog) {
4319                 duplicate_routes_dialog = new DuplicateRouteDialog;
4320         }
4321
4322         if (duplicate_routes_dialog->restart (_session)) {
4323                 return;
4324         }
4325
4326         duplicate_routes_dialog->present ();
4327 }
4328
4329 void
4330 ARDOUR_UI::add_route ()
4331 {
4332         if (!add_route_dialog.get (false)) {
4333                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
4334         }
4335
4336         if (!_session) {
4337                 return;
4338         }
4339
4340         if (add_route_dialog->is_visible()) {
4341                 /* we're already doing this */
4342                 return;
4343         }
4344
4345         add_route_dialog->set_position (WIN_POS_MOUSE);
4346         add_route_dialog->present();
4347 }
4348
4349 void
4350 ARDOUR_UI::add_route_dialog_response (int r)
4351 {
4352         if (!_session) {
4353                 warning << _("You cannot add tracks or busses without a session already loaded.") << endmsg;
4354                 return;
4355         }
4356
4357         if (!AudioEngine::instance()->running ()) {
4358                 switch (r) {
4359                         case AddRouteDialog::Add:
4360                         case AddRouteDialog::AddAndClose:
4361                                 break;
4362                         default:
4363                                 return;
4364                 }
4365                 add_route_dialog->ArdourDialog::on_response (r);
4366                 ARDOUR_UI_UTILS::engine_is_running ();
4367                 return;
4368         }
4369
4370         int count;
4371
4372         switch (r) {
4373         case AddRouteDialog::Add:
4374                 add_route_dialog->reset_name_edited ();
4375                 break;
4376         case AddRouteDialog::AddAndClose:
4377                 add_route_dialog->ArdourDialog::on_response (r);
4378                 break;
4379         default:
4380                 add_route_dialog->ArdourDialog::on_response (r);
4381                 return;
4382         }
4383
4384         std::string template_path = add_route_dialog->get_template_path();
4385         if (!template_path.empty() && template_path.substr (0, 11) == "urn:ardour:") {
4386                 meta_route_setup (template_path.substr (11));
4387                 return;
4388         }
4389
4390         if ((count = add_route_dialog->count()) <= 0) {
4391                 return;
4392         }
4393
4394         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
4395         const string name_template = add_route_dialog->name_template ();
4396         DisplaySuspender ds;
4397
4398         if (!template_path.empty ()) {
4399                 if (add_route_dialog->name_template_is_default ()) {
4400                         _session->new_route_from_template (count, order, template_path, string ());
4401                 } else {
4402                         _session->new_route_from_template (count, order, template_path, name_template);
4403                 }
4404                 return;
4405         }
4406
4407         ChanCount input_chan= add_route_dialog->channels ();
4408         ChanCount output_chan;
4409         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4410         RouteGroup* route_group = add_route_dialog->route_group ();
4411         AutoConnectOption oac = Config->get_output_auto_connect();
4412         bool strict_io = add_route_dialog->use_strict_io ();
4413
4414         if (oac & AutoConnectMaster) {
4415                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4416                 output_chan.set (DataType::MIDI, 0);
4417         } else {
4418                 output_chan = input_chan;
4419         }
4420
4421         /* XXX do something with name template */
4422
4423         Session::ProcessorChangeBlocker pcb (_session);
4424
4425         switch (add_route_dialog->type_wanted()) {
4426         case AddRouteDialog::AudioTrack:
4427                 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);
4428                 break;
4429         case AddRouteDialog::MidiTrack:
4430                 session_add_midi_route (true, route_group, count, name_template, strict_io, instrument, 0, order);
4431                 break;
4432         case AddRouteDialog::MixedTrack:
4433                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4434                 break;
4435         case AddRouteDialog::AudioBus:
4436                 session_add_audio_route (false, input_chan.n_audio(), output_chan.n_audio(), ARDOUR::Normal, route_group, count, name_template, strict_io, order);
4437                 break;
4438         case AddRouteDialog::MidiBus:
4439                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4440                 break;
4441         case AddRouteDialog::VCAMaster:
4442                 _session->vca_manager().create_vca (count, name_template);
4443                 break;
4444         case AddRouteDialog::FoldbackBus:
4445                 session_add_foldback_bus (count, name_template);
4446                 break;
4447         }
4448 }
4449
4450 void
4451 ARDOUR_UI::stop_video_server (bool ask_confirm)
4452 {
4453         if (!video_server_process && ask_confirm) {
4454                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4455         }
4456         if (video_server_process) {
4457                 if(ask_confirm) {
4458                         ArdourDialog confirm (_("Stop Video-Server"), true);
4459                         Label m (_("Do you really want to stop the Video Server?"));
4460                         confirm.get_vbox()->pack_start (m, true, true);
4461                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4462                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4463                         confirm.show_all ();
4464                         if (confirm.run() == RESPONSE_CANCEL) {
4465                                 return;
4466                         }
4467                 }
4468                 delete video_server_process;
4469                 video_server_process =0;
4470         }
4471 }
4472
4473 void
4474 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4475 {
4476   ARDOUR_UI::start_video_server( float_window, true);
4477 }
4478
4479 bool
4480 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4481 {
4482         if (!_session) {
4483                 return false;
4484         }
4485         if (popup_msg) {
4486                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4487                         if (video_server_process) {
4488                                 popup_error(_("The Video Server is already started."));
4489                         } else {
4490                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4491                         }
4492                 }
4493         }
4494
4495         int firsttime = 0;
4496         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4497                 if (firsttime++) {
4498                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4499                 }
4500                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4501                 if (float_window) {
4502                         video_server_dialog->set_transient_for (*float_window);
4503                 }
4504
4505                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4506                         video_server_dialog->hide();
4507                 } else {
4508                         ResponseType r = (ResponseType) video_server_dialog->run ();
4509                         video_server_dialog->hide();
4510                         if (r != RESPONSE_ACCEPT) { return false; }
4511                         if (video_server_dialog->show_again()) {
4512                                 Config->set_show_video_server_dialog(false);
4513                         }
4514                 }
4515
4516                 std::string icsd_exec = video_server_dialog->get_exec_path();
4517                 std::string icsd_docroot = video_server_dialog->get_docroot();
4518 #ifndef PLATFORM_WINDOWS
4519                 if (icsd_docroot.empty()) {
4520                         icsd_docroot = VideoUtils::video_get_docroot (Config);
4521                 }
4522 #endif
4523
4524                 GStatBuf sb;
4525 #ifdef PLATFORM_WINDOWS
4526                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4527                         /* OK, allow all drive letters */
4528                 } else
4529 #endif
4530                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4531                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4532                         continue;
4533                 }
4534 #ifndef PLATFORM_WINDOWS
4535                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4536                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4537                         warning << _("Given Video Server is not an executable file.") << endmsg;
4538                         continue;
4539                 }
4540 #else
4541                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4542                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4543                         warning << _("Given Video Server is not an executable file.") << endmsg;
4544                         continue;
4545                 }
4546 #endif
4547
4548                 char **argp;
4549                 argp=(char**) calloc(9,sizeof(char*));
4550                 argp[0] = strdup(icsd_exec.c_str());
4551                 argp[1] = strdup("-P");
4552                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4553                 argp[3] = strdup("-p");
4554                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4555                 argp[5] = strdup("-C");
4556                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4557                 argp[7] = strdup(icsd_docroot.c_str());
4558                 argp[8] = 0;
4559                 stop_video_server();
4560
4561 #ifdef PLATFORM_WINDOWS
4562                 if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
4563                         /* OK, allow all drive letters */
4564                 } else
4565 #endif
4566                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4567                         Config->set_video_advanced_setup(false);
4568                 } else {
4569                         std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/";
4570                         Config->set_video_server_url(url_str);
4571                         Config->set_video_server_docroot(icsd_docroot);
4572                         Config->set_video_advanced_setup(true);
4573                 }
4574
4575                 if (video_server_process) {
4576                         delete video_server_process;
4577                 }
4578
4579                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4580                 if (video_server_process->start()) {
4581                         warning << _("Cannot launch the video-server") << endmsg;
4582                         continue;
4583                 }
4584                 int timeout = 120; // 6 sec
4585                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4586                         Glib::usleep (50000);
4587                         gui_idle_handler();
4588                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4589                 }
4590                 if (timeout <= 0) {
4591                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4592                 } else {
4593                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4594                                 delete video_server_process;
4595                                 video_server_process = 0;
4596                         }
4597                 }
4598         }
4599         return true;
4600 }
4601
4602 void
4603 ARDOUR_UI::add_video (Gtk::Window* float_window)
4604 {
4605         if (!_session) {
4606                 return;
4607         }
4608
4609         if (!start_video_server(float_window, false)) {
4610                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4611                 return;
4612         }
4613
4614         if (float_window) {
4615                 add_video_dialog->set_transient_for (*float_window);
4616         }
4617
4618         if (add_video_dialog->is_visible()) {
4619                 /* we're already doing this */
4620                 return;
4621         }
4622
4623         ResponseType r = (ResponseType) add_video_dialog->run ();
4624         add_video_dialog->hide();
4625         if (r != RESPONSE_ACCEPT) { return; }
4626
4627         bool local_file, orig_local_file;
4628         std::string path = add_video_dialog->file_name(local_file);
4629
4630         std::string orig_path = path;
4631         orig_local_file = local_file;
4632
4633         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4634
4635         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4636                 warning << string_compose(_("could not open %1"), path) << endmsg;
4637                 return;
4638         }
4639         if (!local_file && path.length() == 0) {
4640                 warning << _("no video-file selected") << endmsg;
4641                 return;
4642         }
4643
4644         std::string audio_from_video;
4645         bool detect_ltc = false;
4646
4647         switch (add_video_dialog->import_option()) {
4648                 case VTL_IMPORT_TRANSCODE:
4649                         {
4650                                 TranscodeVideoDialog *transcode_video_dialog;
4651                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4652                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4653                                 transcode_video_dialog->hide();
4654                                 if (r != RESPONSE_ACCEPT) {
4655                                         delete transcode_video_dialog;
4656                                         return;
4657                                 }
4658
4659                                 audio_from_video = transcode_video_dialog->get_audiofile();
4660
4661                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4662                                         detect_ltc = true;
4663                                 }
4664                                 else if (!audio_from_video.empty()) {
4665                                         editor->embed_audio_from_video(
4666                                                         audio_from_video,
4667                                                         video_timeline->get_offset(),
4668                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4669                                                         );
4670                                 }
4671                                 switch (transcode_video_dialog->import_option()) {
4672                                         case VTL_IMPORT_TRANSCODED:
4673                                                 path = transcode_video_dialog->get_filename();
4674                                                 local_file = true;
4675                                                 break;
4676                                         case VTL_IMPORT_REFERENCE:
4677                                                 break;
4678                                         default:
4679                                                 delete transcode_video_dialog;
4680                                                 return;
4681                                 }
4682                                 delete transcode_video_dialog;
4683                         }
4684                         break;
4685                 default:
4686                 case VTL_IMPORT_NONE:
4687                         break;
4688         }
4689
4690         /* strip _session->session_directory().video_path() from video file if possible */
4691         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4692                  path=path.substr(_session->session_directory().video_path().size());
4693                  if (path.at(0) == G_DIR_SEPARATOR) {
4694                          path=path.substr(1);
4695                  }
4696         }
4697
4698         video_timeline->set_update_session_fps(auto_set_session_fps);
4699
4700         if (video_timeline->video_file_info(path, local_file)) {
4701                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4702                 node->set_property (X_("Filename"), path);
4703                 node->set_property (X_("AutoFPS"), auto_set_session_fps);
4704                 node->set_property (X_("LocalFile"), local_file);
4705                 if (orig_local_file) {
4706                         node->set_property (X_("OriginalVideoFile"), orig_path);
4707                 } else {
4708                         node->remove_property (X_("OriginalVideoFile"));
4709                 }
4710                 _session->add_extra_xml (*node);
4711                 _session->set_dirty ();
4712
4713                 if (!audio_from_video.empty() && detect_ltc) {
4714                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4715
4716                         try {
4717                                 /* TODO ask user about TV standard (LTC alignment if any) */
4718                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4719                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4720
4721                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC samples to decode*/ 15);
4722
4723                                 /* TODO seek near end of file, and read LTC until end.
4724                                  * if it fails to find any LTC samples, scan complete file
4725                                  *
4726                                  * calculate drift of LTC compared to video-duration,
4727                                  * ask user for reference (timecode from start/mid/end)
4728                                  */
4729                         } catch (...) {
4730                                 // LTCFileReader will have written error messages
4731                         }
4732
4733                         ::g_unlink(audio_from_video.c_str());
4734
4735                         if (ltc_seq.size() == 0) {
4736                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4737                         } else {
4738                                 /* the very first TC in the file is somteimes not aligned properly */
4739                                 int i = ltc_seq.size() -1;
4740                                 ARDOUR::sampleoffset_t video_start_offset =
4741                                         _session->nominal_sample_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4742                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4743                                 video_timeline->set_offset(video_start_offset);
4744                         }
4745                 }
4746
4747                 _session->maybe_update_session_range(
4748                         std::max(video_timeline->get_offset(), (ARDOUR::sampleoffset_t) 0),
4749                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::sampleoffset_t) 0));
4750
4751
4752                 if (add_video_dialog->launch_xjadeo() && local_file) {
4753                         editor->set_xjadeo_sensitive(true);
4754                         editor->toggle_xjadeo_proc(1);
4755                 } else {
4756                         editor->toggle_xjadeo_proc(0);
4757                 }
4758                 editor->toggle_ruler_video(true);
4759         }
4760 }
4761
4762 void
4763 ARDOUR_UI::remove_video ()
4764 {
4765         video_timeline->close_session();
4766         editor->toggle_ruler_video(false);
4767
4768         /* reset state */
4769         video_timeline->set_offset_locked(false);
4770         video_timeline->set_offset(0);
4771
4772         /* delete session state */
4773         XMLNode* node = new XMLNode(X_("Videotimeline"));
4774         _session->add_extra_xml(*node);
4775         node = new XMLNode(X_("Videomonitor"));
4776         _session->add_extra_xml(*node);
4777         node = new XMLNode(X_("Videoexport"));
4778         _session->add_extra_xml(*node);
4779         stop_video_server();
4780 }
4781
4782 void
4783 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4784 {
4785         if (localcacheonly) {
4786                 video_timeline->vmon_update();
4787         } else {
4788                 video_timeline->flush_cache();
4789         }
4790         editor->queue_visual_videotimeline_update();
4791 }
4792
4793 void
4794 ARDOUR_UI::export_video (bool range)
4795 {
4796         if (ARDOUR::Config->get_show_video_export_info()) {
4797                 ExportVideoInfobox infobox (_session);
4798                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4799                 if (infobox.show_again()) {
4800                         ARDOUR::Config->set_show_video_export_info(false);
4801                 }
4802                 switch (rv) {
4803                         case GTK_RESPONSE_YES:
4804                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4805                                 break;
4806                         default:
4807                                 break;
4808                 }
4809         }
4810         export_video_dialog->set_session (_session);
4811         export_video_dialog->apply_state(editor->get_selection().time, range);
4812         export_video_dialog->run ();
4813         export_video_dialog->hide ();
4814 }
4815
4816 XMLNode*
4817 ARDOUR_UI::preferences_settings () const
4818 {
4819         XMLNode* node = 0;
4820
4821         if (_session) {
4822                 node = _session->instant_xml(X_("Preferences"));
4823         } else {
4824                 node = Config->instant_xml(X_("Preferences"));
4825         }
4826
4827         if (!node) {
4828                 node = new XMLNode (X_("Preferences"));
4829         }
4830
4831         return node;
4832 }
4833
4834 XMLNode*
4835 ARDOUR_UI::mixer_settings () const
4836 {
4837         XMLNode* node = 0;
4838
4839         if (_session) {
4840                 node = _session->instant_xml(X_("Mixer"));
4841         } else {
4842                 node = Config->instant_xml(X_("Mixer"));
4843         }
4844
4845         if (!node) {
4846                 node = new XMLNode (X_("Mixer"));
4847         }
4848
4849         return node;
4850 }
4851
4852 XMLNode*
4853 ARDOUR_UI::main_window_settings () const
4854 {
4855         XMLNode* node = 0;
4856
4857         if (_session) {
4858                 node = _session->instant_xml(X_("Main"));
4859         } else {
4860                 node = Config->instant_xml(X_("Main"));
4861         }
4862
4863         if (!node) {
4864                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4865                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4866                 }
4867         }
4868
4869         if (!node) {
4870                 node = new XMLNode (X_("Main"));
4871         }
4872
4873         return node;
4874 }
4875
4876 XMLNode*
4877 ARDOUR_UI::editor_settings () const
4878 {
4879         XMLNode* node = 0;
4880
4881         if (_session) {
4882                 node = _session->instant_xml(X_("Editor"));
4883         } else {
4884                 node = Config->instant_xml(X_("Editor"));
4885         }
4886
4887         if (!node) {
4888                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4889                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4890                 }
4891         }
4892
4893         if (!node) {
4894                 node = new XMLNode (X_("Editor"));
4895         }
4896
4897         return node;
4898 }
4899
4900 XMLNode*
4901 ARDOUR_UI::keyboard_settings () const
4902 {
4903         XMLNode* node = 0;
4904
4905         node = Config->extra_xml(X_("Keyboard"));
4906
4907         if (!node) {
4908                 node = new XMLNode (X_("Keyboard"));
4909         }
4910
4911         return node;
4912 }
4913
4914 void
4915 ARDOUR_UI::create_xrun_marker (samplepos_t where)
4916 {
4917         if (_session) {
4918                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark, 0);
4919                 _session->locations()->add (location);
4920         }
4921 }
4922
4923 void
4924 ARDOUR_UI::halt_on_xrun_message ()
4925 {
4926         cerr << "HALT on xrun\n";
4927         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4928         msg.run ();
4929 }
4930
4931 void
4932 ARDOUR_UI::xrun_handler (samplepos_t where)
4933 {
4934         if (!_session) {
4935                 return;
4936         }
4937
4938         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4939
4940         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4941                 create_xrun_marker(where);
4942         }
4943
4944         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4945                 halt_on_xrun_message ();
4946         }
4947 }
4948
4949 void
4950 ARDOUR_UI::disk_overrun_handler ()
4951 {
4952         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4953
4954         if (!have_disk_speed_dialog_displayed) {
4955                 have_disk_speed_dialog_displayed = true;
4956                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4957 The disk system on your computer\n\
4958 was not able to keep up with %1.\n\
4959 \n\
4960 Specifically, it failed to write data to disk\n\
4961 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4962                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4963                 msg->show ();
4964         }
4965 }
4966
4967
4968 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4969 static MessageDialog *scan_dlg = NULL;
4970 static ProgressBar   *scan_pbar = NULL;
4971 static HBox          *scan_tbox = NULL;
4972 static Gtk::Button   *scan_timeout_button;
4973
4974 void
4975 ARDOUR_UI::cancel_plugin_scan ()
4976 {
4977         PluginManager::instance().cancel_plugin_scan();
4978 }
4979
4980 void
4981 ARDOUR_UI::cancel_plugin_timeout ()
4982 {
4983         PluginManager::instance().cancel_plugin_timeout();
4984         scan_timeout_button->set_sensitive (false);
4985 }
4986
4987 void
4988 ARDOUR_UI::plugin_scan_timeout (int timeout)
4989 {
4990         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4991                 return;
4992         }
4993         if (timeout > 0) {
4994                 scan_pbar->set_sensitive (false);
4995                 scan_timeout_button->set_sensitive (true);
4996                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4997                 scan_tbox->show();
4998         } else {
4999                 scan_pbar->set_sensitive (false);
5000                 scan_timeout_button->set_sensitive (false);
5001         }
5002         gui_idle_handler();
5003 }
5004
5005 void
5006 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
5007 {
5008         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
5009                 return;
5010         }
5011
5012         const bool cancelled = PluginManager::instance().cancelled();
5013         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
5014                 if (cancelled && scan_dlg->is_mapped()) {
5015                         scan_dlg->hide();
5016                         gui_idle_handler();
5017                         return;
5018                 }
5019                 if (cancelled || !can_cancel) {
5020                         return;
5021                 }
5022         }
5023
5024         static Gtk::Button *cancel_button;
5025         if (!scan_dlg) {
5026                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
5027                 VBox* vbox = scan_dlg->get_vbox();
5028                 vbox->set_size_request(400,-1);
5029                 scan_dlg->set_title (_("Scanning for plugins"));
5030
5031                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
5032                 cancel_button->set_name ("EditorGTKButton");
5033                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
5034                 cancel_button->show();
5035
5036                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
5037
5038                 scan_tbox = manage( new HBox() );
5039
5040                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
5041                 scan_timeout_button->set_name ("EditorGTKButton");
5042                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
5043                 scan_timeout_button->show();
5044
5045                 scan_pbar = manage(new ProgressBar());
5046                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
5047                 scan_pbar->set_text(_("Scan Timeout"));
5048                 scan_pbar->show();
5049
5050                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
5051                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
5052
5053                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
5054         }
5055
5056         assert(scan_dlg && scan_tbox && cancel_button);
5057
5058         if (type == X_("closeme")) {
5059                 scan_tbox->hide();
5060                 scan_dlg->hide();
5061         } else {
5062                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
5063                 scan_dlg->show();
5064         }
5065         if (!can_cancel || !cancelled) {
5066                 scan_timeout_button->set_sensitive(false);
5067         }
5068         cancel_button->set_sensitive(can_cancel && !cancelled);
5069
5070         gui_idle_handler();
5071 }
5072
5073 void
5074 ARDOUR_UI::gui_idle_handler ()
5075 {
5076         int timeout = 30;
5077         /* due to idle calls, gtk_events_pending() may always return true */
5078         while (gtk_events_pending() && --timeout) {
5079                 gtk_main_iteration ();
5080         }
5081 }
5082
5083 void
5084 ARDOUR_UI::disk_underrun_handler ()
5085 {
5086         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
5087
5088         if (!have_disk_speed_dialog_displayed) {
5089                 have_disk_speed_dialog_displayed = true;
5090                 MessageDialog* msg = new MessageDialog (
5091                         _main_window, string_compose (_("The disk system on your computer\n\
5092 was not able to keep up with %1.\n\
5093 \n\
5094 Specifically, it failed to read data from disk\n\
5095 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
5096                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
5097                 msg->show ();
5098         }
5099 }
5100
5101 void
5102 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
5103 {
5104         have_disk_speed_dialog_displayed = false;
5105         delete msg;
5106 }
5107
5108 void
5109 ARDOUR_UI::session_dialog (std::string msg)
5110 {
5111         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
5112
5113         MessageDialog* d;
5114
5115         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
5116         d->show_all ();
5117         d->run ();
5118         delete d;
5119 }
5120
5121 int
5122 ARDOUR_UI::pending_state_dialog ()
5123 {
5124         HBox* hbox = manage (new HBox());
5125         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
5126         ArdourDialog dialog (_("Crash Recovery"), true);
5127         Label  message (string_compose (_("\
5128 This session appears to have been in the\n\
5129 middle of recording when %1 or\n\
5130 the computer was shutdown.\n\
5131 \n\
5132 %1 can recover any captured audio for\n\
5133 you, or it can ignore it. Please decide\n\
5134 what you would like to do.\n"), PROGRAM_NAME));
5135         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5136         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5137         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5138         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5139         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
5140         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
5141         dialog.set_default_response (RESPONSE_ACCEPT);
5142         dialog.set_position (WIN_POS_CENTER);
5143         message.show();
5144         image->show();
5145         hbox->show();
5146
5147         switch (dialog.run ()) {
5148         case RESPONSE_ACCEPT:
5149                 return 1;
5150         default:
5151                 return 0;
5152         }
5153 }
5154
5155 int
5156 ARDOUR_UI::sr_mismatch_dialog (samplecnt_t desired, samplecnt_t actual)
5157 {
5158         HBox* hbox = new HBox();
5159         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
5160         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
5161         Label  message (string_compose (_("\
5162 This session was created with a sample rate of %1 Hz, but\n\
5163 %2 is currently running at %3 Hz.  If you load this session,\n\
5164 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
5165
5166         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
5167         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
5168         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
5169         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
5170         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
5171         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
5172         dialog.set_default_response (RESPONSE_ACCEPT);
5173         dialog.set_position (WIN_POS_CENTER);
5174         message.show();
5175         image->show();
5176         hbox->show();
5177
5178         switch (dialog.run()) {
5179         case RESPONSE_ACCEPT:
5180                 return 0;
5181         default:
5182                 break;
5183         }
5184
5185         return 1;
5186 }
5187
5188 void
5189 ARDOUR_UI::sr_mismatch_message (samplecnt_t desired, samplecnt_t actual)
5190 {
5191         MessageDialog msg (string_compose (_("\
5192 This session was created with a sample rate of %1 Hz, but\n\
5193 %2 is currently running at %3 Hz.\n\
5194 Audio will be recorded and played at the wrong sample rate.\n\
5195 Re-Configure the Audio Engine in\n\
5196 Menu > Window > Audio/Midi Setup"),
5197                                 desired, PROGRAM_NAME, actual),
5198                         true,
5199                         Gtk::MESSAGE_WARNING);
5200         msg.run ();
5201 }
5202
5203 void
5204 ARDOUR_UI::use_config ()
5205 {
5206         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
5207         if (node) {
5208                 set_transport_controllable_state (*node);
5209         }
5210 }
5211
5212 void
5213 ARDOUR_UI::update_transport_clocks (samplepos_t pos)
5214 {
5215         switch (UIConfiguration::instance().get_primary_clock_delta_mode()) {
5216                 case NoDelta:
5217                         primary_clock->set (pos);
5218                         break;
5219                 case DeltaEditPoint:
5220                         primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5221                         break;
5222                 case DeltaOriginMarker:
5223                         {
5224                                 Location* loc = _session->locations()->clock_origin_location ();
5225                                 primary_clock->set (pos, false, loc ? loc->start() : 0);
5226                         }
5227                         break;
5228         }
5229
5230         switch (UIConfiguration::instance().get_secondary_clock_delta_mode()) {
5231                 case NoDelta:
5232                         secondary_clock->set (pos);
5233                         break;
5234                 case DeltaEditPoint:
5235                         secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
5236                         break;
5237                 case DeltaOriginMarker:
5238                         {
5239                                 Location* loc = _session->locations()->clock_origin_location ();
5240                                 secondary_clock->set (pos, false, loc ? loc->start() : 0);
5241                         }
5242                         break;
5243         }
5244
5245         if (big_clock_window) {
5246                 big_clock->set (pos);
5247         }
5248         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
5249 }
5250
5251
5252 void
5253 ARDOUR_UI::record_state_changed ()
5254 {
5255         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
5256
5257         if (!_session) {
5258                 /* why bother - the clock isn't visible */
5259                 return;
5260         }
5261
5262         ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording());
5263
5264         if (big_clock_window) {
5265                 if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
5266                         big_clock->set_active (true);
5267                 } else {
5268                         big_clock->set_active (false);
5269                 }
5270         }
5271
5272 }
5273
5274 bool
5275 ARDOUR_UI::first_idle ()
5276 {
5277         if (_session) {
5278                 _session->allow_auto_play (true);
5279         }
5280
5281         if (editor) {
5282                 editor->first_idle();
5283         }
5284
5285         /* in 1 second, hide the splash screen
5286          *
5287          * Consider hiding it *now*. If a user opens opens a dialog
5288          * during that one second while the splash is still visible,
5289          * the dialog will push-back the splash.
5290          * Closing the dialog later will pop it back.
5291          */
5292         Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
5293
5294         Keyboard::set_can_save_keybindings (true);
5295         return false;
5296 }
5297
5298 void
5299 ARDOUR_UI::store_clock_modes ()
5300 {
5301         XMLNode* node = new XMLNode(X_("ClockModes"));
5302
5303         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
5304                 XMLNode* child = new XMLNode (X_("Clock"));
5305
5306                 child->set_property (X_("name"), (*x)->name());
5307                 child->set_property (X_("mode"), (*x)->mode());
5308                 child->set_property (X_("on"), (*x)->on());
5309
5310                 node->add_child_nocopy (*child);
5311         }
5312
5313         _session->add_extra_xml (*node);
5314         _session->set_dirty ();
5315 }
5316
5317 void
5318 ARDOUR_UI::setup_profile ()
5319 {
5320         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5321                 Profile->set_small_screen ();
5322         }
5323
5324         if (g_getenv ("TRX")) {
5325                 Profile->set_trx ();
5326         }
5327
5328         if (g_getenv ("MIXBUS")) {
5329                 Profile->set_mixbus ();
5330         }
5331 }
5332
5333 int
5334 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5335 {
5336         MissingFileDialog dialog (s, str, type);
5337
5338         dialog.show ();
5339         dialog.present ();
5340
5341         int result = dialog.run ();
5342         dialog.hide ();
5343
5344         switch (result) {
5345         case RESPONSE_OK:
5346                 break;
5347         default:
5348                 return 1; // quit entire session load
5349         }
5350
5351         result = dialog.get_action ();
5352
5353         return result;
5354 }
5355
5356 int
5357 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5358 {
5359         AmbiguousFileDialog dialog (file, hits);
5360
5361         dialog.show ();
5362         dialog.present ();
5363
5364         dialog.run ();
5365
5366         return dialog.get_which ();
5367 }
5368
5369 /** Allocate our thread-local buffers */
5370 void
5371 ARDOUR_UI::get_process_buffers ()
5372 {
5373         _process_thread->get_buffers ();
5374 }
5375
5376 /** Drop our thread-local buffers */
5377 void
5378 ARDOUR_UI::drop_process_buffers ()
5379 {
5380         _process_thread->drop_buffers ();
5381 }
5382
5383 void
5384 ARDOUR_UI::feedback_detected ()
5385 {
5386         _feedback_exists = true;
5387 }
5388
5389 void
5390 ARDOUR_UI::successful_graph_sort ()
5391 {
5392         _feedback_exists = false;
5393 }
5394
5395 void
5396 ARDOUR_UI::midi_panic ()
5397 {
5398         if (_session) {
5399                 _session->midi_panic();
5400         }
5401 }
5402
5403 void
5404 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5405 {
5406         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5407         const char* end_big = "</span>";
5408         const char* start_mono = "<tt>";
5409         const char* end_mono = "</tt>";
5410
5411         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5412                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5413                                              "From now on, use the backup copy with older versions of %3"),
5414                                            xml_path, backup_path, PROGRAM_NAME,
5415                                            start_big, end_big,
5416                                            start_mono, end_mono), true);
5417
5418         msg.run ();
5419 }
5420
5421 void
5422 ARDOUR_UI::add_editor_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
5423 {
5424         using namespace Menu_Helpers;
5425
5426         items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (editor_meter, &LevelMeterHBox::set_meter_type), type)));
5427         RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
5428         i->set_active (editor_meter->meter_type () == type);
5429 }
5430
5431 void
5432 ARDOUR_UI::popup_editor_meter_menu (GdkEventButton* ev)
5433 {
5434         using namespace Gtk::Menu_Helpers;
5435
5436         Gtk::Menu* m = manage (new Menu);
5437         MenuList& items = m->items ();
5438
5439         RadioMenuItem::Group group;
5440
5441         _suspend_editor_meter_callbacks = true;
5442         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
5443         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak0dB), MeterPeak0dB);
5444         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterKrms),  MeterKrms);
5445         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
5446         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
5447         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
5448         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
5449         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
5450         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
5451         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12);
5452         add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU),  MeterVU);
5453
5454         m->popup (ev->button, ev->time);
5455         _suspend_editor_meter_callbacks = false;
5456 }
5457
5458 bool
5459 ARDOUR_UI::editor_meter_button_press (GdkEventButton* ev)
5460 {
5461         if (ev->button == 3 && editor_meter) {
5462                 popup_editor_meter_menu (ev);
5463                 return true;
5464         }
5465         return false;
5466 }
5467
5468 void
5469 ARDOUR_UI::reset_peak_display ()
5470 {
5471         if (!_session || !_session->master_out() || !editor_meter) return;
5472         editor_meter->clear_meters();
5473         editor_meter_max_peak = -INFINITY;
5474         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5475 }
5476
5477 void
5478 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5479 {
5480         if (!_session || !_session->master_out()) return;
5481         if (group == _session->master_out()->route_group()) {
5482                 reset_peak_display ();
5483         }
5484 }
5485
5486 void
5487 ARDOUR_UI::reset_route_peak_display (Route* route)
5488 {
5489         if (!_session || !_session->master_out()) return;
5490         if (_session->master_out().get() == route) {
5491                 reset_peak_display ();
5492         }
5493 }
5494
5495 int
5496 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5497 {
5498         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5499         audio_midi_setup->set_position (WIN_POS_CENTER);
5500
5501         if (desired_sample_rate != 0) {
5502                 if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5503                         audio_midi_setup->try_autostart ();
5504                         if (ARDOUR::AudioEngine::instance()->running()) {
5505                                 return 0;
5506                         }
5507                 }
5508         }
5509
5510         while (true) {
5511                 int response = audio_midi_setup->run();
5512                 switch (response) {
5513                 case Gtk::RESPONSE_DELETE_EVENT:
5514                         // after latency callibration engine may run,
5515                         // Running() signal was emitted, but dialog will not
5516                         // have emitted a response. The user needs to close
5517                         // the dialog -> Gtk::RESPONSE_DELETE_EVENT
5518                         if (!AudioEngine::instance()->running()) {
5519                                 return -1;
5520                         }
5521                         // fall through
5522                 default:
5523                         if (!AudioEngine::instance()->running()) {
5524                                 continue;
5525                         }
5526                         audio_midi_setup->hide ();
5527                         return 0;
5528                 }
5529         }
5530 }
5531
5532
5533 gint
5534 ARDOUR_UI::transport_numpad_timeout ()
5535 {
5536         _numpad_locate_happening = false;
5537         if (_numpad_timeout_connection.connected() )
5538                 _numpad_timeout_connection.disconnect();
5539         return 1;
5540 }
5541
5542 void
5543 ARDOUR_UI::transport_numpad_decimal ()
5544 {
5545         _numpad_timeout_connection.disconnect();
5546
5547         if (_numpad_locate_happening) {
5548                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5549                 _numpad_locate_happening = false;
5550         } else {
5551                 _pending_locate_num = 0;
5552                 _numpad_locate_happening = true;
5553                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5554         }
5555 }
5556
5557 void
5558 ARDOUR_UI::transport_numpad_event (int num)
5559 {
5560         if ( _numpad_locate_happening ) {
5561                 _pending_locate_num = _pending_locate_num*10 + num;
5562         } else {
5563                 switch (num) {
5564                         case 0:  toggle_roll(false, false);             break;
5565                         case 1:  transport_rewind(1);                           break;
5566                         case 2:  transport_forward(1);                          break;
5567                         case 3:  transport_record(true);                        break;
5568                         case 4:  toggle_session_auto_loop();            break;
5569                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5570                         case 6:  toggle_punch();                                        break;
5571                         case 7:  toggle_click();                                break;
5572                         case 8:  toggle_auto_return();                  break;
5573                         case 9:  toggle_follow_edits();         break;
5574                 }
5575         }
5576 }
5577
5578 void
5579 ARDOUR_UI::set_flat_buttons ()
5580 {
5581         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5582 }
5583
5584 void
5585 ARDOUR_UI::audioengine_became_silent ()
5586 {
5587         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5588                            true,
5589                            Gtk::MESSAGE_WARNING,
5590                            Gtk::BUTTONS_NONE,
5591                            true);
5592
5593         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5594
5595         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5596         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5597         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5598         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5599         Gtk::HBox pay_button_box;
5600         Gtk::HBox subscribe_button_box;
5601
5602         pay_button_box.pack_start (pay_button, true, false);
5603         subscribe_button_box.pack_start (subscribe_button, true, false);
5604
5605         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 */
5606
5607         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5608         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5609
5610         msg.get_vbox()->pack_start (pay_label);
5611         msg.get_vbox()->pack_start (pay_button_box);
5612         msg.get_vbox()->pack_start (subscribe_label);
5613         msg.get_vbox()->pack_start (subscribe_button_box);
5614
5615         msg.get_vbox()->show_all ();
5616
5617         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5618         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5619         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5620
5621         int r = msg.run ();
5622
5623         switch (r) {
5624         case Gtk::RESPONSE_YES:
5625                 AudioEngine::instance()->reset_silence_countdown ();
5626                 break;
5627
5628         case Gtk::RESPONSE_NO:
5629                 /* save and quit */
5630                 save_state_canfail ("");
5631                 exit (0);
5632                 break;
5633
5634         case Gtk::RESPONSE_CANCEL:
5635         default:
5636                 /* don't reset, save session and exit */
5637                 break;
5638         }
5639 }
5640
5641 void
5642 ARDOUR_UI::hide_application ()
5643 {
5644         Application::instance ()-> hide ();
5645 }
5646
5647 void
5648 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5649 {
5650         /* icons, titles, WM stuff */
5651
5652         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5653
5654         if (window_icons.empty()) {
5655                 Glib::RefPtr<Gdk::Pixbuf> icon;
5656                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
5657                         window_icons.push_back (icon);
5658                 }
5659                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
5660                         window_icons.push_back (icon);
5661                 }
5662                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
5663                         window_icons.push_back (icon);
5664                 }
5665                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
5666                         window_icons.push_back (icon);
5667                 }
5668         }
5669
5670         if (!window_icons.empty()) {
5671                 window.set_default_icon_list (window_icons);
5672         }
5673
5674         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5675
5676         if (!name.empty()) {
5677                 title += name;
5678         }
5679
5680         window.set_title (title.get_string());
5681         window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
5682
5683         window.set_flags (CAN_FOCUS);
5684         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5685
5686         /* This is a hack to ensure that GTK-accelerators continue to
5687          * work. Once we switch over to entirely native bindings, this will be
5688          * unnecessary and should be removed
5689          */
5690         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5691
5692         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5693         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5694         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5695         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5696 }
5697
5698 bool
5699 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5700 {
5701         Gtkmm2ext::Bindings* bindings = 0;
5702         Gtk::Window* window = 0;
5703
5704         /* until we get ardour bindings working, we are not handling key
5705          * releases yet.
5706          */
5707
5708         if (ev->type != GDK_KEY_PRESS) {
5709                 return false;
5710         }
5711
5712         if (event_window == &_main_window) {
5713
5714                 window = event_window;
5715
5716                 /* find current tab contents */
5717
5718                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5719
5720                 /* see if it uses the ardour binding system */
5721
5722                 if (w) {
5723                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5724                 }
5725
5726                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5727
5728         } else {
5729
5730                 window = event_window;
5731
5732                 /* see if window uses ardour binding system */
5733
5734                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5735         }
5736
5737         /* An empty binding set is treated as if it doesn't exist */
5738
5739         if (bindings && bindings->empty()) {
5740                 bindings = 0;
5741         }
5742
5743         return key_press_focus_accelerator_handler (*window, ev, bindings);
5744 }
5745
5746 static Gtkmm2ext::Bindings*
5747 get_bindings_from_widget_heirarchy (GtkWidget** w)
5748 {
5749         void* p = NULL;
5750
5751         while (*w) {
5752                 if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
5753                         break;
5754                 }
5755                 *w = gtk_widget_get_parent (*w);
5756         }
5757
5758         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5759 }
5760
5761 bool
5762 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5763 {
5764         GtkWindow* win = window.gobj();
5765         GtkWidget* focus = gtk_window_get_focus (win);
5766         GtkWidget* binding_widget = focus;
5767         bool special_handling_of_unmodified_accelerators = false;
5768         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5769
5770         if (focus) {
5771
5772                 /* some widget has keyboard focus */
5773
5774                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5775
5776                         /* A particular kind of focusable widget currently has keyboard
5777                          * focus. All unmodified key events should go to that widget
5778                          * first and not be used as an accelerator by default
5779                          */
5780
5781                         special_handling_of_unmodified_accelerators = true;
5782
5783                 } else {
5784
5785                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5786                         if (focus_bindings) {
5787                                 bindings = focus_bindings;
5788                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5789                         }
5790                 }
5791         }
5792
5793         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",
5794                                                           win,
5795                                                           ev->keyval,
5796                                                           Gtkmm2ext::show_gdk_event_state (ev->state),
5797                                                           special_handling_of_unmodified_accelerators,
5798                                                           Keyboard::some_magic_widget_has_focus(),
5799                                                           focus,
5800                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5801                                                           ((ev->state & mask) ? "yes" : "no"),
5802                                                           window.get_title()));
5803
5804         /* This exists to allow us to override the way GTK handles
5805            key events. The normal sequence is:
5806
5807            a) event is delivered to a GtkWindow
5808            b) accelerators/mnemonics are activated
5809            c) if (b) didn't handle the event, propagate to
5810                the focus widget and/or focus chain
5811
5812            The problem with this is that if the accelerators include
5813            keys without modifiers, such as the space bar or the
5814            letter "e", then pressing the key while typing into
5815            a text entry widget results in the accelerator being
5816            activated, instead of the desired letter appearing
5817            in the text entry.
5818
5819            There is no good way of fixing this, but this
5820            represents a compromise. The idea is that
5821            key events involving modifiers (not Shift)
5822            get routed into the activation pathway first, then
5823            get propagated to the focus widget if necessary.
5824
5825            If the key event doesn't involve modifiers,
5826            we deliver to the focus widget first, thus allowing
5827            it to get "normal text" without interference
5828            from acceleration.
5829
5830            Of course, this can also be problematic: if there
5831            is a widget with focus, then it will swallow
5832            all "normal text" accelerators.
5833         */
5834
5835
5836         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5837
5838                 /* no special handling or there are modifiers in effect: accelerate first */
5839
5840                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5841                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5842                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5843
5844                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5845                 KeyboardKey k (ev->state, ev->keyval);
5846
5847                 while (bindings) {
5848
5849                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5850
5851                         if (bindings->activate (k, Bindings::Press)) {
5852                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5853                                 return true;
5854                         }
5855
5856                         if (binding_widget) {
5857                                 binding_widget = gtk_widget_get_parent (binding_widget);
5858                                 if (binding_widget) {
5859                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5860                                 } else {
5861                                         bindings = 0;
5862                                 }
5863                         } else {
5864                                 bindings = 0;
5865                         }
5866                 }
5867
5868                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
5869
5870                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5871                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5872                         return true;
5873                 }
5874
5875                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5876
5877                 if (gtk_window_propagate_key_event (win, ev)) {
5878                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5879                         return true;
5880                 }
5881
5882         } else {
5883
5884                 /* no modifiers, propagate first */
5885
5886                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5887
5888                 if (gtk_window_propagate_key_event (win, ev)) {
5889                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5890                         return true;
5891                 }
5892
5893                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5894                 KeyboardKey k (ev->state, ev->keyval);
5895
5896                 while (bindings) {
5897
5898                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5899
5900
5901                         if (bindings->activate (k, Bindings::Press)) {
5902                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5903                                 return true;
5904                         }
5905
5906                         if (binding_widget) {
5907                                 binding_widget = gtk_widget_get_parent (binding_widget);
5908                                 if (binding_widget) {
5909                                         bindings = get_bindings_from_widget_heirarchy (&binding_widget);
5910                                 } else {
5911                                         bindings = 0;
5912                                 }
5913                         } else {
5914                                 bindings = 0;
5915                         }
5916                 }
5917
5918                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tnot yet handled, try global bindings (%1)\n", global_bindings));
5919
5920                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5921                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5922                         return true;
5923                 }
5924         }
5925
5926         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5927         return true;
5928 }
5929
5930 void
5931 ARDOUR_UI::cancel_solo ()
5932 {
5933         if (_session) {
5934                 _session->cancel_all_solo ();
5935         }
5936 }
5937
5938 void
5939 ARDOUR_UI::reset_focus (Gtk::Widget* w)
5940 {
5941         /* this resets focus to the first focusable parent of the given widget,
5942          * or, if there is no focusable parent, cancels focus in the toplevel
5943          * window that the given widget is packed into (if there is one).
5944          */
5945
5946         if (!w) {
5947                 return;
5948         }
5949
5950         Gtk::Widget* top = w->get_toplevel();
5951
5952         if (!top || !top->is_toplevel()) {
5953                 return;
5954         }
5955
5956         w = w->get_parent ();
5957
5958         while (w) {
5959
5960                 if (w->is_toplevel()) {
5961                         /* Setting the focus widget to a Gtk::Window causes all
5962                          * subsequent calls to ::has_focus() on the nominal
5963                          * focus widget in that window to return
5964                          * false. Workaround: never set focus to the toplevel
5965                          * itself.
5966                          */
5967                         break;
5968                 }
5969
5970                 if (w->get_can_focus ()) {
5971                         Gtk::Window* win = dynamic_cast<Gtk::Window*> (top);
5972                         win->set_focus (*w);
5973                         return;
5974                 }
5975                 w = w->get_parent ();
5976         }
5977
5978         if (top == &_main_window) {
5979
5980         }
5981
5982         /* no focusable parent found, cancel focus in top level window.
5983            C++ API cannot be used for this. Thanks, references.
5984         */
5985
5986         gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
5987
5988 }
5989
5990 void
5991 ARDOUR_UI::monitor_dim_all ()
5992 {
5993         boost::shared_ptr<Route> mon = _session->monitor_out ();
5994         if (!mon) {
5995                 return;
5996         }
5997         boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
5998
5999         Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-dim-all");
6000         _monitor->set_dim_all (tact->get_active());
6001 }
6002
6003 void
6004 ARDOUR_UI::monitor_cut_all ()
6005 {
6006         boost::shared_ptr<Route> mon = _session->monitor_out ();
6007         if (!mon) {
6008                 return;
6009         }
6010         boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
6011
6012         Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-cut-all");
6013         _monitor->set_cut_all (tact->get_active());
6014 }
6015
6016 void
6017 ARDOUR_UI::monitor_mono ()
6018 {
6019         boost::shared_ptr<Route> mon = _session->monitor_out ();
6020         if (!mon) {
6021                 return;
6022         }
6023         boost::shared_ptr<ARDOUR::MonitorProcessor> _monitor = mon->monitor_control ();
6024
6025         Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-mono");
6026         _monitor->set_mono (tact->get_active());
6027 }