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