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