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