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