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