first vaguely working version using PresentationInfo
[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                 ARDOUR::PresentationInfo::order_t order)
1823 {
1824         list<boost::shared_ptr<MidiTrack> > tracks;
1825
1826         if (_session == 0) {
1827                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1828                 return;
1829         }
1830
1831         try {
1832                 tracks = _session->new_midi_track (input, output, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
1833
1834                 if (tracks.size() != how_many) {
1835                         error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
1836                 }
1837         }
1838
1839         catch (...) {
1840                 display_insufficient_ports_message ();
1841                 return;
1842         }
1843
1844         if (strict_io) {
1845                 for (list<boost::shared_ptr<MidiTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
1846                         (*i)->set_strict_io (true);
1847                 }
1848         }
1849 }
1850
1851 void
1852 ARDOUR_UI::session_add_midi_bus (
1853                 RouteGroup* route_group,
1854                 uint32_t how_many,
1855                 const string& name_template,
1856                 bool strict_io,
1857                 PluginInfoPtr instrument,
1858                 Plugin::PresetRecord* pset,
1859                 ARDOUR::PresentationInfo::order_t order)
1860 {
1861         RouteList routes;
1862
1863         if (_session == 0) {
1864                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1865                 return;
1866         }
1867
1868         try {
1869
1870                 routes = _session->new_midi_route (route_group, how_many, name_template, instrument, pset, PresentationInfo::MidiBus, order);
1871                 if (routes.size() != how_many) {
1872                         error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
1873                 }
1874
1875         }
1876         catch (...) {
1877                 display_insufficient_ports_message ();
1878                 return;
1879         }
1880
1881         if (strict_io) {
1882                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1883                         (*i)->set_strict_io (true);
1884                 }
1885         }
1886 }
1887
1888 void
1889 ARDOUR_UI::session_add_midi_route (
1890                 bool disk,
1891                 RouteGroup* route_group,
1892                 uint32_t how_many,
1893                 const string& name_template,
1894                 bool strict_io,
1895                 PluginInfoPtr instrument,
1896                 Plugin::PresetRecord* pset,
1897                 ARDOUR::PresentationInfo::order_t order)
1898 {
1899         ChanCount one_midi_channel;
1900         one_midi_channel.set (DataType::MIDI, 1);
1901
1902         if (disk) {
1903                 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, order, instrument, pset);
1904         } else {
1905                 session_add_midi_bus (route_group, how_many, name_template, strict_io, order, instrument, pset);
1906         }
1907 }
1908
1909 void
1910 ARDOUR_UI::session_add_audio_route (
1911         bool track,
1912         int32_t input_channels,
1913         int32_t output_channels,
1914         ARDOUR::TrackMode mode,
1915         RouteGroup* route_group,
1916         uint32_t how_many,
1917         string const & name_template,
1918         bool strict_io,
1919         ARDOUR::PresentationInfo::order_t order)
1920 {
1921         list<boost::shared_ptr<AudioTrack> > tracks;
1922         RouteList routes;
1923
1924         if (_session == 0) {
1925                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1926                 return;
1927         }
1928
1929         try {
1930                 if (track) {
1931                         tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode);
1932
1933                         if (tracks.size() != how_many) {
1934                                 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
1935                                       << endmsg;
1936                         }
1937
1938                 } else {
1939
1940                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order);
1941
1942                         if (routes.size() != how_many) {
1943                                 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
1944                                       << endmsg;
1945                         }
1946                 }
1947         }
1948
1949         catch (...) {
1950                 display_insufficient_ports_message ();
1951                 return;
1952         }
1953
1954         if (strict_io) {
1955                 for (list<boost::shared_ptr<AudioTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
1956                         (*i)->set_strict_io (true);
1957                 }
1958                 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1959                         (*i)->set_strict_io (true);
1960                 }
1961         }
1962 }
1963
1964 void
1965 ARDOUR_UI::display_insufficient_ports_message ()
1966 {
1967         MessageDialog msg (_main_window,
1968                         string_compose (_("There are insufficient ports available\n\
1969 to create a new track or bus.\n\
1970 You should save %1, exit and\n\
1971 restart with more ports."), PROGRAM_NAME));
1972         pop_back_splash (msg);
1973         msg.run ();
1974 }
1975
1976 void
1977 ARDOUR_UI::transport_goto_start ()
1978 {
1979         if (_session) {
1980                 _session->goto_start();
1981
1982                 /* force displayed area in editor to start no matter
1983                    what "follow playhead" setting is.
1984                 */
1985
1986                 if (editor) {
1987                         editor->center_screen (_session->current_start_frame ());
1988                 }
1989         }
1990 }
1991
1992 void
1993 ARDOUR_UI::transport_goto_zero ()
1994 {
1995         if (_session) {
1996                 _session->request_locate (0);
1997
1998                 /* force displayed area in editor to start no matter
1999                    what "follow playhead" setting is.
2000                 */
2001
2002                 if (editor) {
2003                         editor->reset_x_origin (0);
2004                 }
2005         }
2006 }
2007
2008 void
2009 ARDOUR_UI::transport_goto_wallclock ()
2010 {
2011         if (_session && editor) {
2012
2013                 time_t now;
2014                 struct tm tmnow;
2015                 framepos_t frames;
2016
2017                 time (&now);
2018                 localtime_r (&now, &tmnow);
2019
2020                 framecnt_t frame_rate = _session->frame_rate();
2021
2022                 if (frame_rate == 0) {
2023                         /* no frame rate available */
2024                         return;
2025                 }
2026
2027                 frames = tmnow.tm_hour * (60 * 60 * frame_rate);
2028                 frames += tmnow.tm_min * (60 * frame_rate);
2029                 frames += tmnow.tm_sec * frame_rate;
2030
2031                 _session->request_locate (frames, _session->transport_rolling ());
2032
2033                 /* force displayed area in editor to start no matter
2034                    what "follow playhead" setting is.
2035                 */
2036
2037                 if (editor) {
2038                         editor->center_screen (frames);
2039                 }
2040         }
2041 }
2042
2043 void
2044 ARDOUR_UI::transport_goto_end ()
2045 {
2046         if (_session) {
2047                 framepos_t const frame = _session->current_end_frame();
2048                 _session->request_locate (frame);
2049
2050                 /* force displayed area in editor to start no matter
2051                    what "follow playhead" setting is.
2052                 */
2053
2054                 if (editor) {
2055                         editor->center_screen (frame);
2056                 }
2057         }
2058 }
2059
2060 void
2061 ARDOUR_UI::transport_stop ()
2062 {
2063         if (!_session) {
2064                 return;
2065         }
2066
2067         if (_session->is_auditioning()) {
2068                 _session->cancel_audition ();
2069                 return;
2070         }
2071
2072         _session->request_stop (false, true);
2073 }
2074
2075 /** Check if any tracks are record enabled. If none are, record enable all of them.
2076  * @return true if track record-enabled status was changed, false otherwise.
2077  */
2078 bool
2079 ARDOUR_UI::trx_record_enable_all_tracks ()
2080 {
2081         if (!_session) {
2082                 return false;
2083         }
2084
2085         boost::shared_ptr<RouteList> rl = _session->get_tracks ();
2086         bool none_record_enabled = true;
2087
2088         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2089                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
2090                 assert (t);
2091
2092                 if (t->rec_enable_control()->get_value()) {
2093                         none_record_enabled = false;
2094                         break;
2095                 }
2096         }
2097
2098         if (none_record_enabled) {
2099                 _session->set_controls (route_list_to_control_list (rl, &Track::rec_enable_control), 1.0, Controllable::NoGroup);
2100         }
2101
2102         return none_record_enabled;
2103 }
2104
2105 void
2106 ARDOUR_UI::transport_record (bool roll)
2107 {
2108         if (_session) {
2109                 switch (_session->record_status()) {
2110                 case Session::Disabled:
2111                         if (_session->ntracks() == 0) {
2112                                 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."));
2113                                 msg.run ();
2114                                 return;
2115                         }
2116                         if (Profile->get_trx()) {
2117                                 roll = trx_record_enable_all_tracks ();
2118                         }
2119                         _session->maybe_enable_record ();
2120                         if (roll) {
2121                                 transport_roll ();
2122                         }
2123                         break;
2124                 case Session::Recording:
2125                         if (roll) {
2126                                 _session->request_stop();
2127                         } else {
2128                                 _session->disable_record (false, true);
2129                         }
2130                         break;
2131
2132                 case Session::Enabled:
2133                         _session->disable_record (false, true);
2134                 }
2135         }
2136 }
2137
2138 void
2139 ARDOUR_UI::transport_roll ()
2140 {
2141         if (!_session) {
2142                 return;
2143         }
2144
2145         if (_session->is_auditioning()) {
2146                 return;
2147         }
2148
2149 #if 0
2150         if (_session->config.get_external_sync()) {
2151                 switch (Config->get_sync_source()) {
2152                 case Engine:
2153                         break;
2154                 default:
2155                         /* transport controlled by the master */
2156                         return;
2157                 }
2158         }
2159 #endif
2160
2161         bool rolling = _session->transport_rolling();
2162
2163         if (_session->get_play_loop()) {
2164
2165                 /* If loop playback is not a mode, then we should cancel
2166                    it when this action is requested. If it is a mode
2167                    we just leave it in place.
2168                 */
2169
2170                 if (!Config->get_loop_is_mode()) {
2171                         /* XXX it is not possible to just leave seamless loop and keep
2172                            playing at present (nov 4th 2009)
2173                         */
2174                         if (!Config->get_seamless_loop()) {
2175                                 /* stop loop playback and stop rolling */
2176                                 _session->request_play_loop (false, true);
2177                         } else if (rolling) {
2178                                 /* stop loop playback but keep rolling */
2179                                 _session->request_play_loop (false, false);
2180                         }
2181                 }
2182
2183         } else if (_session->get_play_range () ) {
2184                 /* stop playing a range if we currently are */
2185                 _session->request_play_range (0, true);
2186         }
2187
2188         if (!rolling) {
2189                 _session->request_transport_speed (1.0f);
2190         }
2191 }
2192
2193 bool
2194 ARDOUR_UI::get_smart_mode() const
2195 {
2196         return ( editor->get_smart_mode() );
2197 }
2198
2199
2200 void
2201 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2202 {
2203         if (!_session) {
2204                 return;
2205         }
2206
2207         if (_session->is_auditioning()) {
2208                 _session->cancel_audition ();
2209                 return;
2210         }
2211
2212         if (_session->config.get_external_sync()) {
2213                 switch (Config->get_sync_source()) {
2214                 case Engine:
2215                         break;
2216                 default:
2217                         /* transport controlled by the master */
2218                         return;
2219                 }
2220         }
2221
2222         bool rolling = _session->transport_rolling();
2223         bool affect_transport = true;
2224
2225         if (rolling && roll_out_of_bounded_mode) {
2226                 /* drop out of loop/range playback but leave transport rolling */
2227                 if (_session->get_play_loop()) {
2228                         if (_session->actively_recording()) {
2229
2230                                 /* just stop using the loop, then actually stop
2231                                  * below
2232                                  */
2233                                 _session->request_play_loop (false, affect_transport);
2234
2235                         } else {
2236                                 if (Config->get_seamless_loop()) {
2237                                         /* the disk buffers contain copies of the loop - we can't
2238                                            just keep playing, so stop the transport. the user
2239                                            can restart as they wish.
2240                                         */
2241                                         affect_transport = true;
2242                                 } else {
2243                                         /* disk buffers are normal, so we can keep playing */
2244                                         affect_transport = false;
2245                                 }
2246                                 _session->request_play_loop (false, affect_transport);
2247                         }
2248                 } else if (_session->get_play_range ()) {
2249                         affect_transport = false;
2250                         _session->request_play_range (0, true);
2251                 }
2252         }
2253
2254         if (affect_transport) {
2255                 if (rolling) {
2256                         _session->request_stop (with_abort, true);
2257                 } else {
2258                         /* the only external sync condition we can be in here
2259                          * would be Engine (JACK) sync, in which case we still
2260                          * want to do this.
2261                          */
2262
2263                         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
2264                                 _session->request_play_range (&editor->get_selection().time, true);
2265                                 _session->set_requested_return_frame( editor->get_selection().time.front().start );  //force an auto-return here
2266                         }
2267                         _session->request_transport_speed (1.0f);
2268                 }
2269         }
2270 }
2271
2272 void
2273 ARDOUR_UI::toggle_session_auto_loop ()
2274 {
2275         if (!_session) {
2276                 return;
2277         }
2278
2279         Location * looploc = _session->locations()->auto_loop_location();
2280
2281         if (!looploc) {
2282                 return;
2283         }
2284
2285         if (_session->get_play_loop()) {
2286
2287                 /* looping enabled, our job is to disable it */
2288
2289                 _session->request_play_loop (false);
2290
2291         } else {
2292
2293                 /* looping not enabled, our job is to enable it.
2294
2295                    loop-is-NOT-mode: this action always starts the transport rolling.
2296                    loop-IS-mode:     this action simply sets the loop play mechanism, but
2297                                         does not start transport.
2298                 */
2299                 if (Config->get_loop_is_mode()) {
2300                         _session->request_play_loop (true, false);
2301                 } else {
2302                         _session->request_play_loop (true, true);
2303                 }
2304         }
2305
2306         //show the loop markers
2307         looploc->set_hidden (false, this);
2308 }
2309
2310 void
2311 ARDOUR_UI::transport_play_selection ()
2312 {
2313         if (!_session) {
2314                 return;
2315         }
2316
2317         editor->play_selection ();
2318 }
2319
2320 void
2321 ARDOUR_UI::transport_play_preroll ()
2322 {
2323         if (!_session) {
2324                 return;
2325         }
2326         editor->play_with_preroll ();
2327 }
2328
2329 void
2330 ARDOUR_UI::transport_rewind (int option)
2331 {
2332         float current_transport_speed;
2333
2334         if (_session) {
2335                 current_transport_speed = _session->transport_speed();
2336
2337                 if (current_transport_speed >= 0.0f) {
2338                         switch (option) {
2339                         case 0:
2340                                 _session->request_transport_speed (-1.0f);
2341                                 break;
2342                         case 1:
2343                                 _session->request_transport_speed (-4.0f);
2344                                 break;
2345                         case -1:
2346                                 _session->request_transport_speed (-0.5f);
2347                                 break;
2348                         }
2349                 } else {
2350                         /* speed up */
2351                         _session->request_transport_speed (current_transport_speed * 1.5f);
2352                 }
2353         }
2354 }
2355
2356 void
2357 ARDOUR_UI::transport_forward (int option)
2358 {
2359         if (!_session) {
2360                 return;
2361         }
2362
2363         float current_transport_speed = _session->transport_speed();
2364
2365         if (current_transport_speed <= 0.0f) {
2366                 switch (option) {
2367                 case 0:
2368                         _session->request_transport_speed (1.0f);
2369                         break;
2370                 case 1:
2371                         _session->request_transport_speed (4.0f);
2372                         break;
2373                 case -1:
2374                         _session->request_transport_speed (0.5f);
2375                         break;
2376                 }
2377         } else {
2378                 /* speed up */
2379                 _session->request_transport_speed (current_transport_speed * 1.5f);
2380         }
2381 }
2382
2383 void
2384 ARDOUR_UI::toggle_record_enable (uint16_t rid)
2385 {
2386         if (!_session) {
2387                 return;
2388         }
2389
2390         boost::shared_ptr<Route> r;
2391
2392         if ((r = _session->get_remote_nth_route (rid)) != 0) {
2393
2394                 boost::shared_ptr<Track> t;
2395
2396                 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2397                         t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup);
2398                 }
2399         }
2400 }
2401
2402 void
2403 ARDOUR_UI::map_transport_state ()
2404 {
2405         if (!_session) {
2406                 auto_loop_button.unset_active_state ();
2407                 play_selection_button.unset_active_state ();
2408                 roll_button.unset_active_state ();
2409                 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2410                 return;
2411         }
2412
2413         shuttle_box->map_transport_state ();
2414
2415         float sp = _session->transport_speed();
2416
2417         if (sp != 0.0f) {
2418
2419                 /* we're rolling */
2420
2421                 if (_session->get_play_range()) {
2422
2423                         play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2424                         roll_button.unset_active_state ();
2425                         auto_loop_button.unset_active_state ();
2426
2427                 } else if (_session->get_play_loop ()) {
2428
2429                         auto_loop_button.set_active (true);
2430                         play_selection_button.set_active (false);
2431                         if (Config->get_loop_is_mode()) {
2432                                 roll_button.set_active (true);
2433                         } else {
2434                                 roll_button.set_active (false);
2435                         }
2436
2437                 } else {
2438
2439                         roll_button.set_active (true);
2440                         play_selection_button.set_active (false);
2441                         auto_loop_button.set_active (false);
2442                 }
2443
2444                 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2445                         /* light up both roll and play-selection if they are joined */
2446                         roll_button.set_active (true);
2447                         play_selection_button.set_active (true);
2448                 }
2449
2450                 stop_button.set_active (false);
2451
2452         } else {
2453
2454                 stop_button.set_active (true);
2455                 roll_button.set_active (false);
2456                 play_selection_button.set_active (false);
2457                 if (Config->get_loop_is_mode ()) {
2458                         auto_loop_button.set_active (_session->get_play_loop());
2459                 } else {
2460                         auto_loop_button.set_active (false);
2461                 }
2462                 update_disk_space ();
2463         }
2464 }
2465
2466 void
2467 ARDOUR_UI::blink_handler (bool blink_on)
2468 {
2469         transport_rec_enable_blink (blink_on);
2470         solo_blink (blink_on);
2471         sync_blink (blink_on);
2472         audition_blink (blink_on);
2473         feedback_blink (blink_on);
2474         error_blink (blink_on);
2475 }
2476
2477 void
2478 ARDOUR_UI::update_clocks ()
2479 {
2480         if (!_session) return;
2481
2482         if (editor && !editor->dragging_playhead()) {
2483                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2484         }
2485 }
2486
2487 void
2488 ARDOUR_UI::start_clocking ()
2489 {
2490         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2491                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2492         } else {
2493                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2494         }
2495 }
2496
2497 void
2498 ARDOUR_UI::stop_clocking ()
2499 {
2500         clock_signal_connection.disconnect ();
2501 }
2502
2503 bool
2504 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2505 {
2506         char buf[256];
2507
2508         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2509
2510         label->set_text (buf);
2511         bar->set_fraction (fraction);
2512
2513         /* process events, redraws, etc. */
2514
2515         while (gtk_events_pending()) {
2516                 gtk_main_iteration ();
2517         }
2518
2519         return true; /* continue with save-as */
2520 }
2521
2522 void
2523 ARDOUR_UI::save_session_as ()
2524 {
2525         if (!_session) {
2526                 return;
2527         }
2528
2529         if (!save_as_dialog) {
2530                 save_as_dialog = new SaveAsDialog;
2531         }
2532
2533         save_as_dialog->set_name (_session->name());
2534
2535         int response = save_as_dialog->run ();
2536
2537         save_as_dialog->hide ();
2538
2539         switch (response) {
2540         case Gtk::RESPONSE_OK:
2541                 break;
2542         default:
2543                 return;
2544         }
2545
2546
2547         Session::SaveAs sa;
2548
2549         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2550         sa.new_name = save_as_dialog->new_name ();
2551         sa.switch_to = save_as_dialog->switch_to();
2552         sa.copy_media = save_as_dialog->copy_media();
2553         sa.copy_external = save_as_dialog->copy_external();
2554         sa.include_media = save_as_dialog->include_media ();
2555
2556         /* Only bother with a progress dialog if we're going to copy
2557            media into the save-as target. Without that choice, this
2558            will be very fast because we're only talking about a few kB's to
2559            perhaps a couple of MB's of data.
2560         */
2561
2562         ArdourDialog progress_dialog (_("Save As"), true);
2563
2564         if (sa.include_media && sa.copy_media) {
2565
2566                 Gtk::Label label;
2567                 Gtk::ProgressBar progress_bar;
2568
2569                 progress_dialog.get_vbox()->pack_start (label);
2570                 progress_dialog.get_vbox()->pack_start (progress_bar);
2571                 label.show ();
2572                 progress_bar.show ();
2573
2574                 /* this signal will be emitted from within this, the calling thread,
2575                  * after every file is copied. It provides information on percentage
2576                  * complete (in terms of total data to copy), the number of files
2577                  * copied so far, and the total number to copy.
2578                  */
2579
2580                 ScopedConnection c;
2581
2582                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
2583
2584                 progress_dialog.show_all ();
2585                 progress_dialog.present ();
2586         }
2587
2588         if (_session->save_as (sa)) {
2589                 /* ERROR MESSAGE */
2590                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2591                 msg.run ();
2592         }
2593
2594         if (!sa.include_media) {
2595                 unload_session (false);
2596                 load_session (sa.final_session_folder_name, sa.new_name);
2597         }
2598 }
2599
2600 void
2601 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2602 {
2603                 char timebuf[128];
2604                 time_t n;
2605                 struct tm local_time;
2606
2607                 time (&n);
2608                 localtime_r (&n, &local_time);
2609                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2610
2611                 save_state (timebuf, switch_to_it);
2612 }
2613
2614
2615 bool
2616 ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
2617 {
2618         string snapname;
2619
2620         prompter.get_result (snapname);
2621
2622         bool do_save = (snapname.length() != 0);
2623
2624         if (do_save) {
2625                 char illegal = Session::session_name_is_legal(snapname);
2626                 if (illegal) {
2627                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2628                                              "snapshot names may not contain a '%1' character"), illegal));
2629                         msg.run ();
2630                         return false;
2631                 }
2632         }
2633
2634         vector<std::string> p;
2635         get_state_files_in_directory (_session->session_directory().root_path(), p);
2636         vector<string> n = get_file_names_no_extension (p);
2637
2638         if (find (n.begin(), n.end(), snapname) != n.end()) {
2639
2640                 do_save = overwrite_file_dialog (prompter,
2641                                                  _("Confirm Snapshot Overwrite"),
2642                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2643         }
2644
2645         if (do_save) {
2646                 save_state (snapname, switch_to_it);
2647         }
2648         else {
2649                 return false;
2650         }
2651
2652         return true;
2653 }
2654
2655
2656 /** Ask the user for the name of a new snapshot and then take it.
2657  */
2658
2659 void
2660 ARDOUR_UI::snapshot_session (bool switch_to_it)
2661 {
2662         ArdourPrompter prompter (true);
2663
2664         prompter.set_name ("Prompter");
2665         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2666         if (switch_to_it) {
2667                 prompter.set_title (_("Snapshot and switch"));
2668                 prompter.set_prompt (_("New session name"));
2669         } else {
2670                 prompter.set_title (_("Take Snapshot"));
2671                 prompter.set_prompt (_("Name of new snapshot"));
2672         }
2673
2674         if (switch_to_it) {
2675                 prompter.set_initial_text (_session->snap_name());
2676         } else {
2677                 char timebuf[128];
2678                 time_t n;
2679                 struct tm local_time;
2680
2681                 time (&n);
2682                 localtime_r (&n, &local_time);
2683                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2684                 prompter.set_initial_text (timebuf);
2685         }
2686
2687         bool finished = false;
2688         while (!finished) {
2689                 switch (prompter.run()) {
2690                 case RESPONSE_ACCEPT:
2691                 {
2692                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2693                         break;
2694                 }
2695
2696                 default:
2697                         finished = true;
2698                         break;
2699                 }
2700         }
2701 }
2702
2703 /** Ask the user for a new session name and then rename the session to it.
2704  */
2705
2706 void
2707 ARDOUR_UI::rename_session ()
2708 {
2709         if (!_session) {
2710                 return;
2711         }
2712
2713         ArdourPrompter prompter (true);
2714         string name;
2715
2716         prompter.set_name ("Prompter");
2717         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2718         prompter.set_title (_("Rename Session"));
2719         prompter.set_prompt (_("New session name"));
2720
2721   again:
2722         switch (prompter.run()) {
2723         case RESPONSE_ACCEPT:
2724         {
2725                 prompter.get_result (name);
2726
2727                 bool do_rename = (name.length() != 0);
2728
2729                 if (do_rename) {
2730                         char illegal = Session::session_name_is_legal (name);
2731
2732                         if (illegal) {
2733                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2734                                                                      "session names may not contain a '%1' character"), illegal));
2735                                 msg.run ();
2736                                 goto again;
2737                         }
2738
2739                         switch (_session->rename (name)) {
2740                         case -1: {
2741                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2742                                 msg.set_position (WIN_POS_MOUSE);
2743                                 msg.run ();
2744                                 goto again;
2745                                 break;
2746                         }
2747                         case 0:
2748                                 break;
2749                         default: {
2750                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2751                                 msg.set_position (WIN_POS_MOUSE);
2752                                 msg.run ();
2753                                 break;
2754                         }
2755                         }
2756                 }
2757
2758                 break;
2759         }
2760
2761         default:
2762                 break;
2763         }
2764 }
2765
2766 void
2767 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2768 {
2769         if (!_session || _session->deletion_in_progress()) {
2770                 return;
2771         }
2772
2773         XMLNode* node = new XMLNode (X_("UI"));
2774
2775         WM::Manager::instance().add_state (*node);
2776
2777         node->add_child_nocopy (gui_object_state->get_state());
2778
2779         _session->add_extra_xml (*node);
2780
2781         if (export_video_dialog) {
2782                 _session->add_extra_xml (export_video_dialog->get_state());
2783         }
2784
2785         save_state_canfail (name, switch_to_it);
2786 }
2787
2788 int
2789 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2790 {
2791         if (_session) {
2792                 int ret;
2793
2794                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2795                         return ret;
2796                 }
2797         }
2798
2799         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2800         return 0;
2801 }
2802
2803 void
2804 ARDOUR_UI::primary_clock_value_changed ()
2805 {
2806         if (_session) {
2807                 _session->request_locate (primary_clock->current_time ());
2808         }
2809 }
2810
2811 void
2812 ARDOUR_UI::big_clock_value_changed ()
2813 {
2814         if (_session) {
2815                 _session->request_locate (big_clock->current_time ());
2816         }
2817 }
2818
2819 void
2820 ARDOUR_UI::secondary_clock_value_changed ()
2821 {
2822         if (_session) {
2823                 _session->request_locate (secondary_clock->current_time ());
2824         }
2825 }
2826
2827 void
2828 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2829 {
2830         if (_session == 0) {
2831                 return;
2832         }
2833
2834         if (_session->step_editing()) {
2835                 return;
2836         }
2837
2838         Session::RecordState const r = _session->record_status ();
2839         bool const h = _session->have_rec_enabled_track ();
2840
2841         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2842                 if (onoff) {
2843                         rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2844                 } else {
2845                         rec_button.set_active_state (Gtkmm2ext::Off);
2846                 }
2847         } else if (r == Session::Recording && h) {
2848                 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2849         } else {
2850                 rec_button.unset_active_state ();
2851         }
2852 }
2853
2854 bool
2855 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2856 {
2857         string name;
2858
2859         prompter.get_result (name);
2860
2861         if (name.length()) {
2862                 int failed = _session->save_template (name);
2863
2864                 if (failed == -2) { /* file already exists. */
2865                         bool overwrite = overwrite_file_dialog (prompter,
2866                                                                 _("Confirm Template Overwrite"),
2867                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
2868
2869                         if (overwrite) {
2870                                 _session->save_template (name, true);
2871                         }
2872                         else {
2873                                 return false;
2874                         }
2875                 }
2876         }
2877
2878         return true;
2879 }
2880
2881 void
2882 ARDOUR_UI::save_template ()
2883 {
2884         ArdourPrompter prompter (true);
2885
2886         if (!check_audioengine (_main_window)) {
2887                 return;
2888         }
2889
2890         prompter.set_name (X_("Prompter"));
2891         prompter.set_title (_("Save Template"));
2892         prompter.set_prompt (_("Name for template:"));
2893         prompter.set_initial_text(_session->name() + _("-template"));
2894         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2895
2896         bool finished = false;
2897         while (!finished) {
2898                 switch (prompter.run()) {
2899                 case RESPONSE_ACCEPT:
2900                         finished = process_save_template_prompter (prompter);
2901                         break;
2902
2903                 default:
2904                         finished = true;
2905                         break;
2906                 }
2907         }
2908 }
2909
2910 void
2911 ARDOUR_UI::edit_metadata ()
2912 {
2913         SessionMetadataEditor dialog;
2914         dialog.set_session (_session);
2915         dialog.grab_focus ();
2916         dialog.run ();
2917 }
2918
2919 void
2920 ARDOUR_UI::import_metadata ()
2921 {
2922         SessionMetadataImporter dialog;
2923         dialog.set_session (_session);
2924         dialog.run ();
2925 }
2926
2927 bool
2928 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2929 {
2930         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2931
2932         MessageDialog msg (str,
2933                            false,
2934                            Gtk::MESSAGE_WARNING,
2935                            Gtk::BUTTONS_YES_NO,
2936                            true);
2937
2938
2939         msg.set_name (X_("OpenExistingDialog"));
2940         msg.set_title (_("Open Existing Session"));
2941         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2942         msg.set_position (Gtk::WIN_POS_CENTER);
2943         pop_back_splash (msg);
2944
2945         switch (msg.run()) {
2946         case RESPONSE_YES:
2947                 return true;
2948                 break;
2949         }
2950         return false;
2951 }
2952
2953 int
2954 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
2955 {
2956         BusProfile bus_profile;
2957
2958         if (nsm) {
2959
2960                 bus_profile.master_out_channels = 2;
2961                 bus_profile.input_ac = AutoConnectPhysical;
2962                 bus_profile.output_ac = AutoConnectMaster;
2963                 bus_profile.requested_physical_in = 0; // use all available
2964                 bus_profile.requested_physical_out = 0; // use all available
2965
2966         } else {
2967
2968                 /* get settings from advanced section of NSD */
2969
2970                 if (sd.create_master_bus()) {
2971                         bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
2972                 } else {
2973                         bus_profile.master_out_channels = 0;
2974                 }
2975
2976                 if (sd.connect_inputs()) {
2977                         bus_profile.input_ac = AutoConnectPhysical;
2978                 } else {
2979                         bus_profile.input_ac = AutoConnectOption (0);
2980                 }
2981
2982                 bus_profile.output_ac = AutoConnectOption (0);
2983
2984                 if (sd.connect_outputs ()) {
2985                         if (sd.connect_outs_to_master()) {
2986                                 bus_profile.output_ac = AutoConnectMaster;
2987                         } else if (sd.connect_outs_to_physical()) {
2988                                 bus_profile.output_ac = AutoConnectPhysical;
2989                         }
2990                 }
2991
2992                 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
2993                 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
2994         }
2995
2996         if (build_session (session_path, session_name, bus_profile)) {
2997                 return -1;
2998         }
2999
3000         return 0;
3001 }
3002
3003 void
3004 ARDOUR_UI::load_from_application_api (const std::string& path)
3005 {
3006         ARDOUR_COMMAND_LINE::session_name = path;
3007         /* Cancel SessionDialog if it's visible to make OSX delegates work.
3008          *
3009          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
3010          * race-condition:
3011          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
3012          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
3013          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
3014          *    -> SessionDialog is not displayed
3015          */
3016
3017         if (_session_dialog) {
3018                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3019                 std::string session_path = path;
3020                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
3021                         session_path = Glib::path_get_dirname (session_path);
3022                 }
3023                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
3024                 _session_dialog->set_provided_session (session_name, session_path);
3025                 _session_dialog->response (RESPONSE_NONE);
3026                 _session_dialog->hide();
3027                 return;
3028         }
3029
3030         int rv;
3031         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
3032                 /* /path/to/foo => /path/to/foo, foo */
3033                 rv = load_session (path, basename_nosuffix (path));
3034         } else {
3035                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
3036                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
3037         }
3038
3039         // if load_session fails -> pop up SessionDialog.
3040         if (rv) {
3041                 ARDOUR_COMMAND_LINE::session_name = "";
3042
3043                 if (get_session_parameters (true, false)) {
3044                         exit (1);
3045                 }
3046         }
3047 }
3048
3049 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
3050 int
3051 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
3052 {
3053         string session_name;
3054         string session_path;
3055         string template_name;
3056         int ret = -1;
3057         bool likely_new = false;
3058         bool cancel_not_quit;
3059
3060         /* deal with any existing DIRTY session now, rather than later. don't
3061          * treat a non-dirty session this way, so that it stays visible
3062          * as we bring up the new session dialog.
3063          */
3064
3065         if (_session && ARDOUR_UI::instance()->video_timeline) {
3066                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
3067         }
3068
3069         /* if there is already a session, relabel the button
3070            on the SessionDialog so that we don't Quit directly
3071         */
3072         cancel_not_quit = (_session != 0);
3073
3074         if (_session && _session->dirty()) {
3075                 if (unload_session (false)) {
3076                         /* unload cancelled by user */
3077                         return 0;
3078                 }
3079                 ARDOUR_COMMAND_LINE::session_name = "";
3080         }
3081
3082         if (!load_template.empty()) {
3083                 should_be_new = true;
3084                 template_name = load_template;
3085         }
3086
3087         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3088         session_path = ARDOUR_COMMAND_LINE::session_name;
3089
3090         if (!session_path.empty()) {
3091                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3092                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3093                                 /* session/snapshot file, change path to be dir */
3094                                 session_path = Glib::path_get_dirname (session_path);
3095                         }
3096                 }
3097         }
3098
3099         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3100
3101         _session_dialog = &session_dialog;
3102         while (ret != 0) {
3103
3104                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3105
3106                         /* if they named a specific statefile, use it, otherwise they are
3107                            just giving a session folder, and we want to use it as is
3108                            to find the session.
3109                         */
3110
3111                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3112
3113                         if (suffix != string::npos) {
3114                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3115                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3116                                 session_name = Glib::path_get_basename (session_name);
3117                         } else {
3118                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3119                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3120                         }
3121                 } else {
3122                         session_path = "";
3123                         session_name = "";
3124                         session_dialog.clear_given ();
3125                 }
3126
3127                 if (should_be_new || session_name.empty()) {
3128                         /* need the dialog to get info from user */
3129
3130                         cerr << "run dialog\n";
3131
3132                         switch (session_dialog.run()) {
3133                         case RESPONSE_ACCEPT:
3134                                 break;
3135                         case RESPONSE_NONE:
3136                                 /* this is used for async * app->ShouldLoad(). */
3137                                 continue; // while loop
3138                                 break;
3139                         default:
3140                                 if (quit_on_cancel) {
3141                                         // JE - Currently (July 2014) this section can only get reached if the
3142                                         // user quits from the main 'Session Setup' dialog (i.e. reaching this
3143                                         // point does NOT indicate an abnormal termination). Therefore, let's
3144                                         // behave gracefully (i.e. let's do some cleanup) before we call exit()
3145                                         ARDOUR::cleanup ();
3146                                         pthread_cancel_all ();
3147
3148                                         exit (1);
3149                                 } else {
3150                                         return ret;
3151                                 }
3152                         }
3153
3154                         session_dialog.hide ();
3155                 }
3156
3157                 /* if we run the startup dialog again, offer more than just "new session" */
3158
3159                 should_be_new = false;
3160
3161                 session_name = session_dialog.session_name (likely_new);
3162                 session_path = session_dialog.session_folder ();
3163
3164                 if (nsm) {
3165                         likely_new = true;
3166                 }
3167
3168                 string::size_type suffix = session_name.find (statefile_suffix);
3169
3170                 if (suffix != string::npos) {
3171                         session_name = session_name.substr (0, suffix);
3172                 }
3173
3174                 /* this shouldn't happen, but we catch it just in case it does */
3175
3176                 if (session_name.empty()) {
3177                         continue;
3178                 }
3179
3180                 if (session_dialog.use_session_template()) {
3181                         template_name = session_dialog.session_template_name();
3182                         _session_is_new = true;
3183                 }
3184
3185                 if (session_name[0] == G_DIR_SEPARATOR ||
3186 #ifdef PLATFORM_WINDOWS
3187                     (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3188 #else
3189                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3190                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3191 #endif
3192                          )
3193                 {
3194
3195                         /* absolute path or cwd-relative path specified for session name: infer session folder
3196                            from what was given.
3197                         */
3198
3199                         session_path = Glib::path_get_dirname (session_name);
3200                         session_name = Glib::path_get_basename (session_name);
3201
3202                 } else {
3203
3204                         session_path = session_dialog.session_folder();
3205
3206                         char illegal = Session::session_name_is_legal (session_name);
3207
3208                         if (illegal) {
3209                                 MessageDialog msg (session_dialog,
3210                                                    string_compose (_("To ensure compatibility with various systems\n"
3211                                                                      "session names may not contain a '%1' character"),
3212                                                                    illegal));
3213                                 msg.run ();
3214                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3215                                 continue;
3216                         }
3217                 }
3218
3219                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3220
3221
3222                         if (likely_new && !nsm) {
3223
3224                                 std::string existing = Glib::build_filename (session_path, session_name);
3225
3226                                 if (!ask_about_loading_existing_session (existing)) {
3227                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3228                                         continue;
3229                                 }
3230                         }
3231
3232                         _session_is_new = false;
3233
3234                 } else {
3235
3236                         if (!likely_new) {
3237                                 pop_back_splash (session_dialog);
3238                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3239                                 msg.run ();
3240                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3241                                 continue;
3242                         }
3243
3244                         char illegal = Session::session_name_is_legal(session_name);
3245
3246                         if (illegal) {
3247                                 pop_back_splash (session_dialog);
3248                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3249                                                                                     "session names may not contain a '%1' character"), illegal));
3250                                 msg.run ();
3251                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3252                                 continue;
3253                         }
3254
3255                         _session_is_new = true;
3256                 }
3257
3258                 if (likely_new && template_name.empty()) {
3259
3260                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3261
3262                 } else {
3263
3264                         ret = load_session (session_path, session_name, template_name);
3265
3266                         if (ret == -2) {
3267                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3268                                 exit (1);
3269                         }
3270
3271                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3272                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3273                                 exit (1);
3274                         }
3275
3276                         /* clear this to avoid endless attempts to load the
3277                            same session.
3278                         */
3279
3280                         ARDOUR_COMMAND_LINE::session_name = "";
3281                 }
3282         }
3283
3284         _session_dialog = NULL;
3285
3286         return ret;
3287 }
3288
3289 void
3290 ARDOUR_UI::close_session()
3291 {
3292         if (!check_audioengine (_main_window)) {
3293                 return;
3294         }
3295
3296         if (unload_session (true)) {
3297                 return;
3298         }
3299
3300         ARDOUR_COMMAND_LINE::session_name = "";
3301
3302         if (get_session_parameters (true, false)) {
3303                 exit (1);
3304         }
3305         if (splash && splash->is_visible()) {
3306                 // in 1 second, hide the splash screen
3307                 Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
3308         }
3309 }
3310
3311 /** @param snap_name Snapshot name (without .ardour suffix).
3312  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3313  */
3314 int
3315 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3316 {
3317         Session *new_session;
3318         int unload_status;
3319         int retval = -1;
3320
3321         if (_session) {
3322                 unload_status = unload_session ();
3323
3324                 if (unload_status < 0) {
3325                         goto out;
3326                 } else if (unload_status > 0) {
3327                         retval = 0;
3328                         goto out;
3329                 }
3330         }
3331
3332         session_loaded = false;
3333
3334         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3335
3336         try {
3337                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3338         }
3339
3340         /* this one is special */
3341
3342         catch (AudioEngine::PortRegistrationFailure& err) {
3343
3344                 MessageDialog msg (err.what(),
3345                                    true,
3346                                    Gtk::MESSAGE_INFO,
3347                                    Gtk::BUTTONS_CLOSE);
3348
3349                 msg.set_title (_("Port Registration Error"));
3350                 msg.set_secondary_text (_("Click the Close button to try again."));
3351                 msg.set_position (Gtk::WIN_POS_CENTER);
3352                 pop_back_splash (msg);
3353                 msg.present ();
3354
3355                 int response = msg.run ();
3356
3357                 msg.hide ();
3358
3359                 switch (response) {
3360                 case RESPONSE_CANCEL:
3361                         exit (1);
3362                 default:
3363                         break;
3364                 }
3365                 goto out;
3366         }
3367         catch (SessionException e) {
3368                 MessageDialog msg (string_compose(
3369                                            _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3370                                            path, snap_name, e.what()),
3371                                    true,
3372                                    Gtk::MESSAGE_INFO,
3373                                    BUTTONS_OK);
3374
3375                 msg.set_title (_("Loading Error"));
3376                 msg.set_position (Gtk::WIN_POS_CENTER);
3377                 pop_back_splash (msg);
3378                 msg.present ();
3379
3380                 dump_errors (cerr);
3381
3382                 (void) msg.run ();
3383                 msg.hide ();
3384
3385                 goto out;
3386         }
3387         catch (...) {
3388
3389                 MessageDialog msg (string_compose(
3390                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
3391                                            path, snap_name),
3392                                    true,
3393                                    Gtk::MESSAGE_INFO,
3394                                    BUTTONS_OK);
3395
3396                 msg.set_title (_("Loading Error"));
3397                 msg.set_position (Gtk::WIN_POS_CENTER);
3398                 pop_back_splash (msg);
3399                 msg.present ();
3400
3401                 dump_errors (cerr);
3402
3403                 (void) msg.run ();
3404                 msg.hide ();
3405
3406                 goto out;
3407         }
3408
3409         {
3410                 list<string> const u = new_session->unknown_processors ();
3411                 if (!u.empty()) {
3412                         MissingPluginDialog d (_session, u);
3413                         d.run ();
3414                 }
3415         }
3416
3417         if (!new_session->writable()) {
3418                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3419                                    true,
3420                                    Gtk::MESSAGE_INFO,
3421                                    BUTTONS_OK);
3422
3423                 msg.set_title (_("Read-only Session"));
3424                 msg.set_position (Gtk::WIN_POS_CENTER);
3425                 pop_back_splash (msg);
3426                 msg.present ();
3427                 (void) msg.run ();
3428                 msg.hide ();
3429         }
3430
3431
3432         /* Now the session been created, add the transport controls */
3433         new_session->add_controllable(roll_controllable);
3434         new_session->add_controllable(stop_controllable);
3435         new_session->add_controllable(goto_start_controllable);
3436         new_session->add_controllable(goto_end_controllable);
3437         new_session->add_controllable(auto_loop_controllable);
3438         new_session->add_controllable(play_selection_controllable);
3439         new_session->add_controllable(rec_controllable);
3440
3441         set_session (new_session);
3442
3443         session_loaded = true;
3444
3445         if (_session) {
3446                 _session->set_clean ();
3447         }
3448
3449 #ifdef WINDOWS_VST_SUPPORT
3450         fst_stop_threading();
3451 #endif
3452
3453         {
3454                 Timers::TimerSuspender t;
3455                 flush_pending ();
3456         }
3457
3458 #ifdef WINDOWS_VST_SUPPORT
3459         fst_start_threading();
3460 #endif
3461         retval = 0;
3462
3463   out:
3464         return retval;
3465 }
3466
3467 int
3468 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3469 {
3470         Session *new_session;
3471         int x;
3472
3473         session_loaded = false;
3474         x = unload_session ();
3475
3476         if (x < 0) {
3477                 return -1;
3478         } else if (x > 0) {
3479                 return 0;
3480         }
3481
3482         _session_is_new = true;
3483
3484         try {
3485                 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3486         }
3487
3488         catch (SessionException e) {
3489                 dump_errors (cerr);
3490                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3491                 msg.set_title (_("Loading Error"));
3492                 msg.set_position (Gtk::WIN_POS_CENTER);
3493                 pop_back_splash (msg);
3494                 msg.run ();
3495                 return -1;
3496         }
3497         catch (...) {
3498                 dump_errors (cerr);
3499                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3500                 msg.set_title (_("Loading Error"));
3501                 msg.set_position (Gtk::WIN_POS_CENTER);
3502                 pop_back_splash (msg);
3503                 msg.run ();
3504                 return -1;
3505         }
3506
3507         /* Give the new session the default GUI state, if such things exist */
3508
3509         XMLNode* n;
3510         n = Config->instant_xml (X_("Editor"));
3511         if (n) {
3512                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3513                 new_session->add_instant_xml (*n, false);
3514         }
3515         n = Config->instant_xml (X_("Mixer"));
3516         if (n) {
3517                 new_session->add_instant_xml (*n, false);
3518         }
3519
3520         /* Put the playhead at 0 and scroll fully left */
3521         n = new_session->instant_xml (X_("Editor"));
3522         if (n) {
3523                 n->add_property (X_("playhead"), X_("0"));
3524                 n->add_property (X_("left-frame"), X_("0"));
3525         }
3526
3527         set_session (new_session);
3528
3529         session_loaded = true;
3530
3531         new_session->save_state(new_session->name());
3532
3533         return 0;
3534 }
3535
3536 void
3537 ARDOUR_UI::launch_chat ()
3538 {
3539         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3540
3541         dialog.set_title (_("About the Chat"));
3542         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."));
3543
3544         switch (dialog.run()) {
3545         case RESPONSE_OK:
3546 #ifdef __APPLE__
3547                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3548 #elif defined PLATFORM_WINDOWS
3549                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3550 #else
3551                 open_uri("http://webchat.freenode.net/?channels=ardour");
3552 #endif
3553                 break;
3554         default:
3555                 break;
3556         }
3557 }
3558
3559 void
3560 ARDOUR_UI::launch_manual ()
3561 {
3562         PBD::open_uri (Config->get_tutorial_manual_url());
3563 }
3564
3565 void
3566 ARDOUR_UI::launch_reference ()
3567 {
3568         PBD::open_uri (Config->get_reference_manual_url());
3569 }
3570
3571 void
3572 ARDOUR_UI::launch_tracker ()
3573 {
3574         PBD::open_uri ("http://tracker.ardour.org");
3575 }
3576
3577 void
3578 ARDOUR_UI::launch_subscribe ()
3579 {
3580         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3581 }
3582
3583 void
3584 ARDOUR_UI::launch_cheat_sheet ()
3585 {
3586 #ifdef __APPLE__
3587         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3588 #else
3589         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3590 #endif
3591 }
3592
3593 void
3594 ARDOUR_UI::launch_website ()
3595 {
3596         PBD::open_uri ("http://ardour.org");
3597 }
3598
3599 void
3600 ARDOUR_UI::launch_website_dev ()
3601 {
3602         PBD::open_uri ("http://ardour.org/development.html");
3603 }
3604
3605 void
3606 ARDOUR_UI::launch_forums ()
3607 {
3608         PBD::open_uri ("https://community.ardour.org/forums");
3609 }
3610
3611 void
3612 ARDOUR_UI::launch_howto_report ()
3613 {
3614         PBD::open_uri ("http://ardour.org/reporting_bugs");
3615 }
3616
3617 void
3618 ARDOUR_UI::loading_message (const std::string& msg)
3619 {
3620         if (ARDOUR_COMMAND_LINE::no_splash) {
3621                 return;
3622         }
3623
3624         if (!splash) {
3625                 show_splash ();
3626         }
3627
3628         splash->message (msg);
3629 }
3630
3631 void
3632 ARDOUR_UI::show_splash ()
3633 {
3634         if (splash == 0) {
3635                 try {
3636                         splash = new Splash;
3637                 } catch (...) {
3638                         return;
3639                 }
3640         }
3641
3642         splash->display ();
3643 }
3644
3645 void
3646 ARDOUR_UI::hide_splash ()
3647 {
3648         delete splash;
3649         splash = 0;
3650 }
3651
3652 void
3653 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3654 {
3655         size_t removed;
3656
3657         removed = rep.paths.size();
3658
3659         if (removed == 0) {
3660                 MessageDialog msgd (_main_window,
3661                                     _("No files were ready for clean-up"),
3662                                     true,
3663                                     Gtk::MESSAGE_INFO,
3664                                     Gtk::BUTTONS_OK);
3665                 msgd.set_title (_("Clean-up"));
3666                 msgd.set_secondary_text (_("If this seems suprising, \n\
3667 check for any existing snapshots.\n\
3668 These may still include regions that\n\
3669 require some unused files to continue to exist."));
3670
3671                 msgd.run ();
3672                 return;
3673         }
3674
3675         ArdourDialog results (_("Clean-up"), true, false);
3676
3677         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3678             CleanupResultsModelColumns() {
3679                     add (visible_name);
3680                     add (fullpath);
3681             }
3682             Gtk::TreeModelColumn<std::string> visible_name;
3683             Gtk::TreeModelColumn<std::string> fullpath;
3684         };
3685
3686
3687         CleanupResultsModelColumns results_columns;
3688         Glib::RefPtr<Gtk::ListStore> results_model;
3689         Gtk::TreeView results_display;
3690
3691         results_model = ListStore::create (results_columns);
3692         results_display.set_model (results_model);
3693         results_display.append_column (list_title, results_columns.visible_name);
3694
3695         results_display.set_name ("CleanupResultsList");
3696         results_display.set_headers_visible (true);
3697         results_display.set_headers_clickable (false);
3698         results_display.set_reorderable (false);
3699
3700         Gtk::ScrolledWindow list_scroller;
3701         Gtk::Label txt;
3702         Gtk::VBox dvbox;
3703         Gtk::HBox dhbox;  // the hbox for the image and text
3704         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3705         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3706
3707         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3708
3709         const string dead_directory = _session->session_directory().dead_path();
3710
3711         /* subst:
3712            %1 - number of files removed
3713            %2 - location of "dead"
3714            %3 - size of files affected
3715            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3716         */
3717
3718         const char* bprefix;
3719         double space_adjusted = 0;
3720
3721         if (rep.space < 1000) {
3722                 bprefix = X_("");
3723                 space_adjusted = rep.space;
3724         } else if (rep.space < 1000000) {
3725                 bprefix = _("kilo");
3726                 space_adjusted = floorf((float)rep.space / 1000.0);
3727         } else if (rep.space < 1000000 * 1000) {
3728                 bprefix = _("mega");
3729                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3730         } else {
3731                 bprefix = _("giga");
3732                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3733         }
3734
3735         if (msg_delete) {
3736                 txt.set_markup (string_compose (P_("\
3737 The following file was deleted from %2,\n\
3738 releasing %3 %4bytes of disk space", "\
3739 The following %1 files were deleted from %2,\n\
3740 releasing %3 %4bytes of disk space", removed),
3741                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3742         } else {
3743                 txt.set_markup (string_compose (P_("\
3744 The following file was not in use and \n\
3745 has been moved to: %2\n\n\
3746 After a restart of %5\n\n\
3747 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3748 will release an additional %3 %4bytes of disk space.\n", "\
3749 The following %1 files were not in use and \n\
3750 have been moved to: %2\n\n\
3751 After a restart of %5\n\n\
3752 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3753 will release an additional %3 %4bytes of disk space.\n", removed),
3754                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3755         }
3756
3757         dhbox.pack_start (*dimage, true, false, 5);
3758         dhbox.pack_start (txt, true, false, 5);
3759
3760         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3761                 TreeModel::Row row = *(results_model->append());
3762                 row[results_columns.visible_name] = *i;
3763                 row[results_columns.fullpath] = *i;
3764         }
3765
3766         list_scroller.add (results_display);
3767         list_scroller.set_size_request (-1, 150);
3768         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3769
3770         dvbox.pack_start (dhbox, true, false, 5);
3771         dvbox.pack_start (list_scroller, true, false, 5);
3772         ddhbox.pack_start (dvbox, true, false, 5);
3773
3774         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3775         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3776         results.set_default_response (RESPONSE_CLOSE);
3777         results.set_position (Gtk::WIN_POS_MOUSE);
3778
3779         results_display.show();
3780         list_scroller.show();
3781         txt.show();
3782         dvbox.show();
3783         dhbox.show();
3784         ddhbox.show();
3785         dimage->show();
3786
3787         //results.get_vbox()->show();
3788         results.set_resizable (false);
3789
3790         results.run ();
3791
3792 }
3793
3794 void
3795 ARDOUR_UI::cleanup ()
3796 {
3797         if (_session == 0) {
3798                 /* shouldn't happen: menu item is insensitive */
3799                 return;
3800         }
3801
3802
3803         MessageDialog checker (_("Are you sure you want to clean-up?"),
3804                                 true,
3805                                 Gtk::MESSAGE_QUESTION,
3806                                 Gtk::BUTTONS_NONE);
3807
3808         checker.set_title (_("Clean-up"));
3809
3810         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3811 ALL undo/redo information will be lost if you clean-up.\n\
3812 Clean-up will move all unused files to a \"dead\" location."));
3813
3814         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3815         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3816         checker.set_default_response (RESPONSE_CANCEL);
3817
3818         checker.set_name (_("CleanupDialog"));
3819         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3820         checker.set_position (Gtk::WIN_POS_MOUSE);
3821
3822         switch (checker.run()) {
3823         case RESPONSE_ACCEPT:
3824                 break;
3825         default:
3826                 return;
3827         }
3828
3829         ARDOUR::CleanupReport rep;
3830
3831         editor->prepare_for_cleanup ();
3832
3833         /* do not allow flush until a session is reloaded */
3834
3835         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3836         if (act) {
3837                 act->set_sensitive (false);
3838         }
3839
3840         if (_session->cleanup_sources (rep)) {
3841                 editor->finish_cleanup ();
3842                 return;
3843         }
3844
3845         editor->finish_cleanup ();
3846
3847         checker.hide();
3848         display_cleanup_results (rep, _("Cleaned Files"), false);
3849 }
3850
3851 void
3852 ARDOUR_UI::flush_trash ()
3853 {
3854         if (_session == 0) {
3855                 /* shouldn't happen: menu item is insensitive */
3856                 return;
3857         }
3858
3859         ARDOUR::CleanupReport rep;
3860
3861         if (_session->cleanup_trash_sources (rep)) {
3862                 return;
3863         }
3864
3865         display_cleanup_results (rep, _("deleted file"), true);
3866 }
3867
3868 void
3869 ARDOUR_UI::cleanup_peakfiles ()
3870 {
3871         if (_session == 0) {
3872                 /* shouldn't happen: menu item is insensitive */
3873                 return;
3874         }
3875
3876         if (! _session->can_cleanup_peakfiles ()) {
3877                 return;
3878         }
3879
3880         // get all region-views in this session
3881         RegionSelection rs;
3882         TrackViewList empty;
3883         empty.clear();
3884         editor->get_regions_after(rs, (framepos_t) 0, empty);
3885         std::list<RegionView*> views = rs.by_layer();
3886
3887         // remove displayed audio-region-views waveforms
3888         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3889                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3890                 if (!arv) { continue ; }
3891                 arv->delete_waves();
3892         }
3893
3894         // cleanup peak files:
3895         // - stop pending peakfile threads
3896         // - close peakfiles if any
3897         // - remove peak dir in session
3898         // - setup peakfiles (background thread)
3899         _session->cleanup_peakfiles ();
3900
3901         // re-add waves to ARV
3902         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3903                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3904                 if (!arv) { continue ; }
3905                 arv->create_waves();
3906         }
3907 }
3908
3909 PresentationInfo::order_t
3910 ARDOUR_UI::translate_order (AddRouteDialog::InsertAt place)
3911 {
3912         if (editor->get_selection().tracks.empty()) {
3913                 return PresentationInfo::max_order;
3914         }
3915
3916         PresentationInfo::order_t order_hint = PresentationInfo::max_order;
3917
3918         /*
3919           we want the new routes to have their order keys set starting from
3920           the highest order key in the selection + 1 (if available).
3921         */
3922
3923         if (place == AddRouteDialog::AfterSelection) {
3924                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
3925                 if (rtav) {
3926                         order_hint = rtav->route()->presentation_info().group_order();
3927                         order_hint++;
3928                 }
3929         } else if (place == AddRouteDialog::BeforeSelection) {
3930                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
3931                 if (rtav) {
3932                         order_hint = rtav->route()->presentation_info().group_order();
3933                 }
3934         } else if (place == AddRouteDialog::First) {
3935                 order_hint = 0;
3936         } else {
3937                 /* leave order_hint at max_order */
3938         }
3939
3940         return order_hint;
3941 }
3942
3943 void
3944 ARDOUR_UI::start_duplicate_routes ()
3945 {
3946         if (!duplicate_routes_dialog) {
3947                 duplicate_routes_dialog = new DuplicateRouteDialog;
3948         }
3949
3950         if (duplicate_routes_dialog->restart (_session)) {
3951                 return;
3952         }
3953
3954         duplicate_routes_dialog->present ();
3955 }
3956
3957 void
3958 ARDOUR_UI::add_route ()
3959 {
3960         int count;
3961
3962         if (!_session) {
3963                 return;
3964         }
3965
3966         if (add_route_dialog->is_visible()) {
3967                 /* we're already doing this */
3968                 return;
3969         }
3970
3971         ResponseType r = (ResponseType) add_route_dialog->run ();
3972
3973         add_route_dialog->hide();
3974
3975         switch (r) {
3976                 case RESPONSE_ACCEPT:
3977                         break;
3978                 default:
3979                         return;
3980                         break;
3981         }
3982
3983         if ((count = add_route_dialog->count()) <= 0) {
3984                 return;
3985         }
3986
3987         PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
3988         string template_path = add_route_dialog->track_template();
3989         DisplaySuspender ds;
3990
3991         if (!template_path.empty()) {
3992                 if (add_route_dialog->name_template_is_default())  {
3993                         _session->new_route_from_template (count, template_path, string());
3994                 } else {
3995                         _session->new_route_from_template (count, template_path, add_route_dialog->name_template());
3996                 }
3997                 return;
3998         }
3999
4000         ChanCount input_chan= add_route_dialog->channels ();
4001         ChanCount output_chan;
4002         string name_template = add_route_dialog->name_template ();
4003         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
4004         RouteGroup* route_group = add_route_dialog->route_group ();
4005         AutoConnectOption oac = Config->get_output_auto_connect();
4006         bool strict_io = add_route_dialog->use_strict_io ();
4007
4008         if (oac & AutoConnectMaster) {
4009                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
4010                 output_chan.set (DataType::MIDI, 0);
4011         } else {
4012                 output_chan = input_chan;
4013         }
4014
4015         /* XXX do something with name template */
4016
4017         switch (add_route_dialog->type_wanted()) {
4018         case AddRouteDialog::AudioTrack:
4019                 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
4020                 break;
4021         case AddRouteDialog::MidiTrack:
4022                 session_add_midi_track (route_group, count, name_template, strict_io, instrument, 0, order);
4023                 break;
4024         case AddRouteDialog::MixedTrack:
4025                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
4026                 break;
4027         case AddRouteDialog::AudioBus:
4028                 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io, order);
4029                 break;
4030         case AddRouteDialog::MidiBus:
4031                 session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
4032                 break;
4033         case AddRouteDialog::VCAMaster:
4034                 session_add_vca (name_template, count);
4035                 break;
4036         }
4037 }
4038
4039 void
4040 ARDOUR_UI::add_lua_script ()
4041 {
4042         if (!_session) {
4043                 return;
4044         }
4045
4046         LuaScriptInfoPtr spi;
4047         ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
4048         switch (ss.run ()) {
4049                 case Gtk::RESPONSE_ACCEPT:
4050                         spi = ss.script();
4051                         break;
4052                 default:
4053                         return;
4054         }
4055         ss.hide();
4056
4057         std::string script = "";
4058
4059         try {
4060                 script = Glib::file_get_contents (spi->path);
4061         } catch (Glib::FileError e) {
4062                 string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
4063                 MessageDialog am (msg);
4064                 am.run ();
4065                 return;
4066         }
4067
4068         LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
4069         std::vector<std::string> reg = _session->registered_lua_functions ();
4070
4071         ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
4072         switch (spd.run ()) {
4073                 case Gtk::RESPONSE_ACCEPT:
4074                         break;
4075                 default:
4076                         return;
4077         }
4078
4079         try {
4080                 _session->register_lua_function (spd.name(), script, lsp);
4081         } catch (luabridge::LuaException const& e) {
4082                 string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
4083                 MessageDialog am (msg);
4084                 am.run ();
4085         } catch (SessionException e) {
4086                 string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
4087                 MessageDialog am (msg);
4088                 am.run ();
4089         }
4090 }
4091
4092 void
4093 ARDOUR_UI::remove_lua_script ()
4094 {
4095         if (!_session) {
4096                 return;
4097         }
4098         if (_session->registered_lua_function_count () ==  0) {
4099                 string msg = _("There are no active Lua session scripts present in this session.");
4100                 MessageDialog am (msg);
4101                 am.run ();
4102                 return;
4103         }
4104
4105         std::vector<std::string> reg = _session->registered_lua_functions ();
4106         SessionScriptManager sm ("Remove Lua Session Script", reg);
4107         switch (sm.run ()) {
4108                 case Gtk::RESPONSE_ACCEPT:
4109                         break;
4110                 default:
4111                         return;
4112         }
4113         try {
4114                 _session->unregister_lua_function (sm.name());
4115         } catch (luabridge::LuaException const& e) {
4116                 string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
4117                 MessageDialog am (msg);
4118                 am.run ();
4119         }
4120 }
4121
4122 void
4123 ARDOUR_UI::stop_video_server (bool ask_confirm)
4124 {
4125         if (!video_server_process && ask_confirm) {
4126                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4127         }
4128         if (video_server_process) {
4129                 if(ask_confirm) {
4130                         ArdourDialog confirm (_("Stop Video-Server"), true);
4131                         Label m (_("Do you really want to stop the Video Server?"));
4132                         confirm.get_vbox()->pack_start (m, true, true);
4133                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4134                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4135                         confirm.show_all ();
4136                         if (confirm.run() == RESPONSE_CANCEL) {
4137                                 return;
4138                         }
4139                 }
4140                 delete video_server_process;
4141                 video_server_process =0;
4142         }
4143 }
4144
4145 void
4146 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4147 {
4148   ARDOUR_UI::start_video_server( float_window, true);
4149 }
4150
4151 bool
4152 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4153 {
4154         if (!_session) {
4155                 return false;
4156         }
4157         if (popup_msg) {
4158                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4159                         if (video_server_process) {
4160                                 popup_error(_("The Video Server is already started."));
4161                         } else {
4162                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4163                         }
4164                 }
4165         }
4166
4167         int firsttime = 0;
4168         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4169                 if (firsttime++) {
4170                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4171                 }
4172                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4173                 if (float_window) {
4174                         video_server_dialog->set_transient_for (*float_window);
4175                 }
4176
4177                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4178                         video_server_dialog->hide();
4179                 } else {
4180                         ResponseType r = (ResponseType) video_server_dialog->run ();
4181                         video_server_dialog->hide();
4182                         if (r != RESPONSE_ACCEPT) { return false; }
4183                         if (video_server_dialog->show_again()) {
4184                                 Config->set_show_video_server_dialog(false);
4185                         }
4186                 }
4187
4188                 std::string icsd_exec = video_server_dialog->get_exec_path();
4189                 std::string icsd_docroot = video_server_dialog->get_docroot();
4190                 if (icsd_docroot.empty()) {
4191 #ifndef PLATFORM_WINDOWS
4192                         icsd_docroot = X_("/");
4193 #else
4194                         icsd_docroot = X_("C:\\");
4195 #endif
4196                 }
4197
4198                 GStatBuf sb;
4199                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4200                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4201                         continue;
4202                 }
4203 #ifndef PLATFORM_WINDOWS
4204                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4205                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4206                         warning << _("Given Video Server is not an executable file.") << endmsg;
4207                         continue;
4208                 }
4209 #else
4210                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4211                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4212                         warning << _("Given Video Server is not an executable file.") << endmsg;
4213                         continue;
4214                 }
4215 #endif
4216
4217                 char **argp;
4218                 argp=(char**) calloc(9,sizeof(char*));
4219                 argp[0] = strdup(icsd_exec.c_str());
4220                 argp[1] = strdup("-P");
4221                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4222                 argp[3] = strdup("-p");
4223                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4224                 argp[5] = strdup("-C");
4225                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4226                 argp[7] = strdup(icsd_docroot.c_str());
4227                 argp[8] = 0;
4228                 stop_video_server();
4229
4230                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4231                         Config->set_video_advanced_setup(false);
4232                 } else {
4233                         std::ostringstream osstream;
4234                         osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4235                         Config->set_video_server_url(osstream.str());
4236                         Config->set_video_server_docroot(icsd_docroot);
4237                         Config->set_video_advanced_setup(true);
4238                 }
4239
4240                 if (video_server_process) {
4241                         delete video_server_process;
4242                 }
4243
4244                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4245                 if (video_server_process->start()) {
4246                         warning << _("Cannot launch the video-server") << endmsg;
4247                         continue;
4248                 }
4249                 int timeout = 120; // 6 sec
4250                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4251                         Glib::usleep (50000);
4252                         gui_idle_handler();
4253                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4254                 }
4255                 if (timeout <= 0) {
4256                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4257                 } else {
4258                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4259                                 delete video_server_process;
4260                                 video_server_process = 0;
4261                         }
4262                 }
4263         }
4264         return true;
4265 }
4266
4267 void
4268 ARDOUR_UI::add_video (Gtk::Window* float_window)
4269 {
4270         if (!_session) {
4271                 return;
4272         }
4273
4274         if (!start_video_server(float_window, false)) {
4275                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4276                 return;
4277         }
4278
4279         if (float_window) {
4280                 add_video_dialog->set_transient_for (*float_window);
4281         }
4282
4283         if (add_video_dialog->is_visible()) {
4284                 /* we're already doing this */
4285                 return;
4286         }
4287
4288         ResponseType r = (ResponseType) add_video_dialog->run ();
4289         add_video_dialog->hide();
4290         if (r != RESPONSE_ACCEPT) { return; }
4291
4292         bool local_file, orig_local_file;
4293         std::string path = add_video_dialog->file_name(local_file);
4294
4295         std::string orig_path = path;
4296         orig_local_file = local_file;
4297
4298         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4299
4300         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4301                 warning << string_compose(_("could not open %1"), path) << endmsg;
4302                 return;
4303         }
4304         if (!local_file && path.length() == 0) {
4305                 warning << _("no video-file selected") << endmsg;
4306                 return;
4307         }
4308
4309         std::string audio_from_video;
4310         bool detect_ltc = false;
4311
4312         switch (add_video_dialog->import_option()) {
4313                 case VTL_IMPORT_TRANSCODE:
4314                         {
4315                                 TranscodeVideoDialog *transcode_video_dialog;
4316                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4317                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4318                                 transcode_video_dialog->hide();
4319                                 if (r != RESPONSE_ACCEPT) {
4320                                         delete transcode_video_dialog;
4321                                         return;
4322                                 }
4323
4324                                 audio_from_video = transcode_video_dialog->get_audiofile();
4325
4326                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4327                                         detect_ltc = true;
4328                                 }
4329                                 else if (!audio_from_video.empty()) {
4330                                         editor->embed_audio_from_video(
4331                                                         audio_from_video,
4332                                                         video_timeline->get_offset(),
4333                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4334                                                         );
4335                                 }
4336                                 switch (transcode_video_dialog->import_option()) {
4337                                         case VTL_IMPORT_TRANSCODED:
4338                                                 path = transcode_video_dialog->get_filename();
4339                                                 local_file = true;
4340                                                 break;
4341                                         case VTL_IMPORT_REFERENCE:
4342                                                 break;
4343                                         default:
4344                                                 delete transcode_video_dialog;
4345                                                 return;
4346                                 }
4347                                 delete transcode_video_dialog;
4348                         }
4349                         break;
4350                 default:
4351                 case VTL_IMPORT_NONE:
4352                         break;
4353         }
4354
4355         /* strip _session->session_directory().video_path() from video file if possible */
4356         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4357                  path=path.substr(_session->session_directory().video_path().size());
4358                  if (path.at(0) == G_DIR_SEPARATOR) {
4359                          path=path.substr(1);
4360                  }
4361         }
4362
4363         video_timeline->set_update_session_fps(auto_set_session_fps);
4364
4365         if (video_timeline->video_file_info(path, local_file)) {
4366                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4367                 node->add_property (X_("Filename"), path);
4368                 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4369                 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4370                 if (orig_local_file) {
4371                         node->add_property (X_("OriginalVideoFile"), orig_path);
4372                 } else {
4373                         node->remove_property (X_("OriginalVideoFile"));
4374                 }
4375                 _session->add_extra_xml (*node);
4376                 _session->set_dirty ();
4377
4378                 if (!audio_from_video.empty() && detect_ltc) {
4379                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4380
4381                         try {
4382                                 /* TODO ask user about TV standard (LTC alignment if any) */
4383                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4384                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4385
4386                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4387
4388                                 /* TODO seek near end of file, and read LTC until end.
4389                                  * if it fails to find any LTC frames, scan complete file
4390                                  *
4391                                  * calculate drift of LTC compared to video-duration,
4392                                  * ask user for reference (timecode from start/mid/end)
4393                                  */
4394                         } catch (...) {
4395                                 // LTCFileReader will have written error messages
4396                         }
4397
4398                         ::g_unlink(audio_from_video.c_str());
4399
4400                         if (ltc_seq.size() == 0) {
4401                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4402                         } else {
4403                                 /* the very first TC in the file is somteimes not aligned properly */
4404                                 int i = ltc_seq.size() -1;
4405                                 ARDOUR::frameoffset_t video_start_offset =
4406                                         _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4407                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4408                                 video_timeline->set_offset(video_start_offset);
4409                         }
4410                 }
4411
4412                 _session->maybe_update_session_range(
4413                         std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4414                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4415
4416
4417                 if (add_video_dialog->launch_xjadeo() && local_file) {
4418                         editor->set_xjadeo_sensitive(true);
4419                         editor->toggle_xjadeo_proc(1);
4420                 } else {
4421                         editor->toggle_xjadeo_proc(0);
4422                 }
4423                 editor->toggle_ruler_video(true);
4424         }
4425 }
4426
4427 void
4428 ARDOUR_UI::remove_video ()
4429 {
4430         video_timeline->close_session();
4431         editor->toggle_ruler_video(false);
4432
4433         /* reset state */
4434         video_timeline->set_offset_locked(false);
4435         video_timeline->set_offset(0);
4436
4437         /* delete session state */
4438         XMLNode* node = new XMLNode(X_("Videotimeline"));
4439         _session->add_extra_xml(*node);
4440         node = new XMLNode(X_("Videomonitor"));
4441         _session->add_extra_xml(*node);
4442         node = new XMLNode(X_("Videoexport"));
4443         _session->add_extra_xml(*node);
4444         stop_video_server();
4445 }
4446
4447 void
4448 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4449 {
4450         if (localcacheonly) {
4451                 video_timeline->vmon_update();
4452         } else {
4453                 video_timeline->flush_cache();
4454         }
4455         editor->queue_visual_videotimeline_update();
4456 }
4457
4458 void
4459 ARDOUR_UI::export_video (bool range)
4460 {
4461         if (ARDOUR::Config->get_show_video_export_info()) {
4462                 ExportVideoInfobox infobox (_session);
4463                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4464                 if (infobox.show_again()) {
4465                         ARDOUR::Config->set_show_video_export_info(false);
4466                 }
4467                 switch (rv) {
4468                         case GTK_RESPONSE_YES:
4469                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4470                                 break;
4471                         default:
4472                                 break;
4473                 }
4474         }
4475         export_video_dialog->set_session (_session);
4476         export_video_dialog->apply_state(editor->get_selection().time, range);
4477         export_video_dialog->run ();
4478         export_video_dialog->hide ();
4479 }
4480
4481 XMLNode*
4482 ARDOUR_UI::mixer_settings () const
4483 {
4484         XMLNode* node = 0;
4485
4486         if (_session) {
4487                 node = _session->instant_xml(X_("Mixer"));
4488         } else {
4489                 node = Config->instant_xml(X_("Mixer"));
4490         }
4491
4492         if (!node) {
4493                 node = new XMLNode (X_("Mixer"));
4494         }
4495
4496         return node;
4497 }
4498
4499 XMLNode*
4500 ARDOUR_UI::main_window_settings () const
4501 {
4502         XMLNode* node = 0;
4503
4504         if (_session) {
4505                 node = _session->instant_xml(X_("Main"));
4506         } else {
4507                 node = Config->instant_xml(X_("Main"));
4508         }
4509
4510         if (!node) {
4511                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4512                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4513                 }
4514         }
4515
4516         if (!node) {
4517                 node = new XMLNode (X_("Main"));
4518         }
4519
4520         return node;
4521 }
4522
4523 XMLNode*
4524 ARDOUR_UI::editor_settings () const
4525 {
4526         XMLNode* node = 0;
4527
4528         if (_session) {
4529                 node = _session->instant_xml(X_("Editor"));
4530         } else {
4531                 node = Config->instant_xml(X_("Editor"));
4532         }
4533
4534         if (!node) {
4535                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4536                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4537                 }
4538         }
4539
4540         if (!node) {
4541                 node = new XMLNode (X_("Editor"));
4542         }
4543
4544         return node;
4545 }
4546
4547 XMLNode*
4548 ARDOUR_UI::keyboard_settings () const
4549 {
4550         XMLNode* node = 0;
4551
4552         node = Config->extra_xml(X_("Keyboard"));
4553
4554         if (!node) {
4555                 node = new XMLNode (X_("Keyboard"));
4556         }
4557
4558         return node;
4559 }
4560
4561 void
4562 ARDOUR_UI::create_xrun_marker (framepos_t where)
4563 {
4564         if (_session) {
4565                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
4566                 _session->locations()->add (location);
4567         }
4568 }
4569
4570 void
4571 ARDOUR_UI::halt_on_xrun_message ()
4572 {
4573         cerr << "HALT on xrun\n";
4574         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4575         msg.run ();
4576 }
4577
4578 void
4579 ARDOUR_UI::xrun_handler (framepos_t where)
4580 {
4581         if (!_session) {
4582                 return;
4583         }
4584
4585         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4586
4587         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4588                 create_xrun_marker(where);
4589         }
4590
4591         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4592                 halt_on_xrun_message ();
4593         }
4594 }
4595
4596 void
4597 ARDOUR_UI::disk_overrun_handler ()
4598 {
4599         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4600
4601         if (!have_disk_speed_dialog_displayed) {
4602                 have_disk_speed_dialog_displayed = true;
4603                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4604 The disk system on your computer\n\
4605 was not able to keep up with %1.\n\
4606 \n\
4607 Specifically, it failed to write data to disk\n\
4608 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4609                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4610                 msg->show ();
4611         }
4612 }
4613
4614
4615 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4616 static MessageDialog *scan_dlg = NULL;
4617 static ProgressBar   *scan_pbar = NULL;
4618 static HBox          *scan_tbox = NULL;
4619 static Gtk::Button   *scan_timeout_button;
4620
4621 void
4622 ARDOUR_UI::cancel_plugin_scan ()
4623 {
4624         PluginManager::instance().cancel_plugin_scan();
4625 }
4626
4627 void
4628 ARDOUR_UI::cancel_plugin_timeout ()
4629 {
4630         PluginManager::instance().cancel_plugin_timeout();
4631         scan_timeout_button->set_sensitive (false);
4632 }
4633
4634 void
4635 ARDOUR_UI::plugin_scan_timeout (int timeout)
4636 {
4637         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4638                 return;
4639         }
4640         if (timeout > 0) {
4641                 scan_pbar->set_sensitive (false);
4642                 scan_timeout_button->set_sensitive (true);
4643                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4644                 scan_tbox->show();
4645         } else {
4646                 scan_pbar->set_sensitive (false);
4647                 scan_timeout_button->set_sensitive (false);
4648         }
4649         gui_idle_handler();
4650 }
4651
4652 void
4653 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4654 {
4655         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4656                 return;
4657         }
4658
4659         const bool cancelled = PluginManager::instance().cancelled();
4660         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4661                 if (cancelled && scan_dlg->is_mapped()) {
4662                         scan_dlg->hide();
4663                         gui_idle_handler();
4664                         return;
4665                 }
4666                 if (cancelled || !can_cancel) {
4667                         return;
4668                 }
4669         }
4670
4671         static Gtk::Button *cancel_button;
4672         if (!scan_dlg) {
4673                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4674                 VBox* vbox = scan_dlg->get_vbox();
4675                 vbox->set_size_request(400,-1);
4676                 scan_dlg->set_title (_("Scanning for plugins"));
4677
4678                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4679                 cancel_button->set_name ("EditorGTKButton");
4680                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4681                 cancel_button->show();
4682
4683                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4684
4685                 scan_tbox = manage( new HBox() );
4686
4687                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4688                 scan_timeout_button->set_name ("EditorGTKButton");
4689                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4690                 scan_timeout_button->show();
4691
4692                 scan_pbar = manage(new ProgressBar());
4693                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4694                 scan_pbar->set_text(_("Scan Timeout"));
4695                 scan_pbar->show();
4696
4697                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4698                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4699
4700                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4701         }
4702
4703         assert(scan_dlg && scan_tbox && cancel_button);
4704
4705         if (type == X_("closeme")) {
4706                 scan_tbox->hide();
4707                 scan_dlg->hide();
4708         } else {
4709                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4710                 scan_dlg->show();
4711         }
4712         if (!can_cancel || !cancelled) {
4713                 scan_timeout_button->set_sensitive(false);
4714         }
4715         cancel_button->set_sensitive(can_cancel && !cancelled);
4716
4717         gui_idle_handler();
4718 }
4719
4720 void
4721 ARDOUR_UI::gui_idle_handler ()
4722 {
4723         int timeout = 30;
4724         /* due to idle calls, gtk_events_pending() may always return true */
4725         while (gtk_events_pending() && --timeout) {
4726                 gtk_main_iteration ();
4727         }
4728 }
4729
4730 void
4731 ARDOUR_UI::disk_underrun_handler ()
4732 {
4733         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4734
4735         if (!have_disk_speed_dialog_displayed) {
4736                 have_disk_speed_dialog_displayed = true;
4737                 MessageDialog* msg = new MessageDialog (
4738                         _main_window, string_compose (_("The disk system on your computer\n\
4739 was not able to keep up with %1.\n\
4740 \n\
4741 Specifically, it failed to read data from disk\n\
4742 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4743                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4744                 msg->show ();
4745         }
4746 }
4747
4748 void
4749 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4750 {
4751         have_disk_speed_dialog_displayed = false;
4752         delete msg;
4753 }
4754
4755 void
4756 ARDOUR_UI::session_dialog (std::string msg)
4757 {
4758         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4759
4760         MessageDialog* d;
4761
4762         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4763         d->show_all ();
4764         d->run ();
4765         delete d;
4766 }
4767
4768 int
4769 ARDOUR_UI::pending_state_dialog ()
4770 {
4771         HBox* hbox = manage (new HBox());
4772         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4773         ArdourDialog dialog (_("Crash Recovery"), true);
4774         Label  message (string_compose (_("\
4775 This session appears to have been in the\n\
4776 middle of recording when %1 or\n\
4777 the computer was shutdown.\n\
4778 \n\
4779 %1 can recover any captured audio for\n\
4780 you, or it can ignore it. Please decide\n\
4781 what you would like to do.\n"), PROGRAM_NAME));
4782         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4783         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4784         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4785         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4786         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
4787         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
4788         dialog.set_default_response (RESPONSE_ACCEPT);
4789         dialog.set_position (WIN_POS_CENTER);
4790         message.show();
4791         image->show();
4792         hbox->show();
4793
4794         switch (dialog.run ()) {
4795         case RESPONSE_ACCEPT:
4796                 return 1;
4797         default:
4798                 return 0;
4799         }
4800 }
4801
4802 int
4803 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4804 {
4805         HBox* hbox = new HBox();
4806         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4807         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4808         Label  message (string_compose (_("\
4809 This session was created with a sample rate of %1 Hz, but\n\
4810 %2 is currently running at %3 Hz.  If you load this session,\n\
4811 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4812
4813         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4814         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4815         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4816         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4817         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4818         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4819         dialog.set_default_response (RESPONSE_ACCEPT);
4820         dialog.set_position (WIN_POS_CENTER);
4821         message.show();
4822         image->show();
4823         hbox->show();
4824
4825         switch (dialog.run()) {
4826         case RESPONSE_ACCEPT:
4827                 return 0;
4828         default:
4829                 break;
4830         }
4831
4832         return 1;
4833 }
4834
4835 void
4836 ARDOUR_UI::sr_mismatch_message (framecnt_t desired, framecnt_t actual)
4837 {
4838         MessageDialog msg (string_compose (_("\
4839 This session was created with a sample rate of %1 Hz, but\n\
4840 %2 is currently running at %3 Hz.\n\
4841 Audio will be recorded and played at the wrong sample rate.\n\
4842 Re-Configure the Audio Engine in\n\
4843 Menu > Window > Audio/Midi Setup"),
4844                                 desired, PROGRAM_NAME, actual),
4845                         true,
4846                         Gtk::MESSAGE_WARNING);
4847         msg.run ();
4848 }
4849
4850 void
4851 ARDOUR_UI::use_config ()
4852 {
4853         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
4854         if (node) {
4855                 set_transport_controllable_state (*node);
4856         }
4857 }
4858
4859 void
4860 ARDOUR_UI::update_transport_clocks (framepos_t pos)
4861 {
4862         if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
4863                 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4864         } else {
4865                 primary_clock->set (pos);
4866         }
4867
4868         if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
4869                 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4870         } else {
4871                 secondary_clock->set (pos);
4872         }
4873
4874         if (big_clock_window) {
4875                 big_clock->set (pos);
4876         }
4877         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
4878 }
4879
4880 void
4881 ARDOUR_UI::step_edit_status_change (bool yn)
4882 {
4883         // XXX should really store pre-step edit status of things
4884         // we make insensitive
4885
4886         if (yn) {
4887                 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
4888                 rec_button.set_sensitive (false);
4889         } else {
4890                 rec_button.unset_active_state ();;
4891                 rec_button.set_sensitive (true);
4892         }
4893 }
4894
4895 void
4896 ARDOUR_UI::record_state_changed ()
4897 {
4898         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
4899
4900         if (!_session || !big_clock_window) {
4901                 /* why bother - the clock isn't visible */
4902                 return;
4903         }
4904
4905         if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
4906                 big_clock->set_active (true);
4907         } else {
4908                 big_clock->set_active (false);
4909         }
4910 }
4911
4912 bool
4913 ARDOUR_UI::first_idle ()
4914 {
4915         if (_session) {
4916                 _session->allow_auto_play (true);
4917         }
4918
4919         if (editor) {
4920                 editor->first_idle();
4921         }
4922
4923         Keyboard::set_can_save_keybindings (true);
4924         return false;
4925 }
4926
4927 void
4928 ARDOUR_UI::store_clock_modes ()
4929 {
4930         XMLNode* node = new XMLNode(X_("ClockModes"));
4931
4932         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
4933                 XMLNode* child = new XMLNode (X_("Clock"));
4934
4935                 child->add_property (X_("name"), (*x)->name());
4936                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
4937                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
4938
4939                 node->add_child_nocopy (*child);
4940         }
4941
4942         _session->add_extra_xml (*node);
4943         _session->set_dirty ();
4944 }
4945
4946 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
4947         : Controllable (name), ui (u), type(tp)
4948 {
4949
4950 }
4951
4952 void
4953 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
4954 {
4955         if (val < 0.5) {
4956                 /* do nothing: these are radio-style actions */
4957                 return;
4958         }
4959
4960         const char *action = 0;
4961
4962         switch (type) {
4963         case Roll:
4964                 action = X_("Roll");
4965                 break;
4966         case Stop:
4967                 action = X_("Stop");
4968                 break;
4969         case GotoStart:
4970                 action = X_("GotoStart");
4971                 break;
4972         case GotoEnd:
4973                 action = X_("GotoEnd");
4974                 break;
4975         case AutoLoop:
4976                 action = X_("Loop");
4977                 break;
4978         case PlaySelection:
4979                 action = X_("PlaySelection");
4980                 break;
4981         case RecordEnable:
4982                 action = X_("Record");
4983                 break;
4984         default:
4985                 break;
4986         }
4987
4988         if (action == 0) {
4989                 return;
4990         }
4991
4992         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
4993
4994         if (act) {
4995                 act->activate ();
4996         }
4997 }
4998
4999 double
5000 ARDOUR_UI::TransportControllable::get_value (void) const
5001 {
5002         float val = 0.0;
5003
5004         switch (type) {
5005         case Roll:
5006                 break;
5007         case Stop:
5008                 break;
5009         case GotoStart:
5010                 break;
5011         case GotoEnd:
5012                 break;
5013         case AutoLoop:
5014                 break;
5015         case PlaySelection:
5016                 break;
5017         case RecordEnable:
5018                 break;
5019         default:
5020                 break;
5021         }
5022
5023         return val;
5024 }
5025
5026 void
5027 ARDOUR_UI::setup_profile ()
5028 {
5029         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
5030                 Profile->set_small_screen ();
5031         }
5032
5033         if (g_getenv ("TRX")) {
5034                 Profile->set_trx ();
5035         }
5036
5037         if (g_getenv ("MIXBUS")) {
5038                 Profile->set_mixbus ();
5039         }
5040 }
5041
5042 int
5043 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
5044 {
5045         MissingFileDialog dialog (s, str, type);
5046
5047         dialog.show ();
5048         dialog.present ();
5049
5050         int result = dialog.run ();
5051         dialog.hide ();
5052
5053         switch (result) {
5054         case RESPONSE_OK:
5055                 break;
5056         default:
5057                 return 1; // quit entire session load
5058         }
5059
5060         result = dialog.get_action ();
5061
5062         return result;
5063 }
5064
5065 int
5066 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
5067 {
5068         AmbiguousFileDialog dialog (file, hits);
5069
5070         dialog.show ();
5071         dialog.present ();
5072
5073         dialog.run ();
5074
5075         return dialog.get_which ();
5076 }
5077
5078 /** Allocate our thread-local buffers */
5079 void
5080 ARDOUR_UI::get_process_buffers ()
5081 {
5082         _process_thread->get_buffers ();
5083 }
5084
5085 /** Drop our thread-local buffers */
5086 void
5087 ARDOUR_UI::drop_process_buffers ()
5088 {
5089         _process_thread->drop_buffers ();
5090 }
5091
5092 void
5093 ARDOUR_UI::feedback_detected ()
5094 {
5095         _feedback_exists = true;
5096 }
5097
5098 void
5099 ARDOUR_UI::successful_graph_sort ()
5100 {
5101         _feedback_exists = false;
5102 }
5103
5104 void
5105 ARDOUR_UI::midi_panic ()
5106 {
5107         if (_session) {
5108                 _session->midi_panic();
5109         }
5110 }
5111
5112 void
5113 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5114 {
5115         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5116         const char* end_big = "</span>";
5117         const char* start_mono = "<tt>";
5118         const char* end_mono = "</tt>";
5119
5120         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5121                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5122                                              "From now on, use the -2000 version with older versions of %3"),
5123                                            xml_path, backup_path, PROGRAM_NAME,
5124                                            start_big, end_big,
5125                                            start_mono, end_mono), true);
5126
5127         msg.run ();
5128 }
5129
5130
5131 void
5132 ARDOUR_UI::reset_peak_display ()
5133 {
5134         if (!_session || !_session->master_out() || !editor_meter) return;
5135         editor_meter->clear_meters();
5136         editor_meter_max_peak = -INFINITY;
5137         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5138 }
5139
5140 void
5141 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5142 {
5143         if (!_session || !_session->master_out()) return;
5144         if (group == _session->master_out()->route_group()) {
5145                 reset_peak_display ();
5146         }
5147 }
5148
5149 void
5150 ARDOUR_UI::reset_route_peak_display (Route* route)
5151 {
5152         if (!_session || !_session->master_out()) return;
5153         if (_session->master_out().get() == route) {
5154                 reset_peak_display ();
5155         }
5156 }
5157
5158 int
5159 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5160 {
5161         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5162         audio_midi_setup->set_position (WIN_POS_CENTER);
5163
5164         if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
5165                 audio_midi_setup->try_autostart ();
5166                 if (ARDOUR::AudioEngine::instance()->running()) {
5167                         return 0;
5168                 }
5169         }
5170
5171         while (true) {
5172                 int response = audio_midi_setup->run();
5173                 switch (response) {
5174                 case Gtk::RESPONSE_OK:
5175                         if (!AudioEngine::instance()->running()) {
5176                                 continue;
5177                         } else {
5178                                 return 0;
5179                         }
5180                         return 0;
5181                 default:
5182                         return -1;
5183                 }
5184         }
5185 }
5186
5187
5188 gint
5189 ARDOUR_UI::transport_numpad_timeout ()
5190 {
5191         _numpad_locate_happening = false;
5192         if (_numpad_timeout_connection.connected() )
5193                 _numpad_timeout_connection.disconnect();
5194         return 1;
5195 }
5196
5197 void
5198 ARDOUR_UI::transport_numpad_decimal ()
5199 {
5200         _numpad_timeout_connection.disconnect();
5201
5202         if (_numpad_locate_happening) {
5203                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5204                 _numpad_locate_happening = false;
5205         } else {
5206                 _pending_locate_num = 0;
5207                 _numpad_locate_happening = true;
5208                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5209         }
5210 }
5211
5212 void
5213 ARDOUR_UI::transport_numpad_event (int num)
5214 {
5215         if ( _numpad_locate_happening ) {
5216                 _pending_locate_num = _pending_locate_num*10 + num;
5217         } else {
5218                 switch (num) {
5219                         case 0:  toggle_roll(false, false);             break;
5220                         case 1:  transport_rewind(1);                           break;
5221                         case 2:  transport_forward(1);                          break;
5222                         case 3:  transport_record(true);                        break;
5223                         case 4:  toggle_session_auto_loop();            break;
5224                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5225                         case 6:  toggle_punch();                                        break;
5226                         case 7:  toggle_click();                                break;
5227                         case 8:  toggle_auto_return();                  break;
5228                         case 9:  toggle_follow_edits();         break;
5229                 }
5230         }
5231 }
5232
5233 void
5234 ARDOUR_UI::set_flat_buttons ()
5235 {
5236         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5237 }
5238
5239 void
5240 ARDOUR_UI::audioengine_became_silent ()
5241 {
5242         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5243                            true,
5244                            Gtk::MESSAGE_WARNING,
5245                            Gtk::BUTTONS_NONE,
5246                            true);
5247
5248         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5249
5250         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5251         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5252         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5253         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5254         Gtk::HBox pay_button_box;
5255         Gtk::HBox subscribe_button_box;
5256
5257         pay_button_box.pack_start (pay_button, true, false);
5258         subscribe_button_box.pack_start (subscribe_button, true, false);
5259
5260         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 */
5261
5262         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5263         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5264
5265         msg.get_vbox()->pack_start (pay_label);
5266         msg.get_vbox()->pack_start (pay_button_box);
5267         msg.get_vbox()->pack_start (subscribe_label);
5268         msg.get_vbox()->pack_start (subscribe_button_box);
5269
5270         msg.get_vbox()->show_all ();
5271
5272         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5273         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5274         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5275
5276         int r = msg.run ();
5277
5278         switch (r) {
5279         case Gtk::RESPONSE_YES:
5280                 AudioEngine::instance()->reset_silence_countdown ();
5281                 break;
5282
5283         case Gtk::RESPONSE_NO:
5284                 /* save and quit */
5285                 save_state_canfail ("");
5286                 exit (0);
5287                 break;
5288
5289         case Gtk::RESPONSE_CANCEL:
5290         default:
5291                 /* don't reset, save session and exit */
5292                 break;
5293         }
5294 }
5295
5296 void
5297 ARDOUR_UI::hide_application ()
5298 {
5299     Application::instance ()-> hide ();
5300 }
5301
5302 void
5303 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5304 {
5305         /* icons, titles, WM stuff */
5306
5307         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5308
5309         if (window_icons.empty()) {
5310                 Glib::RefPtr<Gdk::Pixbuf> icon;
5311                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px")) != 0) {
5312                         window_icons.push_back (icon);
5313                 }
5314                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px")) != 0) {
5315                         window_icons.push_back (icon);
5316                 }
5317                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px")) != 0) {
5318                         window_icons.push_back (icon);
5319                 }
5320                 if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px")) != 0) {
5321                         window_icons.push_back (icon);
5322                 }
5323         }
5324
5325         if (!window_icons.empty()) {
5326                 window.set_default_icon_list (window_icons);
5327         }
5328
5329         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5330
5331         if (!name.empty()) {
5332                 title += name;
5333         }
5334
5335         window.set_title (title.get_string());
5336         window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
5337
5338         window.set_flags (CAN_FOCUS);
5339         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5340
5341         /* This is a hack to ensure that GTK-accelerators continue to
5342          * work. Once we switch over to entirely native bindings, this will be
5343          * unnecessary and should be removed
5344          */
5345         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5346
5347         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5348         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5349         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5350         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5351 }
5352
5353 bool
5354 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5355 {
5356         Gtkmm2ext::Bindings* bindings = 0;
5357         Gtk::Window* window = 0;
5358
5359         /* until we get ardour bindings working, we are not handling key
5360          * releases yet.
5361          */
5362
5363         if (ev->type != GDK_KEY_PRESS) {
5364                 return false;
5365         }
5366
5367         if (event_window == &_main_window) {
5368
5369                 window = event_window;
5370
5371                 /* find current tab contents */
5372
5373                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5374
5375                 /* see if it uses the ardour binding system */
5376
5377                 if (w) {
5378                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5379                 }
5380
5381                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5382
5383         } else {
5384
5385                 window = event_window;
5386
5387                 /* see if window uses ardour binding system */
5388
5389                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5390         }
5391
5392         /* An empty binding set is treated as if it doesn't exist */
5393
5394         if (bindings && bindings->empty()) {
5395                 bindings = 0;
5396         }
5397
5398         return key_press_focus_accelerator_handler (*window, ev, bindings);
5399 }
5400
5401 static Gtkmm2ext::Bindings*
5402 get_bindings_from_widget_heirarchy (GtkWidget* w)
5403 {
5404         void* p = NULL;
5405
5406         while (w) {
5407                 if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) {
5408                         break;
5409                 }
5410                 w = gtk_widget_get_parent (w);
5411         }
5412
5413         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5414 }
5415
5416 bool
5417 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5418 {
5419         GtkWindow* win = window.gobj();
5420         GtkWidget* focus = gtk_window_get_focus (win);
5421         bool special_handling_of_unmodified_accelerators = false;
5422         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5423
5424         if (focus) {
5425
5426                 /* some widget has keyboard focus */
5427
5428                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5429
5430                         /* A particular kind of focusable widget currently has keyboard
5431                          * focus. All unmodified key events should go to that widget
5432                          * first and not be used as an accelerator by default
5433                          */
5434
5435                         special_handling_of_unmodified_accelerators = true;
5436
5437                 } else {
5438
5439                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus);
5440                         if (focus_bindings) {
5441                                 bindings = focus_bindings;
5442                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5443                         }
5444                 }
5445         }
5446
5447         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",
5448                                                           win,
5449                                                           ev->keyval,
5450                                                           show_gdk_event_state (ev->state),
5451                                                           special_handling_of_unmodified_accelerators,
5452                                                           Keyboard::some_magic_widget_has_focus(),
5453                                                           focus,
5454                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5455                                                           ((ev->state & mask) ? "yes" : "no"),
5456                                                           window.get_title()));
5457
5458         /* This exists to allow us to override the way GTK handles
5459            key events. The normal sequence is:
5460
5461            a) event is delivered to a GtkWindow
5462            b) accelerators/mnemonics are activated
5463            c) if (b) didn't handle the event, propagate to
5464                the focus widget and/or focus chain
5465
5466            The problem with this is that if the accelerators include
5467            keys without modifiers, such as the space bar or the
5468            letter "e", then pressing the key while typing into
5469            a text entry widget results in the accelerator being
5470            activated, instead of the desired letter appearing
5471            in the text entry.
5472
5473            There is no good way of fixing this, but this
5474            represents a compromise. The idea is that
5475            key events involving modifiers (not Shift)
5476            get routed into the activation pathway first, then
5477            get propagated to the focus widget if necessary.
5478
5479            If the key event doesn't involve modifiers,
5480            we deliver to the focus widget first, thus allowing
5481            it to get "normal text" without interference
5482            from acceleration.
5483
5484            Of course, this can also be problematic: if there
5485            is a widget with focus, then it will swallow
5486            all "normal text" accelerators.
5487         */
5488
5489
5490         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5491
5492                 /* no special handling or there are modifiers in effect: accelerate first */
5493
5494                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5495                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5496                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5497
5498                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5499                 KeyboardKey k (ev->state, ev->keyval);
5500
5501                 if (bindings) {
5502
5503                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5504
5505                         if (bindings->activate (k, Bindings::Press)) {
5506                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5507                                 return true;
5508                         }
5509                 }
5510
5511                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5512
5513                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5514                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5515                         return true;
5516                 }
5517
5518                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5519
5520                 if (gtk_window_propagate_key_event (win, ev)) {
5521                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5522                         return true;
5523                 }
5524
5525         } else {
5526
5527                 /* no modifiers, propagate first */
5528
5529                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5530
5531                 if (gtk_window_propagate_key_event (win, ev)) {
5532                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5533                         return true;
5534                 }
5535
5536                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5537                 KeyboardKey k (ev->state, ev->keyval);
5538
5539                 if (bindings) {
5540
5541                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5542
5543
5544                         if (bindings->activate (k, Bindings::Press)) {
5545                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5546                                 return true;
5547                         }
5548
5549                 }
5550
5551                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5552
5553                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5554                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5555                         return true;
5556                 }
5557         }
5558
5559         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5560         return true;
5561 }
5562
5563 void
5564 ARDOUR_UI::load_bindings ()
5565 {
5566         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5567                 error << _("Global keybindings are missing") << endmsg;
5568         }
5569 }
5570
5571 void
5572 ARDOUR_UI::cancel_solo ()
5573 {
5574         if (_session) {
5575                 if (_session) {
5576                         _session->set_controls (route_list_to_control_list (_session->get_routes(), &Route::solo_control), 0.0, Controllable::NoGroup);
5577                 }
5578                 _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window
5579         }
5580 }