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