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