Let user add a route template description on saving route templates
[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         SaveTemplateDialog* d = new SaveTemplateDialog (_session->name());
3196
3197         d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::save_template_dialog_response), d));
3198
3199         d->show ();
3200 }
3201
3202 void ARDOUR_UI::manage_templates ()
3203 {
3204         TemplateDialog td;
3205         td.run();
3206 }
3207
3208 void
3209 ARDOUR_UI::edit_metadata ()
3210 {
3211         SessionMetadataEditor dialog;
3212         dialog.set_session (_session);
3213         dialog.grab_focus ();
3214         dialog.run ();
3215 }
3216
3217 void
3218 ARDOUR_UI::import_metadata ()
3219 {
3220         SessionMetadataImporter dialog;
3221         dialog.set_session (_session);
3222         dialog.run ();
3223 }
3224
3225 bool
3226 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
3227 {
3228         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
3229
3230         MessageDialog msg (str,
3231                            false,
3232                            Gtk::MESSAGE_WARNING,
3233                            Gtk::BUTTONS_YES_NO,
3234                            true);
3235
3236
3237         msg.set_name (X_("OpenExistingDialog"));
3238         msg.set_title (_("Open Existing Session"));
3239         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
3240         msg.set_position (Gtk::WIN_POS_CENTER);
3241         pop_back_splash (msg);
3242
3243         switch (msg.run()) {
3244         case RESPONSE_YES:
3245                 return true;
3246                 break;
3247         }
3248         return false;
3249 }
3250
3251 int
3252 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
3253 {
3254         BusProfile bus_profile;
3255
3256         if (nsm) {
3257                 bus_profile.master_out_channels = 2;
3258         } else {
3259                 /* get settings from advanced section of NSD */
3260                 bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
3261         }
3262
3263         // NULL profile: no master, no monitor
3264         if (build_session (session_path, session_name, bus_profile.master_out_channels > 0 ? &bus_profile : NULL)) {
3265                 return -1;
3266         }
3267
3268         return 0;
3269 }
3270
3271 void
3272 ARDOUR_UI::load_from_application_api (const std::string& path)
3273 {
3274         /* OS X El Capitan (and probably later) now somehow passes the command
3275            line arguments to an app via the openFile delegate protocol. Ardour
3276            already does its own command line processing, and having both
3277            pathways active causes crashes. So, if the command line was already
3278            set, do nothing here.
3279         */
3280
3281         if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3282                 return;
3283         }
3284
3285         ARDOUR_COMMAND_LINE::session_name = path;
3286
3287         /* Cancel SessionDialog if it's visible to make OSX delegates work.
3288          *
3289          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
3290          * race-condition:
3291          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
3292          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
3293          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
3294          *    -> SessionDialog is not displayed
3295          */
3296
3297         if (_session_dialog) {
3298                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3299                 std::string session_path = path;
3300                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
3301                         session_path = Glib::path_get_dirname (session_path);
3302                 }
3303                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
3304                 _session_dialog->set_provided_session (session_name, session_path);
3305                 _session_dialog->response (RESPONSE_NONE);
3306                 _session_dialog->hide();
3307                 return;
3308         }
3309
3310         int rv;
3311         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
3312                 /* /path/to/foo => /path/to/foo, foo */
3313                 rv = load_session (path, basename_nosuffix (path));
3314         } else {
3315                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3316                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3317         }
3318
3319         // if load_session fails -> pop up SessionDialog.
3320         if (rv) {
3321                 ARDOUR_COMMAND_LINE::session_name = "";
3322
3323                 if (get_session_parameters (true, false)) {
3324                         exit (1);
3325                 }
3326         }
3327 }
3328
3329 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3330 int
3331 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3332 {
3333         string session_name;
3334         string session_path;
3335         string template_name;
3336         int ret = -1;
3337         bool likely_new = false;
3338         bool cancel_not_quit;
3339
3340         /* deal with any existing DIRTY session now, rather than later. don't
3341          * treat a non-dirty session this way, so that it stays visible
3342          * as we bring up the new session dialog.
3343          */
3344
3345         if (_session && ARDOUR_UI::instance()->video_timeline) {
3346                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3347         }
3348
3349         /* if there is already a session, relabel the button
3350            on the SessionDialog so that we don't Quit directly
3351         */
3352         cancel_not_quit = (_session != 0) && !quit_on_cancel;
3353
3354         if (_session && _session->dirty()) {
3355                 if (unload_session (false)) {
3356                         /* unload cancelled by user */
3357                         return 0;
3358                 }
3359                 ARDOUR_COMMAND_LINE::session_name = "";
3360         }
3361
3362         if (!load_template.empty()) {
3363                 should_be_new = true;
3364                 template_name = load_template;
3365         }
3366
3367         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3368         session_path = ARDOUR_COMMAND_LINE::session_name;
3369
3370         if (!session_path.empty()) {
3371                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3372                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3373                                 /* session/snapshot file, change path to be dir */
3374                                 session_path = Glib::path_get_dirname (session_path);
3375                         }
3376                 }
3377         }
3378
3379         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3380
3381         _session_dialog = &session_dialog;
3382         while (ret != 0) {
3383
3384                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3385
3386                         /* if they named a specific statefile, use it, otherwise they are
3387                            just giving a session folder, and we want to use it as is
3388                            to find the session.
3389                         */
3390
3391                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3392
3393                         if (suffix != string::npos) {
3394                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3395                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3396                                 session_name = Glib::path_get_basename (session_name);
3397                         } else {
3398                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3399                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3400                         }
3401                 } else {
3402                         session_path = "";
3403                         session_name = "";
3404                         session_dialog.clear_given ();
3405                 }
3406
3407                 if (should_be_new || session_name.empty()) {
3408                         /* need the dialog to get info from user */
3409
3410                         cerr << "run dialog\n";
3411
3412                         switch (session_dialog.run()) {
3413                         case RESPONSE_ACCEPT:
3414                                 break;
3415                         case RESPONSE_NONE:
3416                                 /* this is used for async * app->ShouldLoad(). */
3417                                 continue; // while loop
3418                                 break;
3419                         default:
3420                                 if (quit_on_cancel) {
3421                                         ARDOUR_UI::finish ();
3422                                         Gtkmm2ext::Application::instance()->cleanup();
3423                                         ARDOUR::cleanup ();
3424                                         pthread_cancel_all ();
3425                                         return -1; // caller is responsible to call exit()
3426                                 } else {
3427                                         return ret;
3428                                 }
3429                         }
3430
3431                         session_dialog.hide ();
3432                 }
3433
3434                 /* if we run the startup dialog again, offer more than just "new session" */
3435
3436                 should_be_new = false;
3437
3438                 session_name = session_dialog.session_name (likely_new);
3439                 session_path = session_dialog.session_folder ();
3440
3441                 if (nsm) {
3442                         likely_new = true;
3443                 }
3444
3445                 if (!likely_new) {
3446                         int rv = ARDOUR::inflate_session (session_name,
3447                                         Config->get_default_session_parent_dir(), session_path, session_name);
3448                         if (rv < 0) {
3449                                 MessageDialog msg (session_dialog,
3450                                         string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
3451                                 msg.run ();
3452                                 continue;
3453                         }
3454                         else if (rv == 0) {
3455                                 session_dialog.set_provided_session (session_name, session_path);
3456                         }
3457                 }
3458
3459                 // XXX check archive, inflate
3460                 string::size_type suffix = session_name.find (statefile_suffix);
3461
3462                 if (suffix != string::npos) {
3463                         session_name = session_name.substr (0, suffix);
3464                 }
3465
3466                 /* this shouldn't happen, but we catch it just in case it does */
3467
3468                 if (session_name.empty()) {
3469                         continue;
3470                 }
3471
3472                 if (session_dialog.use_session_template()) {
3473                         template_name = session_dialog.session_template_name();
3474                         _session_is_new = true;
3475                 }
3476
3477                 if (session_name[0] == G_DIR_SEPARATOR ||
3478 #ifdef PLATFORM_WINDOWS
3479                    (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3480 #else
3481                    (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3482                    (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3483 #endif
3484                 )
3485                 {
3486
3487                         /* absolute path or cwd-relative path specified for session name: infer session folder
3488                            from what was given.
3489                         */
3490
3491                         session_path = Glib::path_get_dirname (session_name);
3492                         session_name = Glib::path_get_basename (session_name);
3493
3494                 } else {
3495
3496                         session_path = session_dialog.session_folder();
3497
3498                         char illegal = Session::session_name_is_legal (session_name);
3499
3500                         if (illegal) {
3501                                 MessageDialog msg (session_dialog,
3502                                                    string_compose (_("To ensure compatibility with various systems\n"
3503                                                                      "session names may not contain a '%1' character"),
3504                                                                    illegal));
3505                                 msg.run ();
3506                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3507                                 continue;
3508                         }
3509                 }
3510
3511                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3512
3513
3514                         if (likely_new && !nsm) {
3515
3516                                 std::string existing = Glib::build_filename (session_path, session_name);
3517
3518                                 if (!ask_about_loading_existing_session (existing)) {
3519                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3520                                         continue;
3521                                 }
3522                         }
3523
3524                         _session_is_new = false;
3525
3526                 } else {
3527
3528                         if (!likely_new) {
3529                                 pop_back_splash (session_dialog);
3530                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3531                                 msg.run ();
3532                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3533                                 continue;
3534                         }
3535
3536                         char illegal = Session::session_name_is_legal(session_name);
3537
3538                         if (illegal) {
3539                                 pop_back_splash (session_dialog);
3540                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3541                                                                                     "session names may not contain a '%1' character"), illegal));
3542                                 msg.run ();
3543                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3544                                 continue;
3545                         }
3546
3547                         _session_is_new = true;
3548                 }
3549
3550                 if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
3551
3552                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3553                         meta_session_setup (template_name.substr (11));
3554
3555                 } else if (likely_new && template_name.empty()) {
3556
3557                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3558
3559                 } else {
3560
3561                         ret = load_session (session_path, session_name, template_name);
3562
3563                         if (ret == -2) {
3564                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3565                                 exit (1);
3566                         }
3567
3568                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3569                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3570                                 exit (1);
3571                         }
3572
3573                         /* clear this to avoid endless attempts to load the
3574                            same session.
3575                         */
3576
3577                         ARDOUR_COMMAND_LINE::session_name = "";
3578                 }
3579         }
3580
3581         _session_dialog = NULL;
3582
3583         return ret;
3584 }
3585
3586 void
3587 ARDOUR_UI::close_session()
3588 {
3589         if (!check_audioengine (_main_window)) {
3590                 return;
3591         }
3592
3593         if (unload_session (true)) {
3594                 return;
3595         }
3596
3597         ARDOUR_COMMAND_LINE::session_name = "";
3598
3599         if (get_session_parameters (true, false)) {
3600                 exit (1);
3601         }
3602 }
3603
3604 /** @param snap_name Snapshot name (without .ardour suffix).
3605  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3606  */
3607 int
3608 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3609 {
3610         /* load_session calls flush_pending() which allows
3611          * GUI interaction and potentially loading another session
3612          * (that was easy via snapshot sidebar).
3613          * Recursing into load_session() from load_session() and recusive
3614          * event loops causes all kind of crashes.
3615          */
3616         assert (!session_load_in_progress);
3617         if (session_load_in_progress) {
3618                 return -1;
3619         }
3620         PBD::Unwinder<bool> lsu (session_load_in_progress, true);
3621
3622         Session *new_session;
3623         int unload_status;
3624         int retval = -1;
3625
3626         if (_session) {
3627                 unload_status = unload_session ();
3628
3629                 if (unload_status < 0) {
3630                         goto out;
3631                 } else if (unload_status > 0) {
3632                         retval = 0;
3633                         goto out;
3634                 }
3635         }
3636
3637         session_loaded = false;
3638
3639         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3640
3641         try {
3642                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3643         }
3644
3645         /* this one is special */
3646
3647         catch (AudioEngine::PortRegistrationFailure& err) {
3648
3649                 MessageDialog msg (err.what(),
3650                                    true,
3651                                    Gtk::MESSAGE_INFO,
3652                                    Gtk::BUTTONS_CLOSE);
3653
3654                 msg.set_title (_("Port Registration Error"));
3655                 msg.set_secondary_text (_("Click the Close button to try again."));
3656                 msg.set_position (Gtk::WIN_POS_CENTER);
3657                 pop_back_splash (msg);
3658                 msg.present ();
3659
3660                 int response = msg.run ();
3661
3662                 msg.hide ();
3663
3664                 switch (response) {
3665                 case RESPONSE_CANCEL:
3666                         exit (1);
3667                 default:
3668                         break;
3669                 }
3670                 goto out;
3671         }
3672         catch (SessionException e) {
3673                 MessageDialog msg (string_compose(
3674                                            _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
3675                                            path, snap_name, e.what()),
3676                                    true,
3677                                    Gtk::MESSAGE_INFO,
3678                                    BUTTONS_OK);
3679
3680                 msg.set_title (_("Loading Error"));
3681                 msg.set_position (Gtk::WIN_POS_CENTER);
3682                 pop_back_splash (msg);
3683                 msg.present ();
3684
3685                 dump_errors (cerr);
3686
3687                 (void) msg.run ();
3688                 msg.hide ();
3689
3690                 goto out;
3691         }
3692         catch (...) {
3693
3694                 MessageDialog msg (string_compose(
3695                                            _("Session \"%1 (snapshot %2)\" did not load successfully."),
3696                                            path, snap_name),
3697                                    true,
3698                                    Gtk::MESSAGE_INFO,
3699                                    BUTTONS_OK);
3700
3701                 msg.set_title (_("Loading Error"));
3702                 msg.set_position (Gtk::WIN_POS_CENTER);
3703                 pop_back_splash (msg);
3704                 msg.present ();
3705
3706                 dump_errors (cerr);
3707
3708                 (void) msg.run ();
3709                 msg.hide ();
3710
3711                 goto out;
3712         }
3713
3714         {
3715                 list<string> const u = new_session->unknown_processors ();
3716                 if (!u.empty()) {
3717                         MissingPluginDialog d (_session, u);
3718                         d.run ();
3719                 }
3720         }
3721
3722         if (!new_session->writable()) {
3723                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3724                                    true,
3725                                    Gtk::MESSAGE_INFO,
3726                                    BUTTONS_OK);
3727
3728                 msg.set_title (_("Read-only Session"));
3729                 msg.set_position (Gtk::WIN_POS_CENTER);
3730                 pop_back_splash (msg);
3731                 msg.present ();
3732                 (void) msg.run ();
3733                 msg.hide ();
3734         }
3735
3736
3737         /* Now the session been created, add the transport controls */
3738         new_session->add_controllable(roll_controllable);
3739         new_session->add_controllable(stop_controllable);
3740         new_session->add_controllable(goto_start_controllable);
3741         new_session->add_controllable(goto_end_controllable);
3742         new_session->add_controllable(auto_loop_controllable);
3743         new_session->add_controllable(play_selection_controllable);
3744         new_session->add_controllable(rec_controllable);
3745
3746         set_session (new_session);
3747
3748         session_loaded = true;
3749
3750         if (_session) {
3751                 _session->set_clean ();
3752         }
3753
3754 #ifdef WINDOWS_VST_SUPPORT
3755         fst_stop_threading();
3756 #endif
3757
3758         {
3759                 Timers::TimerSuspender t;
3760                 flush_pending (10);
3761         }
3762
3763 #ifdef WINDOWS_VST_SUPPORT
3764         fst_start_threading();
3765 #endif
3766         retval = 0;
3767
3768         if (!mix_template.empty ()) {
3769                 /* if mix_template is given, assume this is a new session */
3770                 string metascript = Glib::build_filename (mix_template, "template.lua");
3771                 meta_session_setup (metascript);
3772         }
3773
3774
3775   out:
3776         /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
3777          * which is queued by set_session().
3778          * If session-loading fails we hide it explicitly.
3779          * This covers both cases in a central place.
3780          */
3781         if (retval) {
3782                 hide_splash ();
3783         }
3784         return retval;
3785 }
3786
3787 int
3788 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile* bus_profile)
3789 {
3790         Session *new_session;
3791         int x;
3792
3793         session_loaded = false;
3794         x = unload_session ();
3795
3796         if (x < 0) {
3797                 return -1;
3798         } else if (x > 0) {
3799                 return 0;
3800         }
3801
3802         _session_is_new = true;
3803
3804         try {
3805                 new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
3806         }
3807
3808         catch (SessionException e) {
3809                 cerr << "Here are the errors associated with this failed session:\n";
3810                 dump_errors (cerr);
3811                 cerr << "---------\n";
3812                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3813                 msg.set_title (_("Loading Error"));
3814                 msg.set_position (Gtk::WIN_POS_CENTER);
3815                 pop_back_splash (msg);
3816                 msg.run ();
3817                 return -1;
3818         }
3819         catch (...) {
3820                 cerr << "Here are the errors associated with this failed session:\n";
3821                 dump_errors (cerr);
3822                 cerr << "---------\n";
3823                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3824                 msg.set_title (_("Loading Error"));
3825                 msg.set_position (Gtk::WIN_POS_CENTER);
3826                 pop_back_splash (msg);
3827                 msg.run ();
3828                 return -1;
3829         }
3830
3831         /* Give the new session the default GUI state, if such things exist */
3832
3833         XMLNode* n;
3834         n = Config->instant_xml (X_("Editor"));
3835         if (n) {
3836                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3837                 new_session->add_instant_xml (*n, false);
3838         }
3839         n = Config->instant_xml (X_("Mixer"));
3840         if (n) {
3841                 new_session->add_instant_xml (*n, false);
3842         }
3843
3844         n = Config->instant_xml (X_("Preferences"));
3845         if (n) {
3846                 new_session->add_instant_xml (*n, false);
3847         }
3848
3849         /* Put the playhead at 0 and scroll fully left */
3850         n = new_session->instant_xml (X_("Editor"));
3851         if (n) {
3852                 n->set_property (X_("playhead"), X_("0"));
3853                 n->set_property (X_("left-frame"), X_("0"));
3854         }
3855
3856         set_session (new_session);
3857
3858         session_loaded = true;
3859
3860         new_session->save_state(new_session->name());
3861
3862         return 0;
3863 }
3864
3865
3866 static void _lua_print (std::string s) {
3867 #ifndef NDEBUG
3868         std::cout << "LuaInstance: " << s << "\n";
3869 #endif
3870         PBD::info << "LuaInstance: " << s << endmsg;
3871 }
3872
3873 std::map<std::string, std::string>
3874 ARDOUR_UI::route_setup_info (const std::string& script_path)
3875 {
3876         std::map<std::string, std::string> rv;
3877
3878         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3879                 return rv;
3880         }
3881
3882         LuaState lua;
3883         lua.Print.connect (&_lua_print);
3884         lua.sandbox (true);
3885
3886         lua_State* L = lua.getState();
3887         LuaInstance::register_classes (L);
3888         LuaBindings::set_session (L, _session);
3889         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3890         lua_setglobal (L, "Editor");
3891
3892         lua.do_command ("function ardour () end");
3893         lua.do_file (script_path);
3894
3895         try {
3896                 luabridge::LuaRef fn = luabridge::getGlobal (L, "route_setup");
3897                 if (!fn.isFunction ()) {
3898                         return rv;
3899                 }
3900                 luabridge::LuaRef rs = fn ();
3901                 if (!rs.isTable ()) {
3902                         return rv;
3903                 }
3904                 for (luabridge::Iterator i(rs); !i.isNil (); ++i) {
3905                         if (!i.key().isString()) {
3906                                 continue;
3907                         }
3908                         std::string key = i.key().tostring();
3909                         if (i.value().isString() || i.value().isNumber() || i.value().isBoolean()) {
3910                                 rv[key] = i.value().tostring();
3911                         }
3912                 }
3913         } catch (luabridge::LuaException const& e) {
3914                 cerr << "LuaException:" << e.what () << endl;
3915         } catch (...) { }
3916         return rv;
3917 }
3918
3919 void
3920 ARDOUR_UI::meta_route_setup (const std::string& script_path)
3921 {
3922         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3923                 return;
3924         }
3925         assert (add_route_dialog);
3926
3927         int count;
3928         if ((count = add_route_dialog->count()) <= 0) {
3929                 return;
3930         }
3931
3932         LuaState lua;
3933         lua.Print.connect (&_lua_print);
3934         lua.sandbox (true);
3935
3936         lua_State* L = lua.getState();
3937         LuaInstance::register_classes (L);
3938         LuaBindings::set_session (L, _session);
3939         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3940         lua_setglobal (L, "Editor");
3941
3942         lua.do_command ("function ardour () end");
3943         lua.do_file (script_path);
3944
3945         luabridge::LuaRef args (luabridge::newTable (L));
3946
3947         args["name"]       = add_route_dialog->name_template ();
3948         args["insert_at"]  = translate_order (add_route_dialog->insert_at());
3949         args["group"]      = add_route_dialog->route_group ();
3950         args["strict_io"]  = add_route_dialog->use_strict_io ();
3951         args["instrument"] = add_route_dialog->requested_instrument ();
3952         args["track_mode"] = add_route_dialog->mode ();
3953         args["channels"]   = add_route_dialog->channel_count ();
3954         args["how_many"]   = count;
3955
3956         try {
3957                 luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
3958                 if (fn.isFunction()) {
3959                         fn (args)();
3960                 }
3961         } catch (luabridge::LuaException const& e) {
3962                 cerr << "LuaException:" << e.what () << endl;
3963         } catch (...) {
3964                 display_insufficient_ports_message ();
3965         }
3966 }
3967
3968 void
3969 ARDOUR_UI::meta_session_setup (const std::string& script_path)
3970 {
3971         if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
3972                 return;
3973         }
3974
3975         LuaState lua;
3976         lua.Print.connect (&_lua_print);
3977         lua.sandbox (true);
3978
3979         lua_State* L = lua.getState();
3980         LuaInstance::register_classes (L);
3981         LuaBindings::set_session (L, _session);
3982         luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
3983         lua_setglobal (L, "Editor");
3984
3985         lua.do_command ("function ardour () end");
3986         lua.do_file (script_path);
3987
3988         try {
3989                 luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
3990                 if (fn.isFunction()) {
3991                         fn ()();
3992                 }
3993         } catch (luabridge::LuaException const& e) {
3994                 cerr << "LuaException:" << e.what () << endl;
3995         } catch (...) {
3996                 display_insufficient_ports_message ();
3997         }
3998 }
3999
4000 void
4001 ARDOUR_UI::launch_chat ()
4002 {
4003         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
4004
4005         dialog.set_title (_("About the Chat"));
4006         dialog.set_secondary_text (_("When you're inside the chat just ask your question and wait for an answer. The chat is occupied by real people with real lives so many of them are passively online and might not read your question before minutes or hours later.\nSo please be patient and wait for an answer.\n\nYou should just leave the chat window open and check back regularly until someone has answered your question."));
4007
4008         switch (dialog.run()) {
4009         case RESPONSE_OK:
4010 #ifdef __APPLE__
4011                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
4012 #elif defined PLATFORM_WINDOWS
4013                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
4014 #else
4015                 open_uri("http://webchat.freenode.net/?channels=ardour");
4016 #endif
4017                 break;
4018         default:
4019                 break;
4020         }
4021 }
4022
4023 void
4024 ARDOUR_UI::launch_manual ()
4025 {
4026         PBD::open_uri (Config->get_tutorial_manual_url());
4027 }
4028
4029 void
4030 ARDOUR_UI::launch_reference ()
4031 {
4032         PBD::open_uri (Config->get_reference_manual_url());
4033 }
4034
4035 void
4036 ARDOUR_UI::launch_tracker ()
4037 {
4038         PBD::open_uri ("http://tracker.ardour.org");
4039 }
4040
4041 void
4042 ARDOUR_UI::launch_subscribe ()
4043 {
4044         PBD::open_uri ("https://community.ardour.org/s/subscribe");
4045 }
4046
4047 void
4048 ARDOUR_UI::launch_cheat_sheet ()
4049 {
4050 #ifdef __APPLE__
4051         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
4052 #else
4053         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
4054 #endif
4055 }
4056
4057 void
4058 ARDOUR_UI::launch_website ()
4059 {
4060         PBD::open_uri ("http://ardour.org");
4061 }
4062
4063 void
4064 ARDOUR_UI::launch_website_dev ()
4065 {
4066         PBD::open_uri ("http://ardour.org/development.html");
4067 }
4068
4069 void
4070 ARDOUR_UI::launch_forums ()
4071 {
4072         PBD::open_uri ("https://community.ardour.org/forums");
4073 }
4074
4075 void
4076 ARDOUR_UI::launch_howto_report ()
4077 {
4078         PBD::open_uri ("http://ardour.org/reporting_bugs");
4079 }
4080
4081 void
4082 ARDOUR_UI::loading_message (const std::string& msg)
4083 {
4084         if (ARDOUR_COMMAND_LINE::no_splash) {
4085                 return;
4086         }
4087
4088         if (!splash) {
4089                 show_splash ();
4090         }
4091
4092         splash->message (msg);
4093 }
4094
4095 void
4096 ARDOUR_UI::show_splash ()
4097 {
4098         if (splash == 0) {
4099                 try {
4100                         splash = new Splash;
4101                 } catch (...) {
4102                         return;
4103                 }
4104         }
4105
4106         splash->display ();
4107 }
4108
4109 void
4110 ARDOUR_UI::hide_splash ()
4111 {
4112         delete splash;
4113         splash = 0;
4114 }
4115
4116 void
4117 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
4118 {
4119         size_t removed;
4120
4121         removed = rep.paths.size();
4122
4123         if (removed == 0) {
4124                 MessageDialog msgd (_main_window,
4125                                     _("No files were ready for clean-up"),
4126                                     true,
4127                                     Gtk::MESSAGE_INFO,
4128                                     Gtk::BUTTONS_OK);
4129                 msgd.set_title (_("Clean-up"));
4130                 msgd.set_secondary_text (_("If this seems surprising, \n\
4131 check for any existing snapshots.\n\
4132 These may still include regions that\n\
4133 require some unused files to continue to exist."));
4134
4135                 msgd.run ();
4136                 return;
4137         }
4138
4139         ArdourDialog results (_("Clean-up"), true, false);
4140
4141         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
4142                 CleanupResultsModelColumns() {
4143                         add (visible_name);
4144                         add (fullpath);
4145                 }
4146                 Gtk::TreeModelColumn<std::string> visible_name;
4147                 Gtk::TreeModelColumn<std::string> fullpath;
4148         };
4149
4150
4151         CleanupResultsModelColumns results_columns;
4152         Glib::RefPtr<Gtk::ListStore> results_model;
4153         Gtk::TreeView results_display;
4154
4155         results_model = ListStore::create (results_columns);
4156         results_display.set_model (results_model);
4157         results_display.append_column (list_title, results_columns.visible_name);
4158
4159         results_display.set_name ("CleanupResultsList");
4160         results_display.set_headers_visible (true);
4161         results_display.set_headers_clickable (false);
4162         results_display.set_reorderable (false);
4163
4164         Gtk::ScrolledWindow list_scroller;
4165         Gtk::Label txt;
4166         Gtk::VBox dvbox;
4167         Gtk::HBox dhbox;  // the hbox for the image and text
4168         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
4169         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
4170
4171         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
4172
4173         const string dead_directory = _session->session_directory().dead_path();
4174
4175         /* subst:
4176            %1 - number of files removed
4177            %2 - location of "dead"
4178            %3 - size of files affected
4179            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
4180         */
4181
4182         const char* bprefix;
4183         double space_adjusted = 0;
4184
4185         if (rep.space < 1000) {
4186                 bprefix = X_("");
4187                 space_adjusted = rep.space;
4188         } else if (rep.space < 1000000) {
4189                 bprefix = _("kilo");
4190                 space_adjusted = floorf((float)rep.space / 1000.0);
4191         } else if (rep.space < 1000000 * 1000) {
4192                 bprefix = _("mega");
4193                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
4194         } else {
4195                 bprefix = _("giga");
4196                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
4197         }
4198
4199         if (msg_delete) {
4200                 txt.set_markup (string_compose (P_("\
4201 The following file was deleted from %2,\n\
4202 releasing %3 %4bytes of disk space", "\
4203 The following %1 files were deleted from %2,\n\
4204 releasing %3 %4bytes of disk space", removed),
4205                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4206         } else {
4207                 txt.set_markup (string_compose (P_("\
4208 The following file was not in use and \n\
4209 has been moved to: %2\n\n\
4210 After a restart of %5\n\n\
4211 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4212 will release an additional %3 %4bytes of disk space.\n", "\
4213 The following %1 files were not in use and \n\
4214 have been moved to: %2\n\n\
4215 After a restart of %5\n\n\
4216 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
4217 will release an additional %3 %4bytes of disk space.\n", removed),
4218                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
4219         }
4220
4221         dhbox.pack_start (*dimage, true, false, 5);
4222         dhbox.pack_start (txt, true, false, 5);
4223
4224         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
4225                 TreeModel::Row row = *(results_model->append());
4226                 row[results_columns.visible_name] = *i;
4227                 row[results_columns.fullpath] = *i;
4228         }
4229
4230         list_scroller.add (results_display);
4231         list_scroller.set_size_request (-1, 150);
4232         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
4233
4234         dvbox.pack_start (dhbox, true, false, 5);
4235         dvbox.pack_start (list_scroller, true, false, 5);
4236         ddhbox.pack_start (dvbox, true, false, 5);
4237
4238         results.get_vbox()->pack_start (ddhbox, true, false, 5);
4239         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
4240         results.set_default_response (RESPONSE_CLOSE);
4241         results.set_position (Gtk::WIN_POS_MOUSE);
4242
4243         results_display.show();
4244         list_scroller.show();
4245         txt.show();
4246         dvbox.show();
4247         dhbox.show();
4248         ddhbox.show();
4249         dimage->show();
4250
4251         //results.get_vbox()->show();
4252         results.set_resizable (false);
4253
4254         results.run ();
4255
4256 }
4257
4258 void
4259 ARDOUR_UI::cleanup ()
4260 {
4261         if (_session == 0) {
4262                 /* shouldn't happen: menu item is insensitive */
4263                 return;
4264         }
4265
4266
4267         MessageDialog checker (_("Are you sure you want to clean-up?"),
4268                                 true,
4269                                 Gtk::MESSAGE_QUESTION,
4270                                 Gtk::BUTTONS_NONE);
4271
4272         checker.set_title (_("Clean-up"));
4273
4274         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
4275 ALL undo/redo information will be lost if you clean-up.\n\
4276 Clean-up will move all unused files to a \"dead\" location."));
4277
4278         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
4279         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
4280         checker.set_default_response (RESPONSE_CANCEL);
4281
4282         checker.set_name (_("CleanupDialog"));
4283         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
4284         checker.set_position (Gtk::WIN_POS_MOUSE);
4285
4286         switch (checker.run()) {
4287         case RESPONSE_ACCEPT:
4288                 break;
4289         default:
4290                 return;
4291         }
4292
4293         ARDOUR::CleanupReport rep;
4294
4295         editor->prepare_for_cleanup ();
4296
4297         /* do not allow flush until a session is reloaded */
4298
4299         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
4300         if (act) {
4301                 act->set_sensitive (false);
4302         }
4303
4304         if (_session->cleanup_sources (rep)) {
4305                 editor->finish_cleanup ();
4306                 return;
4307         }
4308
4309         editor->finish_cleanup ();
4310
4311         checker.hide();
4312         display_cleanup_results (rep, _("Cleaned Files"), false);
4313 }
4314
4315 void
4316 ARDOUR_UI::flush_trash ()
4317 {
4318         if (_session == 0) {
4319                 /* shouldn't happen: menu item is insensitive */
4320                 return;
4321         }
4322
4323         ARDOUR::CleanupReport rep;
4324
4325         if (_session->cleanup_trash_sources (rep)) {
4326                 return;
4327         }
4328
4329         display_cleanup_results (rep, _("deleted file"), true);
4330 }
4331
4332 void
4333 ARDOUR_UI::cleanup_peakfiles ()
4334 {
4335         if (_session == 0) {
4336                 /* shouldn't happen: menu item is insensitive */
4337                 return;
4338         }
4339
4340         if (! _session->can_cleanup_peakfiles ()) {
4341                 return;
4342         }
4343
4344         // get all region-views in this session
4345         RegionSelection rs;
4346         TrackViewList empty;
4347         empty.clear();
4348         editor->get_regions_after(rs, (framepos_t) 0, empty);
4349         std::list<RegionView*> views = rs.by_layer();
4350
4351         // remove displayed audio-region-views waveforms
4352         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4353                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4354                 if (!arv) { continue ; }
4355                 arv->delete_waves();
4356         }
4357
4358         // cleanup peak files:
4359         // - stop pending peakfile threads
4360         // - close peakfiles if any
4361         // - remove peak dir in session
4362         // - setup peakfiles (background thread)
4363         _session->cleanup_peakfiles ();
4364
4365         // re-add waves to ARV
4366         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
4367                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
4368                 if (!arv) { continue ; }
4369                 arv->create_waves();
4370         }
4371 }
4372
4373 PresentationInfo::order_t
4374 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
4375 {
4376         if (editor->get_selection().tracks.empty()) {
4377                 return place == RouteDialogs::First ? 0 : PresentationInfo::max_order;
4378         }
4379
4380         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
4381
4382         /*
4383           we want the new routes to have their order keys set starting from
4384           the highest order key in the selection + 1 (if available).
4385         */
4386
4387         if (place == RouteDialogs::AfterSelection) {
4388                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
4389                 if (rtav) {
4390                         order_hint = rtav->route()->presentation_info().order();
4391                         order_hint++;
4392                 }
4393         } else if (place == RouteDialogs::BeforeSelection) {
4394                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
4395                 if (rtav) {
4396                         order_hint = rtav->route()->presentation_info().order();
4397                 }
4398         } else if (place == RouteDialogs::First) {
4399                 order_hint = 0;
4400         } else {
4401                 /* leave order_hint at max_order */
4402         }
4403
4404         return order_hint;
4405 }
4406
4407 void
4408 ARDOUR_UI::start_duplicate_routes ()
4409 {
4410         if (!duplicate_routes_dialog) {
4411                 duplicate_routes_dialog = new DuplicateRouteDialog;
4412         }
4413
4414         if (duplicate_routes_dialog->restart (_session)) {
4415                 return;
4416         }
4417
4418         duplicate_routes_dialog->present ();
4419 }
4420
4421 void
4422 ARDOUR_UI::add_route ()
4423 {
4424         if (!add_route_dialog.get (false)) {
4425                 add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
4426         }
4427
4428         if (!_session) {
4429                 return;
4430         }
4431
4432         if (add_route_dialog->is_visible()) {
4433                 /* we're already doing this */
4434                 return;
4435         }
4436
4437         add_route_dialog->set_position (WIN_POS_MOUSE);
4438         add_route_dialog->present();
4439 }
4440
4441 void
4442 ARDOUR_UI::add_route_dialog_response (int r)
4443 {
4444         if (!_session) {
4445                 warning << _("You cannot add tracks or busses without a session already loaded.") << endmsg;
4446                 return;
4447         }
4448
4449         int count;
4450
4451         switch (r) {
4452         case AddRouteDialog::Add:
4453                 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 }