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