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