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