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