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