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