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