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