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