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