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