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