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