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