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