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