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