remove debug output
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2013 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #include "gtk2ardour-version.h"
23 #endif
24
25 #include <algorithm>
26 #include <cmath>
27 #include <iostream>
28 #include <cerrno>
29
30 #include <stdarg.h>
31
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
34 #endif
35
36 #include <stdint.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 #include <unistd.h>
40 #include <time.h>
41
42 #include <glib.h>
43 #include "pbd/gstdio_compat.h"
44
45 #include <gtkmm/messagedialog.h>
46 #include <gtkmm/accelmap.h>
47
48 #include "pbd/error.h"
49 #include "pbd/basename.h"
50 #include "pbd/compose.h"
51 #include "pbd/failed_constructor.h"
52 #include "pbd/enumwriter.h"
53 #include "pbd/memento_command.h"
54 #include "pbd/openuri.h"
55 #include "pbd/stl_delete.h"
56 #include "pbd/file_utils.h"
57 #include "pbd/localtime_r.h"
58 #include "pbd/pthread_utils.h"
59 #include "pbd/replace_all.h"
60 #include "pbd/xml++.h"
61
62 #include "gtkmm2ext/application.h"
63 #include "gtkmm2ext/bindings.h"
64 #include "gtkmm2ext/gtk_ui.h"
65 #include "gtkmm2ext/utils.h"
66 #include "gtkmm2ext/click_box.h"
67 #include "gtkmm2ext/fastmeter.h"
68 #include "gtkmm2ext/popup.h"
69 #include "gtkmm2ext/window_title.h"
70
71 #include "ardour/ardour.h"
72 #include "ardour/audio_backend.h"
73 #include "ardour/audioengine.h"
74 #include "ardour/audiofilesource.h"
75 #include "ardour/automation_watch.h"
76 #include "ardour/diskstream.h"
77 #include "ardour/filename_extensions.h"
78 #include "ardour/filesystem_paths.h"
79 #include "ardour/ltc_file_reader.h"
80 #include "ardour/port.h"
81 #include "ardour/plugin_manager.h"
82 #include "ardour/process_thread.h"
83 #include "ardour/profile.h"
84 #include "ardour/recent_sessions.h"
85 #include "ardour/session_directory.h"
86 #include "ardour/session_route.h"
87 #include "ardour/session_state_utils.h"
88 #include "ardour/session_utils.h"
89 #include "ardour/source_factory.h"
90 #include "ardour/slave.h"
91 #include "ardour/system_exec.h"
92
93 #ifdef WINDOWS_VST_SUPPORT
94 #include <fst.h>
95 #endif
96 #ifdef AUDIOUNIT_SUPPORT
97 #include "ardour/audio_unit.h"
98 #endif
99
100 #include "timecode/time.h"
101
102 typedef uint64_t microseconds_t;
103
104 #include "about.h"
105 #include "editing.h"
106 #include "actions.h"
107 #include "add_route_dialog.h"
108 #include "ambiguous_file_dialog.h"
109 #include "ardour_ui.h"
110 #include "audio_clock.h"
111 #include "audio_region_view.h"
112 #include "big_clock_window.h"
113 #include "bundle_manager.h"
114 #include "duplicate_routes_dialog.h"
115 #include "engine_dialog.h"
116 #include "export_video_dialog.h"
117 #include "export_video_infobox.h"
118 #include "gain_meter.h"
119 #include "global_port_matrix.h"
120 #include "gui_object.h"
121 #include "gui_thread.h"
122 #include "keyboard.h"
123 #include "keyeditor.h"
124 #include "location_ui.h"
125 #include "main_clock.h"
126 #include "missing_file_dialog.h"
127 #include "missing_plugin_dialog.h"
128 #include "mixer_ui.h"
129 #include "meterbridge.h"
130 #include "mouse_cursors.h"
131 #include "nsm.h"
132 #include "opts.h"
133 #include "pingback.h"
134 #include "processor_box.h"
135 #include "prompter.h"
136 #include "public_editor.h"
137 #include "rc_option_editor.h"
138 #include "route_time_axis.h"
139 #include "route_params_ui.h"
140 #include "save_as_dialog.h"
141 #include "session_dialog.h"
142 #include "session_metadata_dialog.h"
143 #include "session_option_editor.h"
144 #include "shuttle_control.h"
145 #include "speaker_dialog.h"
146 #include "splash.h"
147 #include "startup.h"
148 #include "theme_manager.h"
149 #include "time_axis_view_item.h"
150 #include "timers.h"
151 #include "utils.h"
152 #include "video_server_dialog.h"
153 #include "add_video_dialog.h"
154 #include "transcode_video_dialog.h"
155
156 #include "i18n.h"
157
158 using namespace ARDOUR;
159 using namespace ARDOUR_UI_UTILS;
160 using namespace PBD;
161 using namespace Gtkmm2ext;
162 using namespace Gtk;
163 using namespace std;
164 using namespace Editing;
165
166 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
167
168 sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
169 sigc::signal<void>      ARDOUR_UI::CloseAllDialogs;
170
171 static bool
172 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
173 {
174         MessageDialog msg (string_compose (_("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
175                                              "Would you like these files to be copied and used for %1 %2.x?\n\n"
176                                              "(This will require you to restart %1.)"),
177                                            PROGRAM_NAME, PROGRAM_VERSION, version),
178                            false, /* no markup */
179                            Gtk::MESSAGE_INFO,
180                            Gtk::BUTTONS_YES_NO,
181                            true /* modal, though it hardly matters since it is the only window */
182                 );
183
184         msg.set_default_response (Gtk::RESPONSE_YES);
185         msg.show_all ();
186
187         return (msg.run() == Gtk::RESPONSE_YES);
188 }
189
190 static void
191 libxml_generic_error_func (void* /* parsing_context*/,
192                    const char* msg,
193                    ...)
194 {
195         va_list ap;
196         char buf[2048];
197
198         va_start (ap, msg);
199         vsnprintf (buf, sizeof (buf), msg, ap);
200         error << buf << endmsg;
201         va_end (ap);
202 }
203
204 static void
205 libxml_structured_error_func (void* /* parsing_context*/,
206                               xmlErrorPtr err)
207 {
208         string msg;
209
210         if (err->message)
211                 msg = err->message;
212
213         replace_all (msg, "\n", "");
214
215         if (err->file && err->line) {
216                 error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
217
218                 if (err->int2) {
219                         error << ':' << err->int2;
220                 }
221         }
222         error << endmsg;
223 }
224
225
226 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
227
228         : Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
229         , session_loaded (false)
230         , gui_object_state (new GUIObjectState)
231         , primary_clock   (new MainClock (X_("primary"),   X_("transport"), true ))
232         , secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
233         , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
234         , video_timeline(0)
235         , ignore_dual_punch (false)
236         , editor (0)
237         , mixer (0)
238         , nsm (0)
239         , _was_dirty (false)
240         , _mixer_on_top (false)
241         , _initial_verbose_plugin_scan (false)
242         , first_time_engine_run (true)
243         , roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
244         , stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
245         , goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
246         , goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd))
247         , auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
248         , play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
249         , rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
250         , auto_return_button (ArdourButton::led_default_elements)
251         , follow_edits_button (ArdourButton::led_default_elements)
252         , auto_input_button (ArdourButton::led_default_elements)
253         , auditioning_alert_button (_("Audition"))
254         , solo_alert_button (_("Solo"))
255         , feedback_alert_button (_("Feedback"))
256         , error_alert_button ( ArdourButton::just_led_default_elements )
257         , editor_meter(0)
258         , editor_meter_peak_display()
259         , _numpad_locate_happening (false)
260         , _session_is_new (false)
261         , last_key_press_time (0)
262         , save_as_dialog (0)
263         , meterbridge (0)
264         , speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
265         , key_editor (X_("key-editor"), _("Key Bindings"))
266         , rc_option_editor (X_("rc-options-editor"), _("Preferences"))
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 if (!_session->config.get_external_sync()) {
2114                         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
2115                                 _session->request_play_range (&editor->get_selection().time, true);
2116                                 _session->set_requested_return_frame( editor->get_selection().time.front().start );  //force an auto-return here
2117                         }
2118                         _session->request_transport_speed (1.0f);
2119                 }
2120         }
2121 }
2122
2123 void
2124 ARDOUR_UI::toggle_session_auto_loop ()
2125 {
2126         if (!_session) {
2127                 return;
2128         }
2129
2130         Location * looploc = _session->locations()->auto_loop_location();
2131
2132         if (!looploc) {
2133                 return;
2134         }
2135
2136         if (_session->get_play_loop()) {
2137
2138                 /* looping enabled, our job is to disable it */
2139
2140                 _session->request_play_loop (false);
2141
2142         } else {
2143
2144                 /* looping not enabled, our job is to enable it.
2145
2146                    loop-is-NOT-mode: this action always starts the transport rolling.
2147                    loop-IS-mode:     this action simply sets the loop play mechanism, but
2148                                         does not start transport.
2149                 */
2150                 if (Config->get_loop_is_mode()) {
2151                         _session->request_play_loop (true, false);
2152                 } else {
2153                         _session->request_play_loop (true, true);
2154                 }
2155         }
2156
2157         //show the loop markers
2158         looploc->set_hidden (false, this);
2159 }
2160
2161 void
2162 ARDOUR_UI::transport_play_selection ()
2163 {
2164         if (!_session) {
2165                 return;
2166         }
2167
2168         editor->play_selection ();
2169 }
2170
2171 void
2172 ARDOUR_UI::transport_play_preroll ()
2173 {
2174         if (!_session) {
2175                 return;
2176         }
2177         editor->play_with_preroll ();
2178 }
2179
2180 void
2181 ARDOUR_UI::transport_rewind (int option)
2182 {
2183         float current_transport_speed;
2184
2185         if (_session) {
2186                 current_transport_speed = _session->transport_speed();
2187
2188                 if (current_transport_speed >= 0.0f) {
2189                         switch (option) {
2190                         case 0:
2191                                 _session->request_transport_speed (-1.0f);
2192                                 break;
2193                         case 1:
2194                                 _session->request_transport_speed (-4.0f);
2195                                 break;
2196                         case -1:
2197                                 _session->request_transport_speed (-0.5f);
2198                                 break;
2199                         }
2200                 } else {
2201                         /* speed up */
2202                         _session->request_transport_speed (current_transport_speed * 1.5f);
2203                 }
2204         }
2205 }
2206
2207 void
2208 ARDOUR_UI::transport_forward (int option)
2209 {
2210         if (!_session) {
2211                 return;
2212         }
2213
2214         float current_transport_speed = _session->transport_speed();
2215
2216         if (current_transport_speed <= 0.0f) {
2217                 switch (option) {
2218                 case 0:
2219                         _session->request_transport_speed (1.0f);
2220                         break;
2221                 case 1:
2222                         _session->request_transport_speed (4.0f);
2223                         break;
2224                 case -1:
2225                         _session->request_transport_speed (0.5f);
2226                         break;
2227                 }
2228         } else {
2229                 /* speed up */
2230                 _session->request_transport_speed (current_transport_speed * 1.5f);
2231         }
2232 }
2233
2234 void
2235 ARDOUR_UI::toggle_record_enable (uint32_t rid)
2236 {
2237         if (!_session) {
2238                 return;
2239         }
2240
2241         boost::shared_ptr<Route> r;
2242
2243         if ((r = _session->route_by_remote_id (rid)) != 0) {
2244
2245                 Track* t;
2246
2247                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
2248                         t->set_record_enabled (!t->record_enabled(), this);
2249                 }
2250         }
2251 }
2252
2253 void
2254 ARDOUR_UI::map_transport_state ()
2255 {
2256         if (!_session) {
2257                 auto_loop_button.unset_active_state ();
2258                 play_selection_button.unset_active_state ();
2259                 roll_button.unset_active_state ();
2260                 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2261                 return;
2262         }
2263
2264         shuttle_box->map_transport_state ();
2265
2266         float sp = _session->transport_speed();
2267
2268         if (sp != 0.0f) {
2269
2270                 /* we're rolling */
2271
2272                 if (_session->get_play_range()) {
2273
2274                         play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2275                         roll_button.unset_active_state ();
2276                         auto_loop_button.unset_active_state ();
2277
2278                 } else if (_session->get_play_loop ()) {
2279
2280                         auto_loop_button.set_active (true);
2281                         play_selection_button.set_active (false);
2282                         if (Config->get_loop_is_mode()) {
2283                                 roll_button.set_active (true);
2284                         } else {
2285                                 roll_button.set_active (false);
2286                         }
2287
2288                 } else {
2289
2290                         roll_button.set_active (true);
2291                         play_selection_button.set_active (false);
2292                         auto_loop_button.set_active (false);
2293                 }
2294
2295                 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2296                         /* light up both roll and play-selection if they are joined */
2297                         roll_button.set_active (true);
2298                         play_selection_button.set_active (true);
2299                 }
2300
2301                 stop_button.set_active (false);
2302
2303         } else {
2304
2305                 stop_button.set_active (true);
2306                 roll_button.set_active (false);
2307                 play_selection_button.set_active (false);
2308                 if (Config->get_loop_is_mode ()) {
2309                         auto_loop_button.set_active (_session->get_play_loop());
2310                 } else {
2311                         auto_loop_button.set_active (false);
2312                 }
2313                 update_disk_space ();
2314         }
2315 }
2316
2317 void
2318 ARDOUR_UI::blink_handler (bool blink_on)
2319 {
2320         transport_rec_enable_blink (blink_on);
2321         solo_blink (blink_on);
2322         sync_blink (blink_on);
2323         audition_blink (blink_on);
2324         feedback_blink (blink_on);
2325         error_blink (blink_on);
2326 }
2327
2328 void
2329 ARDOUR_UI::update_clocks ()
2330 {
2331         if (!_session) return;
2332
2333         if (editor && !editor->dragging_playhead()) {
2334                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2335         }
2336 }
2337
2338 void
2339 ARDOUR_UI::start_clocking ()
2340 {
2341         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2342                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2343         } else {
2344                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2345         }
2346 }
2347
2348 void
2349 ARDOUR_UI::stop_clocking ()
2350 {
2351         clock_signal_connection.disconnect ();
2352 }
2353
2354 bool
2355 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2356 {
2357         char buf[256];
2358
2359         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2360
2361         label->set_text (buf);
2362         bar->set_fraction (fraction);
2363
2364         /* process events, redraws, etc. */
2365
2366         while (gtk_events_pending()) {
2367                 gtk_main_iteration ();
2368         }
2369
2370         return true; /* continue with save-as */
2371 }
2372
2373 void
2374 ARDOUR_UI::save_session_as ()
2375 {
2376         if (!_session) {
2377                 return;
2378         }
2379
2380         if (!save_as_dialog) {
2381                 save_as_dialog = new SaveAsDialog;
2382         }
2383
2384         save_as_dialog->set_name (_session->name());
2385
2386         int response = save_as_dialog->run ();
2387
2388         save_as_dialog->hide ();
2389
2390         switch (response) {
2391         case Gtk::RESPONSE_OK:
2392                 break;
2393         default:
2394                 return;
2395         }
2396
2397
2398         Session::SaveAs sa;
2399
2400         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2401         sa.new_name = save_as_dialog->new_name ();
2402         sa.switch_to = save_as_dialog->switch_to();
2403         sa.copy_media = save_as_dialog->copy_media();
2404         sa.copy_external = save_as_dialog->copy_external();
2405         sa.include_media = save_as_dialog->include_media ();
2406
2407         /* Only bother with a progress dialog if we're going to copy
2408            media into the save-as target. Without that choice, this
2409            will be very fast because we're only talking about a few kB's to
2410            perhaps a couple of MB's of data.
2411         */
2412
2413         ArdourDialog progress_dialog (_("Save As"), true);
2414
2415         if (sa.include_media && sa.copy_media) {
2416
2417                 Gtk::Label label;
2418                 Gtk::ProgressBar progress_bar;
2419
2420                 progress_dialog.get_vbox()->pack_start (label);
2421                 progress_dialog.get_vbox()->pack_start (progress_bar);
2422                 label.show ();
2423                 progress_bar.show ();
2424
2425                 /* this signal will be emitted from within this, the calling thread,
2426                  * after every file is copied. It provides information on percentage
2427                  * complete (in terms of total data to copy), the number of files
2428                  * copied so far, and the total number to copy.
2429                  */
2430
2431                 ScopedConnection c;
2432
2433                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
2434
2435                 progress_dialog.show_all ();
2436                 progress_dialog.present ();
2437         }
2438
2439         if (_session->save_as (sa)) {
2440                 /* ERROR MESSAGE */
2441                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2442                 msg.run ();
2443         }
2444
2445         if (!sa.include_media) {
2446                 unload_session (false);
2447                 load_session (sa.final_session_folder_name, sa.new_name);
2448         }
2449 }
2450
2451 bool
2452 ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
2453 {
2454         string snapname;
2455
2456         prompter.get_result (snapname);
2457
2458         bool do_save = (snapname.length() != 0);
2459
2460         if (do_save) {
2461                 char illegal = Session::session_name_is_legal(snapname);
2462                 if (illegal) {
2463                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2464                                              "snapshot names may not contain a '%1' character"), illegal));
2465                         msg.run ();
2466                         return false;
2467                 }
2468         }
2469
2470         vector<std::string> p;
2471         get_state_files_in_directory (_session->session_directory().root_path(), p);
2472         vector<string> n = get_file_names_no_extension (p);
2473
2474         if (find (n.begin(), n.end(), snapname) != n.end()) {
2475
2476                 do_save = overwrite_file_dialog (prompter,
2477                                                  _("Confirm Snapshot Overwrite"),
2478                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2479         }
2480
2481         if (do_save) {
2482                 save_state (snapname, switch_to_it);
2483         }
2484         else {
2485                 return false;
2486         }
2487
2488         return true;
2489 }
2490
2491
2492 /** Ask the user for the name of a new snapshot and then take it.
2493  */
2494
2495 void
2496 ARDOUR_UI::snapshot_session (bool switch_to_it)
2497 {
2498         ArdourPrompter prompter (true);
2499
2500         prompter.set_name ("Prompter");
2501         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2502         if (switch_to_it) {
2503                 prompter.set_title (_("Save as..."));
2504                 prompter.set_prompt (_("New session name"));
2505         } else {
2506                 prompter.set_title (_("Take Snapshot"));
2507                 prompter.set_prompt (_("Name of new snapshot"));
2508         }
2509
2510         if (switch_to_it) {
2511                 prompter.set_initial_text (_session->snap_name());
2512         } else {
2513                 char timebuf[128];
2514                 time_t n;
2515                 struct tm local_time;
2516
2517                 time (&n);
2518                 localtime_r (&n, &local_time);
2519                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2520                 prompter.set_initial_text (timebuf);
2521         }
2522
2523         bool finished = false;
2524         while (!finished) {
2525                 switch (prompter.run()) {
2526                 case RESPONSE_ACCEPT:
2527                 {
2528                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2529                         break;
2530                 }
2531
2532                 default:
2533                         finished = true;
2534                         break;
2535                 }
2536         }
2537 }
2538
2539 /** Ask the user for a new session name and then rename the session to it.
2540  */
2541
2542 void
2543 ARDOUR_UI::rename_session ()
2544 {
2545         if (!_session) {
2546                 return;
2547         }
2548
2549         ArdourPrompter prompter (true);
2550         string name;
2551
2552         prompter.set_name ("Prompter");
2553         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2554         prompter.set_title (_("Rename Session"));
2555         prompter.set_prompt (_("New session name"));
2556
2557   again:
2558         switch (prompter.run()) {
2559         case RESPONSE_ACCEPT:
2560         {
2561                 prompter.get_result (name);
2562
2563                 bool do_rename = (name.length() != 0);
2564
2565                 if (do_rename) {
2566                         char illegal = Session::session_name_is_legal (name);
2567
2568                         if (illegal) {
2569                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2570                                                                      "session names may not contain a '%1' character"), illegal));
2571                                 msg.run ();
2572                                 goto again;
2573                         }
2574
2575                         switch (_session->rename (name)) {
2576                         case -1: {
2577                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2578                                 msg.set_position (WIN_POS_MOUSE);
2579                                 msg.run ();
2580                                 goto again;
2581                                 break;
2582                         }
2583                         case 0:
2584                                 break;
2585                         default: {
2586                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2587                                 msg.set_position (WIN_POS_MOUSE);
2588                                 msg.run ();
2589                                 break;
2590                         }
2591                         }
2592                 }
2593
2594                 break;
2595         }
2596
2597         default:
2598                 break;
2599         }
2600 }
2601
2602 void
2603 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2604 {
2605         if (!_session || _session->deletion_in_progress()) {
2606                 return;
2607         }
2608
2609         XMLNode* node = new XMLNode (X_("UI"));
2610
2611         WM::Manager::instance().add_state (*node);
2612
2613         node->add_child_nocopy (gui_object_state->get_state());
2614
2615         _session->add_extra_xml (*node);
2616
2617         if (export_video_dialog) {
2618                 _session->add_extra_xml (export_video_dialog->get_state());
2619         }
2620
2621         save_state_canfail (name, switch_to_it);
2622 }
2623
2624 int
2625 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2626 {
2627         if (_session) {
2628                 int ret;
2629
2630                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2631                         return ret;
2632                 }
2633         }
2634
2635         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2636         return 0;
2637 }
2638
2639 void
2640 ARDOUR_UI::primary_clock_value_changed ()
2641 {
2642         if (_session) {
2643                 _session->request_locate (primary_clock->current_time ());
2644         }
2645 }
2646
2647 void
2648 ARDOUR_UI::big_clock_value_changed ()
2649 {
2650         if (_session) {
2651                 _session->request_locate (big_clock->current_time ());
2652         }
2653 }
2654
2655 void
2656 ARDOUR_UI::secondary_clock_value_changed ()
2657 {
2658         if (_session) {
2659                 _session->request_locate (secondary_clock->current_time ());
2660         }
2661 }
2662
2663 void
2664 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2665 {
2666         if (_session == 0) {
2667                 return;
2668         }
2669
2670         if (_session->step_editing()) {
2671                 return;
2672         }
2673
2674         Session::RecordState const r = _session->record_status ();
2675         bool const h = _session->have_rec_enabled_track ();
2676
2677         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2678                 if (onoff) {
2679                         rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2680                 } else {
2681                         rec_button.set_active_state (Gtkmm2ext::Off);
2682                 }
2683         } else if (r == Session::Recording && h) {
2684                 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2685         } else {
2686                 rec_button.unset_active_state ();
2687         }
2688 }
2689
2690 bool
2691 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2692 {
2693         string name;
2694
2695         prompter.get_result (name);
2696
2697         if (name.length()) {
2698                 int failed = _session->save_template (name);
2699
2700                 if (failed == -2) { /* file already exists. */
2701                         bool overwrite = overwrite_file_dialog (prompter,
2702                                                                 _("Confirm Template Overwrite"),
2703                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
2704
2705                         if (overwrite) {
2706                                 _session->save_template (name, true);
2707                         }
2708                         else {
2709                                 return false;
2710                         }
2711                 }
2712         }
2713
2714         return true;
2715 }
2716
2717 void
2718 ARDOUR_UI::save_template ()
2719 {
2720         ArdourPrompter prompter (true);
2721
2722         if (!check_audioengine(*editor)) {
2723                 return;
2724         }
2725
2726         prompter.set_name (X_("Prompter"));
2727         prompter.set_title (_("Save Template"));
2728         prompter.set_prompt (_("Name for template:"));
2729         prompter.set_initial_text(_session->name() + _("-template"));
2730         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2731
2732         bool finished = false;
2733         while (!finished) {
2734                 switch (prompter.run()) {
2735                 case RESPONSE_ACCEPT:
2736                         finished = process_save_template_prompter (prompter);
2737                         break;
2738
2739                 default:
2740                         finished = true;
2741                         break;
2742                 }
2743         }
2744 }
2745
2746 void
2747 ARDOUR_UI::edit_metadata ()
2748 {
2749         SessionMetadataEditor dialog;
2750         dialog.set_session (_session);
2751         dialog.grab_focus ();
2752         dialog.run ();
2753 }
2754
2755 void
2756 ARDOUR_UI::import_metadata ()
2757 {
2758         SessionMetadataImporter dialog;
2759         dialog.set_session (_session);
2760         dialog.run ();
2761 }
2762
2763 bool
2764 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2765 {
2766         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2767
2768         MessageDialog msg (str,
2769                            false,
2770                            Gtk::MESSAGE_WARNING,
2771                            Gtk::BUTTONS_YES_NO,
2772                            true);
2773
2774
2775         msg.set_name (X_("OpenExistingDialog"));
2776         msg.set_title (_("Open Existing Session"));
2777         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2778         msg.set_position (Gtk::WIN_POS_CENTER);
2779         pop_back_splash (msg);
2780
2781         switch (msg.run()) {
2782         case RESPONSE_YES:
2783                 return true;
2784                 break;
2785         }
2786         return false;
2787 }
2788
2789 int
2790 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
2791 {
2792         BusProfile bus_profile;
2793
2794         if (nsm || Profile->get_sae()) {
2795
2796                 bus_profile.master_out_channels = 2;
2797                 bus_profile.input_ac = AutoConnectPhysical;
2798                 bus_profile.output_ac = AutoConnectMaster;
2799                 bus_profile.requested_physical_in = 0; // use all available
2800                 bus_profile.requested_physical_out = 0; // use all available
2801
2802         } else {
2803
2804                 /* get settings from advanced section of NSD */
2805
2806                 if (sd.create_master_bus()) {
2807                         bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
2808                 } else {
2809                         bus_profile.master_out_channels = 0;
2810                 }
2811
2812                 if (sd.connect_inputs()) {
2813                         bus_profile.input_ac = AutoConnectPhysical;
2814                 } else {
2815                         bus_profile.input_ac = AutoConnectOption (0);
2816                 }
2817
2818                 bus_profile.output_ac = AutoConnectOption (0);
2819
2820                 if (sd.connect_outputs ()) {
2821                         if (sd.connect_outs_to_master()) {
2822                                 bus_profile.output_ac = AutoConnectMaster;
2823                         } else if (sd.connect_outs_to_physical()) {
2824                                 bus_profile.output_ac = AutoConnectPhysical;
2825                         }
2826                 }
2827
2828                 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
2829                 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
2830         }
2831
2832         if (build_session (session_path, session_name, bus_profile)) {
2833                 return -1;
2834         }
2835
2836         return 0;
2837 }
2838
2839 void
2840 ARDOUR_UI::load_from_application_api (const std::string& path)
2841 {
2842         ARDOUR_COMMAND_LINE::session_name = path;
2843         /* Cancel SessionDialog if it's visible to make OSX delegates work.
2844          *
2845          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
2846          * race-condition:
2847          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
2848          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
2849          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
2850          *    -> SessionDialog is not displayed
2851          */
2852
2853         if (_session_dialog) {
2854                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
2855                 std::string session_path = path;
2856                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
2857                         session_path = Glib::path_get_dirname (session_path);
2858                 }
2859                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
2860                 _session_dialog->set_provided_session (session_name, session_path);
2861                 _session_dialog->response (RESPONSE_NONE);
2862                 _session_dialog->hide();
2863                 return;
2864         }
2865
2866         int rv;
2867         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2868                 /* /path/to/foo => /path/to/foo, foo */
2869                 rv = load_session (path, basename_nosuffix (path));
2870         } else {
2871                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2872                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2873         }
2874
2875         // if load_session fails -> pop up SessionDialog.
2876         if (rv) {
2877                 ARDOUR_COMMAND_LINE::session_name = "";
2878
2879                 if (get_session_parameters (true, false)) {
2880                         exit (1);
2881                 }
2882
2883                 goto_editor_window ();
2884         }
2885 }
2886
2887 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2888 int
2889 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2890 {
2891         string session_name;
2892         string session_path;
2893         string template_name;
2894         int ret = -1;
2895         bool likely_new = false;
2896         bool cancel_not_quit;
2897
2898         /* deal with any existing DIRTY session now, rather than later. don't
2899          * treat a non-dirty session this way, so that it stays visible
2900          * as we bring up the new session dialog.
2901          */
2902
2903         if (_session && ARDOUR_UI::instance()->video_timeline) {
2904                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
2905         }
2906
2907         /* if there is already a session, relabel the button
2908            on the SessionDialog so that we don't Quit directly
2909         */
2910         cancel_not_quit = (_session != 0);
2911
2912         if (_session && _session->dirty()) {
2913                 if (unload_session (false)) {
2914                         /* unload cancelled by user */
2915                         return 0;
2916                 }
2917                 ARDOUR_COMMAND_LINE::session_name = "";
2918         }
2919
2920         if (!load_template.empty()) {
2921                 should_be_new = true;
2922                 template_name = load_template;
2923         }
2924
2925         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
2926         session_path = ARDOUR_COMMAND_LINE::session_name;
2927
2928         if (!session_path.empty()) {
2929                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
2930                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
2931                                 /* session/snapshot file, change path to be dir */
2932                                 session_path = Glib::path_get_dirname (session_path);
2933                         }
2934                 }
2935         }
2936
2937         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
2938
2939         _session_dialog = &session_dialog;
2940         while (ret != 0) {
2941
2942                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
2943
2944                         /* if they named a specific statefile, use it, otherwise they are
2945                            just giving a session folder, and we want to use it as is
2946                            to find the session.
2947                         */
2948
2949                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
2950
2951                         if (suffix != string::npos) {
2952                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2953                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
2954                                 session_name = Glib::path_get_basename (session_name);
2955                         } else {
2956                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2957                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2958                         }
2959                 } else {
2960                         session_path = "";
2961                         session_name = "";
2962                         session_dialog.clear_given ();
2963                 }
2964
2965                 if (should_be_new || session_name.empty()) {
2966                         /* need the dialog to get info from user */
2967
2968                         cerr << "run dialog\n";
2969
2970                         switch (session_dialog.run()) {
2971                         case RESPONSE_ACCEPT:
2972                                 break;
2973                         case RESPONSE_NONE:
2974                                 /* this is used for async * app->ShouldLoad(). */
2975                                 continue; // while loop
2976                                 break;
2977                         default:
2978                                 if (quit_on_cancel) {
2979                                         // JE - Currently (July 2014) this section can only get reached if the
2980                                         // user quits from the main 'Session Setup' dialog (i.e. reaching this
2981                                         // point does NOT indicate an abnormal termination). Therefore, let's
2982                                         // behave gracefully (i.e. let's do some cleanup) before we call exit()
2983                                         ARDOUR::cleanup ();
2984                                         pthread_cancel_all ();
2985
2986                                         exit (1);
2987                                 } else {
2988                                         return ret;
2989                                 }
2990                         }
2991
2992                         session_dialog.hide ();
2993                 }
2994
2995                 /* if we run the startup dialog again, offer more than just "new session" */
2996
2997                 should_be_new = false;
2998
2999                 session_name = session_dialog.session_name (likely_new);
3000                 session_path = session_dialog.session_folder ();
3001
3002                 if (nsm) {
3003                         likely_new = true;
3004                 }
3005
3006                 string::size_type suffix = session_name.find (statefile_suffix);
3007
3008                 if (suffix != string::npos) {
3009                         session_name = session_name.substr (0, suffix);
3010                 }
3011
3012                 /* this shouldn't happen, but we catch it just in case it does */
3013
3014                 if (session_name.empty()) {
3015                         continue;
3016                 }
3017
3018                 if (session_dialog.use_session_template()) {
3019                         template_name = session_dialog.session_template_name();
3020                         _session_is_new = true;
3021                 }
3022
3023                 if (session_name[0] == G_DIR_SEPARATOR ||
3024 #ifdef PLATFORM_WINDOWS
3025                     (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3026 #else
3027                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3028                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3029 #endif
3030                          )
3031                 {
3032
3033                         /* absolute path or cwd-relative path specified for session name: infer session folder
3034                            from what was given.
3035                         */
3036
3037                         session_path = Glib::path_get_dirname (session_name);
3038                         session_name = Glib::path_get_basename (session_name);
3039
3040                 } else {
3041
3042                         session_path = session_dialog.session_folder();
3043
3044                         char illegal = Session::session_name_is_legal (session_name);
3045
3046                         if (illegal) {
3047                                 MessageDialog msg (session_dialog,
3048                                                    string_compose (_("To ensure compatibility with various systems\n"
3049                                                                      "session names may not contain a '%1' character"),
3050                                                                    illegal));
3051                                 msg.run ();
3052                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3053                                 continue;
3054                         }
3055                 }
3056
3057                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3058
3059
3060                         if (likely_new && !nsm) {
3061
3062                                 std::string existing = Glib::build_filename (session_path, session_name);
3063
3064                                 if (!ask_about_loading_existing_session (existing)) {
3065                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3066                                         continue;
3067                                 }
3068                         }
3069
3070                         _session_is_new = false;
3071
3072                 } else {
3073
3074                         if (!likely_new) {
3075                                 pop_back_splash (session_dialog);
3076                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3077                                 msg.run ();
3078                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3079                                 continue;
3080                         }
3081
3082                         char illegal = Session::session_name_is_legal(session_name);
3083
3084                         if (illegal) {
3085                                 pop_back_splash (session_dialog);
3086                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3087                                                                                     "session names may not contain a '%1' character"), illegal));
3088                                 msg.run ();
3089                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3090                                 continue;
3091                         }
3092
3093                         _session_is_new = true;
3094                 }
3095
3096                 if (likely_new && template_name.empty()) {
3097
3098                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3099
3100                 } else {
3101
3102                         ret = load_session (session_path, session_name, template_name);
3103
3104                         if (ret == -2) {
3105                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3106                                 exit (1);
3107                         }
3108
3109                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3110                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3111                                 exit (1);
3112                         }
3113
3114                         /* clear this to avoid endless attempts to load the
3115                            same session.
3116                         */
3117
3118                         ARDOUR_COMMAND_LINE::session_name = "";
3119                 }
3120         }
3121
3122         _session_dialog = NULL;
3123
3124         return ret;
3125 }
3126
3127 void
3128 ARDOUR_UI::close_session()
3129 {
3130         if (!check_audioengine(*editor)) {
3131                 return;
3132         }
3133
3134         if (unload_session (true)) {
3135                 return;
3136         }
3137
3138         ARDOUR_COMMAND_LINE::session_name = "";
3139
3140         if (get_session_parameters (true, false)) {
3141                 exit (1);
3142         }
3143
3144         goto_editor_window ();
3145 }
3146
3147 /** @param snap_name Snapshot name (without .ardour suffix).
3148  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3149  */
3150 int
3151 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3152 {
3153         Session *new_session;
3154         int unload_status;
3155         int retval = -1;
3156
3157         if (_session) {
3158                 unload_status = unload_session ();
3159
3160                 if (unload_status < 0) {
3161                         goto out;
3162                 } else if (unload_status > 0) {
3163                         retval = 0;
3164                         goto out;
3165                 }
3166         }
3167
3168         session_loaded = false;
3169
3170         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3171
3172         try {
3173                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3174         }
3175
3176         /* this one is special */
3177
3178         catch (AudioEngine::PortRegistrationFailure& err) {
3179
3180                 MessageDialog msg (err.what(),
3181                                    true,
3182                                    Gtk::MESSAGE_INFO,
3183                                    Gtk::BUTTONS_CLOSE);
3184
3185                 msg.set_title (_("Port Registration Error"));
3186                 msg.set_secondary_text (_("Click the Close button to try again."));
3187                 msg.set_position (Gtk::WIN_POS_CENTER);
3188                 pop_back_splash (msg);
3189                 msg.present ();
3190
3191                 int response = msg.run ();
3192
3193                 msg.hide ();
3194
3195                 switch (response) {
3196                 case RESPONSE_CANCEL:
3197                         exit (1);
3198                 default:
3199                         break;
3200                 }
3201                 goto out;
3202         }
3203         catch (SessionException e) {
3204                 MessageDialog msg (string_compose(
3205                                            _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3206                                            path, snap_name, e.what()),
3207                                    true,
3208                                    Gtk::MESSAGE_INFO,
3209                                    BUTTONS_OK);
3210
3211                 msg.set_title (_("Loading Error"));
3212                 msg.set_position (Gtk::WIN_POS_CENTER);
3213                 pop_back_splash (msg);
3214                 msg.present ();
3215
3216                 dump_errors (cerr);
3217
3218                 (void) msg.run ();
3219                 msg.hide ();
3220
3221                 goto out;
3222         }
3223         catch (...) {
3224
3225                 MessageDialog msg (string_compose(
3226                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
3227                                            path, snap_name),
3228                                    true,
3229                                    Gtk::MESSAGE_INFO,
3230                                    BUTTONS_OK);
3231
3232                 msg.set_title (_("Loading Error"));
3233                 msg.set_position (Gtk::WIN_POS_CENTER);
3234                 pop_back_splash (msg);
3235                 msg.present ();
3236
3237                 dump_errors (cerr);
3238
3239                 (void) msg.run ();
3240                 msg.hide ();
3241
3242                 goto out;
3243         }
3244
3245         {
3246                 list<string> const u = new_session->unknown_processors ();
3247                 if (!u.empty()) {
3248                         MissingPluginDialog d (_session, u);
3249                         d.run ();
3250                 }
3251         }
3252
3253         if (!new_session->writable()) {
3254                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3255                                    true,
3256                                    Gtk::MESSAGE_INFO,
3257                                    BUTTONS_OK);
3258
3259                 msg.set_title (_("Read-only Session"));
3260                 msg.set_position (Gtk::WIN_POS_CENTER);
3261                 pop_back_splash (msg);
3262                 msg.present ();
3263                 (void) msg.run ();
3264                 msg.hide ();
3265         }
3266
3267
3268         /* Now the session been created, add the transport controls */
3269         new_session->add_controllable(roll_controllable);
3270         new_session->add_controllable(stop_controllable);
3271         new_session->add_controllable(goto_start_controllable);
3272         new_session->add_controllable(goto_end_controllable);
3273         new_session->add_controllable(auto_loop_controllable);
3274         new_session->add_controllable(play_selection_controllable);
3275         new_session->add_controllable(rec_controllable);
3276
3277         set_session (new_session);
3278
3279         session_loaded = true;
3280
3281         goto_editor_window ();
3282
3283         if (_session) {
3284                 _session->set_clean ();
3285         }
3286
3287 #ifdef WINDOWS_VST_SUPPORT
3288         fst_stop_threading();
3289 #endif
3290
3291         {
3292                 Timers::TimerSuspender t;
3293                 flush_pending ();
3294         }
3295
3296 #ifdef WINDOWS_VST_SUPPORT
3297         fst_start_threading();
3298 #endif
3299         retval = 0;
3300
3301   out:
3302         return retval;
3303 }
3304
3305 int
3306 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3307 {
3308         Session *new_session;
3309         int x;
3310
3311         session_loaded = false;
3312         x = unload_session ();
3313
3314         if (x < 0) {
3315                 return -1;
3316         } else if (x > 0) {
3317                 return 0;
3318         }
3319
3320         _session_is_new = true;
3321
3322         try {
3323                 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3324         }
3325
3326         catch (SessionException e) {
3327                 dump_errors (cerr);
3328                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3329                 msg.set_title (_("Loading Error"));
3330                 msg.set_position (Gtk::WIN_POS_CENTER);
3331                 pop_back_splash (msg);
3332                 msg.run ();
3333                 return -1;
3334         }
3335         catch (...) {
3336                 dump_errors (cerr);
3337                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3338                 msg.set_title (_("Loading Error"));
3339                 msg.set_position (Gtk::WIN_POS_CENTER);
3340                 pop_back_splash (msg);
3341                 msg.run ();
3342                 return -1;
3343         }
3344
3345         /* Give the new session the default GUI state, if such things exist */
3346
3347         XMLNode* n;
3348         n = Config->instant_xml (X_("Editor"));
3349         if (n) {
3350                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3351                 new_session->add_instant_xml (*n, false);
3352         }
3353         n = Config->instant_xml (X_("Mixer"));
3354         if (n) {
3355                 new_session->add_instant_xml (*n, false);
3356         }
3357
3358         /* Put the playhead at 0 and scroll fully left */
3359         n = new_session->instant_xml (X_("Editor"));
3360         if (n) {
3361                 n->add_property (X_("playhead"), X_("0"));
3362                 n->add_property (X_("left-frame"), X_("0"));
3363         }
3364
3365         set_session (new_session);
3366
3367         session_loaded = true;
3368
3369         new_session->save_state(new_session->name());
3370
3371         return 0;
3372 }
3373
3374 void
3375 ARDOUR_UI::launch_chat ()
3376 {
3377         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3378
3379         dialog.set_title (_("About the Chat"));
3380         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."));
3381
3382         switch (dialog.run()) {
3383         case RESPONSE_OK:
3384 #ifdef __APPLE__
3385                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3386 #elif defined PLATFORM_WINDOWS
3387                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3388 #else
3389                 open_uri("http://webchat.freenode.net/?channels=ardour");
3390 #endif
3391                 break;
3392         default:
3393                 break;
3394         }
3395 }
3396
3397 void
3398 ARDOUR_UI::launch_manual ()
3399 {
3400         PBD::open_uri (Config->get_tutorial_manual_url());
3401 }
3402
3403 void
3404 ARDOUR_UI::launch_reference ()
3405 {
3406         PBD::open_uri (Config->get_reference_manual_url());
3407 }
3408
3409 void
3410 ARDOUR_UI::launch_tracker ()
3411 {
3412         PBD::open_uri ("http://tracker.ardour.org");
3413 }
3414
3415 void
3416 ARDOUR_UI::launch_subscribe ()
3417 {
3418         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3419 }
3420
3421 void
3422 ARDOUR_UI::launch_cheat_sheet ()
3423 {
3424 #ifdef __APPLE__
3425         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3426 #else
3427         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3428 #endif
3429 }
3430
3431 void
3432 ARDOUR_UI::launch_website ()
3433 {
3434         PBD::open_uri ("http://ardour.org");
3435 }
3436
3437 void
3438 ARDOUR_UI::launch_website_dev ()
3439 {
3440         PBD::open_uri ("http://ardour.org/development.html");
3441 }
3442
3443 void
3444 ARDOUR_UI::launch_forums ()
3445 {
3446         PBD::open_uri ("https://community.ardour.org/forums");
3447 }
3448
3449 void
3450 ARDOUR_UI::launch_howto_report ()
3451 {
3452         PBD::open_uri ("http://ardour.org/reporting_bugs");
3453 }
3454
3455 void
3456 ARDOUR_UI::loading_message (const std::string& msg)
3457 {
3458         if (ARDOUR_COMMAND_LINE::no_splash) {
3459                 return;
3460         }
3461
3462         if (!splash) {
3463                 show_splash ();
3464         }
3465
3466         splash->message (msg);
3467 }
3468
3469 void
3470 ARDOUR_UI::show_splash ()
3471 {
3472         if (splash == 0) {
3473                 try {
3474                         splash = new Splash;
3475                 } catch (...) {
3476                         return;
3477                 }
3478         }
3479
3480         splash->display ();
3481 }
3482
3483 void
3484 ARDOUR_UI::hide_splash ()
3485 {
3486         delete splash;
3487         splash = 0;
3488 }
3489
3490 void
3491 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3492 {
3493         size_t removed;
3494
3495         removed = rep.paths.size();
3496
3497         if (removed == 0) {
3498                 MessageDialog msgd (*editor,
3499                                     _("No files were ready for clean-up"),
3500                                     true,
3501                                     Gtk::MESSAGE_INFO,
3502                                     Gtk::BUTTONS_OK);
3503                 msgd.set_title (_("Clean-up"));
3504                 msgd.set_secondary_text (_("If this seems suprising, \n\
3505 check for any existing snapshots.\n\
3506 These may still include regions that\n\
3507 require some unused files to continue to exist."));
3508
3509                 msgd.run ();
3510                 return;
3511         }
3512
3513         ArdourDialog results (_("Clean-up"), true, false);
3514
3515         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3516             CleanupResultsModelColumns() {
3517                     add (visible_name);
3518                     add (fullpath);
3519             }
3520             Gtk::TreeModelColumn<std::string> visible_name;
3521             Gtk::TreeModelColumn<std::string> fullpath;
3522         };
3523
3524
3525         CleanupResultsModelColumns results_columns;
3526         Glib::RefPtr<Gtk::ListStore> results_model;
3527         Gtk::TreeView results_display;
3528
3529         results_model = ListStore::create (results_columns);
3530         results_display.set_model (results_model);
3531         results_display.append_column (list_title, results_columns.visible_name);
3532
3533         results_display.set_name ("CleanupResultsList");
3534         results_display.set_headers_visible (true);
3535         results_display.set_headers_clickable (false);
3536         results_display.set_reorderable (false);
3537
3538         Gtk::ScrolledWindow list_scroller;
3539         Gtk::Label txt;
3540         Gtk::VBox dvbox;
3541         Gtk::HBox dhbox;  // the hbox for the image and text
3542         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3543         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3544
3545         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3546
3547         const string dead_directory = _session->session_directory().dead_path();
3548
3549         /* subst:
3550            %1 - number of files removed
3551            %2 - location of "dead"
3552            %3 - size of files affected
3553            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3554         */
3555
3556         const char* bprefix;
3557         double space_adjusted = 0;
3558
3559         if (rep.space < 1000) {
3560                 bprefix = X_("");
3561                 space_adjusted = rep.space;
3562         } else if (rep.space < 1000000) {
3563                 bprefix = _("kilo");
3564                 space_adjusted = floorf((float)rep.space / 1000.0);
3565         } else if (rep.space < 1000000 * 1000) {
3566                 bprefix = _("mega");
3567                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3568         } else {
3569                 bprefix = _("giga");
3570                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3571         }
3572
3573         if (msg_delete) {
3574                 txt.set_markup (string_compose (P_("\
3575 The following file was deleted from %2,\n\
3576 releasing %3 %4bytes of disk space", "\
3577 The following %1 files were deleted from %2,\n\
3578 releasing %3 %4bytes of disk space", removed),
3579                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3580         } else {
3581                 txt.set_markup (string_compose (P_("\
3582 The following file was not in use and \n\
3583 has been moved to: %2\n\n\
3584 After a restart of %5\n\n\
3585 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3586 will release an additional %3 %4bytes of disk space.\n", "\
3587 The following %1 files were not in use and \n\
3588 have been moved to: %2\n\n\
3589 After a restart of %5\n\n\
3590 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3591 will release an additional %3 %4bytes of disk space.\n", removed),
3592                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3593         }
3594
3595         dhbox.pack_start (*dimage, true, false, 5);
3596         dhbox.pack_start (txt, true, false, 5);
3597
3598         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3599                 TreeModel::Row row = *(results_model->append());
3600                 row[results_columns.visible_name] = *i;
3601                 row[results_columns.fullpath] = *i;
3602         }
3603
3604         list_scroller.add (results_display);
3605         list_scroller.set_size_request (-1, 150);
3606         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3607
3608         dvbox.pack_start (dhbox, true, false, 5);
3609         dvbox.pack_start (list_scroller, true, false, 5);
3610         ddhbox.pack_start (dvbox, true, false, 5);
3611
3612         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3613         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3614         results.set_default_response (RESPONSE_CLOSE);
3615         results.set_position (Gtk::WIN_POS_MOUSE);
3616
3617         results_display.show();
3618         list_scroller.show();
3619         txt.show();
3620         dvbox.show();
3621         dhbox.show();
3622         ddhbox.show();
3623         dimage->show();
3624
3625         //results.get_vbox()->show();
3626         results.set_resizable (false);
3627
3628         results.run ();
3629
3630 }
3631
3632 void
3633 ARDOUR_UI::cleanup ()
3634 {
3635         if (_session == 0) {
3636                 /* shouldn't happen: menu item is insensitive */
3637                 return;
3638         }
3639
3640
3641         MessageDialog checker (_("Are you sure you want to clean-up?"),
3642                                 true,
3643                                 Gtk::MESSAGE_QUESTION,
3644                                 Gtk::BUTTONS_NONE);
3645
3646         checker.set_title (_("Clean-up"));
3647
3648         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3649 ALL undo/redo information will be lost if you clean-up.\n\
3650 Clean-up will move all unused files to a \"dead\" location."));
3651
3652         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3653         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3654         checker.set_default_response (RESPONSE_CANCEL);
3655
3656         checker.set_name (_("CleanupDialog"));
3657         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3658         checker.set_position (Gtk::WIN_POS_MOUSE);
3659
3660         switch (checker.run()) {
3661         case RESPONSE_ACCEPT:
3662                 break;
3663         default:
3664                 return;
3665         }
3666
3667         ARDOUR::CleanupReport rep;
3668
3669         editor->prepare_for_cleanup ();
3670
3671         /* do not allow flush until a session is reloaded */
3672
3673         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3674         if (act) {
3675                 act->set_sensitive (false);
3676         }
3677
3678         if (_session->cleanup_sources (rep)) {
3679                 editor->finish_cleanup ();
3680                 return;
3681         }
3682
3683         editor->finish_cleanup ();
3684
3685         checker.hide();
3686         display_cleanup_results (rep, _("Cleaned Files"), false);
3687 }
3688
3689 void
3690 ARDOUR_UI::flush_trash ()
3691 {
3692         if (_session == 0) {
3693                 /* shouldn't happen: menu item is insensitive */
3694                 return;
3695         }
3696
3697         ARDOUR::CleanupReport rep;
3698
3699         if (_session->cleanup_trash_sources (rep)) {
3700                 return;
3701         }
3702
3703         display_cleanup_results (rep, _("deleted file"), true);
3704 }
3705
3706 void
3707 ARDOUR_UI::cleanup_peakfiles ()
3708 {
3709         if (_session == 0) {
3710                 /* shouldn't happen: menu item is insensitive */
3711                 return;
3712         }
3713
3714         if (! _session->can_cleanup_peakfiles ()) {
3715                 return;
3716         }
3717
3718         // get all region-views in this session
3719         RegionSelection rs;
3720         TrackViewList empty;
3721         empty.clear();
3722         editor->get_regions_after(rs, (framepos_t) 0, empty);
3723         std::list<RegionView*> views = rs.by_layer();
3724
3725         // remove displayed audio-region-views waveforms
3726         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3727                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3728                 if (!arv) { continue ; }
3729                 arv->delete_waves();
3730         }
3731
3732         // cleanup peak files:
3733         // - stop pending peakfile threads
3734         // - close peakfiles if any
3735         // - remove peak dir in session
3736         // - setup peakfiles (background thread)
3737         _session->cleanup_peakfiles ();
3738
3739         // re-add waves to ARV
3740         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3741                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3742                 if (!arv) { continue ; }
3743                 arv->create_waves();
3744         }
3745 }
3746
3747 void
3748 ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
3749 {
3750         uint32_t order_hint = UINT32_MAX;
3751
3752         if (editor->get_selection().tracks.empty()) {
3753                 return;
3754         }
3755
3756         /*
3757           we want the new routes to have their order keys set starting from
3758           the highest order key in the selection + 1 (if available).
3759         */
3760
3761         if (place == AddRouteDialog::AfterSelection) {
3762                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
3763                 if (rtav) {
3764                         order_hint = rtav->route()->order_key();
3765                         order_hint++;
3766                 }
3767         } else if (place == AddRouteDialog::BeforeSelection) {
3768                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
3769                 if (rtav) {
3770                         order_hint = rtav->route()->order_key();
3771                 }
3772         } else if (place == AddRouteDialog::First) {
3773                 order_hint = 0;
3774         } else {
3775                 /* leave order_hint at UINT32_MAX */
3776         }
3777
3778         if (order_hint == UINT32_MAX) {
3779                 /** AddRouteDialog::Last or selection with first/last not a RouteTimeAxisView
3780                  * not setting an order hint will place new routes last.
3781                  */
3782                 return;
3783         }
3784
3785         _session->set_order_hint (order_hint);
3786
3787         /* create a gap in the existing route order keys to accomodate new routes.*/
3788         boost::shared_ptr <RouteList> rd = _session->get_routes();
3789         for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
3790                 boost::shared_ptr<Route> rt (*ri);
3791
3792                 if (rt->is_monitor()) {
3793                         continue;
3794                 }
3795
3796                 if (rt->order_key () >= order_hint) {
3797                         rt->set_order_key (rt->order_key () + add_route_dialog->count());
3798                 }
3799         }
3800 }
3801
3802 void
3803 ARDOUR_UI::start_duplicate_routes ()
3804 {
3805         if (!duplicate_routes_dialog) {
3806                 duplicate_routes_dialog = new DuplicateRouteDialog;
3807         }
3808
3809         if (duplicate_routes_dialog->restart (_session)) {
3810                 return;
3811         }
3812
3813         duplicate_routes_dialog->present ();
3814 }
3815
3816 void
3817 ARDOUR_UI::add_route (Gtk::Window* /* ignored */)
3818 {
3819         int count;
3820
3821         if (!_session) {
3822                 return;
3823         }
3824
3825         if (add_route_dialog->is_visible()) {
3826                 /* we're already doing this */
3827                 return;
3828         }
3829
3830         ResponseType r = (ResponseType) add_route_dialog->run ();
3831
3832         add_route_dialog->hide();
3833
3834         switch (r) {
3835                 case RESPONSE_ACCEPT:
3836                         break;
3837                 default:
3838                         return;
3839                         break;
3840         }
3841
3842         if ((count = add_route_dialog->count()) <= 0) {
3843                 return;
3844         }
3845
3846         setup_order_hint(add_route_dialog->insert_at());
3847
3848         string template_path = add_route_dialog->track_template();
3849         DisplaySuspender ds;
3850
3851         if (!template_path.empty()) {
3852                 if (add_route_dialog->name_template_is_default())  {
3853                         _session->new_route_from_template (count, template_path, string());
3854                 } else {
3855                         _session->new_route_from_template (count, template_path, add_route_dialog->name_template());
3856                 }
3857                 return;
3858         }
3859
3860         ChanCount input_chan= add_route_dialog->channels ();
3861         ChanCount output_chan;
3862         string name_template = add_route_dialog->name_template ();
3863         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
3864         RouteGroup* route_group = add_route_dialog->route_group ();
3865         AutoConnectOption oac = Config->get_output_auto_connect();
3866
3867         if (oac & AutoConnectMaster) {
3868                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
3869                 output_chan.set (DataType::MIDI, 0);
3870         } else {
3871                 output_chan = input_chan;
3872         }
3873
3874         /* XXX do something with name template */
3875
3876         switch (add_route_dialog->type_wanted()) {
3877         case AddRouteDialog::AudioTrack:
3878                 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template);
3879                 break;
3880         case AddRouteDialog::MidiTrack:
3881                 session_add_midi_track (route_group, count, name_template, instrument);
3882                 break;
3883         case AddRouteDialog::MixedTrack:
3884                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, instrument);
3885                 break;
3886         case AddRouteDialog::AudioBus:
3887                 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template);
3888                 break;
3889         }
3890 }
3891
3892 void
3893 ARDOUR_UI::stop_video_server (bool ask_confirm)
3894 {
3895         if (!video_server_process && ask_confirm) {
3896                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
3897         }
3898         if (video_server_process) {
3899                 if(ask_confirm) {
3900                         ArdourDialog confirm (_("Stop Video-Server"), true);
3901                         Label m (_("Do you really want to stop the Video Server?"));
3902                         confirm.get_vbox()->pack_start (m, true, true);
3903                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
3904                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
3905                         confirm.show_all ();
3906                         if (confirm.run() == RESPONSE_CANCEL) {
3907                                 return;
3908                         }
3909                 }
3910                 delete video_server_process;
3911                 video_server_process =0;
3912         }
3913 }
3914
3915 void
3916 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
3917 {
3918   ARDOUR_UI::start_video_server( float_window, true);
3919 }
3920
3921 bool
3922 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
3923 {
3924         if (!_session) {
3925                 return false;
3926         }
3927         if (popup_msg) {
3928                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
3929                         if (video_server_process) {
3930                                 popup_error(_("The Video Server is already started."));
3931                         } else {
3932                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
3933                         }
3934                 }
3935         }
3936
3937         int firsttime = 0;
3938         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
3939                 if (firsttime++) {
3940                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
3941                 }
3942                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
3943                 if (float_window) {
3944                         video_server_dialog->set_transient_for (*float_window);
3945                 }
3946
3947                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
3948                         video_server_dialog->hide();
3949                 } else {
3950                         ResponseType r = (ResponseType) video_server_dialog->run ();
3951                         video_server_dialog->hide();
3952                         if (r != RESPONSE_ACCEPT) { return false; }
3953                         if (video_server_dialog->show_again()) {
3954                                 Config->set_show_video_server_dialog(false);
3955                         }
3956                 }
3957
3958                 std::string icsd_exec = video_server_dialog->get_exec_path();
3959                 std::string icsd_docroot = video_server_dialog->get_docroot();
3960                 if (icsd_docroot.empty()) {
3961 #ifndef PLATFORM_WINDOWS
3962                         icsd_docroot = X_("/");
3963 #else
3964                         icsd_docroot = X_("C:\\");
3965 #endif
3966                 }
3967
3968                 GStatBuf sb;
3969                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
3970                         warning << _("Specified docroot is not an existing directory.") << endmsg;
3971                         continue;
3972                 }
3973 #ifndef PLATFORM_WINDOWS
3974                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
3975                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
3976                         warning << _("Given Video Server is not an executable file.") << endmsg;
3977                         continue;
3978                 }
3979 #else
3980                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
3981                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
3982                         warning << _("Given Video Server is not an executable file.") << endmsg;
3983                         continue;
3984                 }
3985 #endif
3986
3987                 char **argp;
3988                 argp=(char**) calloc(9,sizeof(char*));
3989                 argp[0] = strdup(icsd_exec.c_str());
3990                 argp[1] = strdup("-P");
3991                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
3992                 argp[3] = strdup("-p");
3993                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
3994                 argp[5] = strdup("-C");
3995                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
3996                 argp[7] = strdup(icsd_docroot.c_str());
3997                 argp[8] = 0;
3998                 stop_video_server();
3999
4000                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4001                         Config->set_video_advanced_setup(false);
4002                 } else {
4003                         std::ostringstream osstream;
4004                         osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4005                         Config->set_video_server_url(osstream.str());
4006                         Config->set_video_server_docroot(icsd_docroot);
4007                         Config->set_video_advanced_setup(true);
4008                 }
4009
4010                 if (video_server_process) {
4011                         delete video_server_process;
4012                 }
4013
4014                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4015                 if (video_server_process->start()) {
4016                         warning << _("Cannot launch the video-server") << endmsg;
4017                         continue;
4018                 }
4019                 int timeout = 120; // 6 sec
4020                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4021                         Glib::usleep (50000);
4022                         gui_idle_handler();
4023                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4024                 }
4025                 if (timeout <= 0) {
4026                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4027                 } else {
4028                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4029                                 delete video_server_process;
4030                                 video_server_process = 0;
4031                         }
4032                 }
4033         }
4034         return true;
4035 }
4036
4037 void
4038 ARDOUR_UI::add_video (Gtk::Window* float_window)
4039 {
4040         if (!_session) {
4041                 return;
4042         }
4043
4044         if (!start_video_server(float_window, false)) {
4045                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4046                 return;
4047         }
4048
4049         if (float_window) {
4050                 add_video_dialog->set_transient_for (*float_window);
4051         }
4052
4053         if (add_video_dialog->is_visible()) {
4054                 /* we're already doing this */
4055                 return;
4056         }
4057
4058         ResponseType r = (ResponseType) add_video_dialog->run ();
4059         add_video_dialog->hide();
4060         if (r != RESPONSE_ACCEPT) { return; }
4061
4062         bool local_file, orig_local_file;
4063         std::string path = add_video_dialog->file_name(local_file);
4064
4065         std::string orig_path = path;
4066         orig_local_file = local_file;
4067
4068         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4069
4070         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4071                 warning << string_compose(_("could not open %1"), path) << endmsg;
4072                 return;
4073         }
4074         if (!local_file && path.length() == 0) {
4075                 warning << _("no video-file selected") << endmsg;
4076                 return;
4077         }
4078
4079         std::string audio_from_video;
4080         bool detect_ltc = false;
4081
4082         switch (add_video_dialog->import_option()) {
4083                 case VTL_IMPORT_TRANSCODE:
4084                         {
4085                                 TranscodeVideoDialog *transcode_video_dialog;
4086                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4087                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4088                                 transcode_video_dialog->hide();
4089                                 if (r != RESPONSE_ACCEPT) {
4090                                         delete transcode_video_dialog;
4091                                         return;
4092                                 }
4093
4094                                 audio_from_video = transcode_video_dialog->get_audiofile();
4095
4096                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4097                                         detect_ltc = true;
4098                                 }
4099                                 else if (!audio_from_video.empty()) {
4100                                         editor->embed_audio_from_video(
4101                                                         audio_from_video,
4102                                                         video_timeline->get_offset(),
4103                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4104                                                         );
4105                                 }
4106                                 switch (transcode_video_dialog->import_option()) {
4107                                         case VTL_IMPORT_TRANSCODED:
4108                                                 path = transcode_video_dialog->get_filename();
4109                                                 local_file = true;
4110                                                 break;
4111                                         case VTL_IMPORT_REFERENCE:
4112                                                 break;
4113                                         default:
4114                                                 delete transcode_video_dialog;
4115                                                 return;
4116                                 }
4117                                 delete transcode_video_dialog;
4118                         }
4119                         break;
4120                 default:
4121                 case VTL_IMPORT_NONE:
4122                         break;
4123         }
4124
4125         /* strip _session->session_directory().video_path() from video file if possible */
4126         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4127                  path=path.substr(_session->session_directory().video_path().size());
4128                  if (path.at(0) == G_DIR_SEPARATOR) {
4129                          path=path.substr(1);
4130                  }
4131         }
4132
4133         video_timeline->set_update_session_fps(auto_set_session_fps);
4134
4135         if (video_timeline->video_file_info(path, local_file)) {
4136                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4137                 node->add_property (X_("Filename"), path);
4138                 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4139                 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4140                 if (orig_local_file) {
4141                         node->add_property (X_("OriginalVideoFile"), orig_path);
4142                 } else {
4143                         node->remove_property (X_("OriginalVideoFile"));
4144                 }
4145                 _session->add_extra_xml (*node);
4146                 _session->set_dirty ();
4147
4148                 if (!audio_from_video.empty() && detect_ltc) {
4149                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4150
4151                         try {
4152                                 /* TODO ask user about TV standard (LTC alignment if any) */
4153                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4154                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4155
4156                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4157
4158                                 /* TODO seek near end of file, and read LTC until end.
4159                                  * if it fails to find any LTC frames, scan complete file
4160                                  *
4161                                  * calculate drift of LTC compared to video-duration,
4162                                  * ask user for reference (timecode from start/mid/end)
4163                                  */
4164                         } catch (...) {
4165                                 // LTCFileReader will have written error messages
4166                         }
4167
4168                         ::g_unlink(audio_from_video.c_str());
4169
4170                         if (ltc_seq.size() == 0) {
4171                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4172                         } else {
4173                                 /* the very first TC in the file is somteimes not aligned properly */
4174                                 int i = ltc_seq.size() -1;
4175                                 ARDOUR::frameoffset_t video_start_offset =
4176                                         _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4177                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4178                                 video_timeline->set_offset(video_start_offset);
4179                         }
4180                 }
4181
4182                 _session->maybe_update_session_range(
4183                         std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4184                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4185
4186
4187                 if (add_video_dialog->launch_xjadeo() && local_file) {
4188                         editor->set_xjadeo_sensitive(true);
4189                         editor->toggle_xjadeo_proc(1);
4190                 } else {
4191                         editor->toggle_xjadeo_proc(0);
4192                 }
4193                 editor->toggle_ruler_video(true);
4194         }
4195 }
4196
4197 void
4198 ARDOUR_UI::remove_video ()
4199 {
4200         video_timeline->close_session();
4201         editor->toggle_ruler_video(false);
4202
4203         /* reset state */
4204         video_timeline->set_offset_locked(false);
4205         video_timeline->set_offset(0);
4206
4207         /* delete session state */
4208         XMLNode* node = new XMLNode(X_("Videotimeline"));
4209         _session->add_extra_xml(*node);
4210         node = new XMLNode(X_("Videomonitor"));
4211         _session->add_extra_xml(*node);
4212         node = new XMLNode(X_("Videoexport"));
4213         _session->add_extra_xml(*node);
4214         stop_video_server();
4215 }
4216
4217 void
4218 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4219 {
4220         if (localcacheonly) {
4221                 video_timeline->vmon_update();
4222         } else {
4223                 video_timeline->flush_cache();
4224         }
4225         editor->queue_visual_videotimeline_update();
4226 }
4227
4228 void
4229 ARDOUR_UI::export_video (bool range)
4230 {
4231         if (ARDOUR::Config->get_show_video_export_info()) {
4232                 ExportVideoInfobox infobox (_session);
4233                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4234                 if (infobox.show_again()) {
4235                         ARDOUR::Config->set_show_video_export_info(false);
4236                 }
4237                 switch (rv) {
4238                         case GTK_RESPONSE_YES:
4239                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4240                                 break;
4241                         default:
4242                                 break;
4243                 }
4244         }
4245         export_video_dialog->set_session (_session);
4246         export_video_dialog->apply_state(editor->get_selection().time, range);
4247         export_video_dialog->run ();
4248         export_video_dialog->hide ();
4249 }
4250
4251 XMLNode*
4252 ARDOUR_UI::mixer_settings () const
4253 {
4254         XMLNode* node = 0;
4255
4256         if (_session) {
4257                 node = _session->instant_xml(X_("Mixer"));
4258         } else {
4259                 node = Config->instant_xml(X_("Mixer"));
4260         }
4261
4262         if (!node) {
4263                 node = new XMLNode (X_("Mixer"));
4264         }
4265
4266         return node;
4267 }
4268
4269 XMLNode*
4270 ARDOUR_UI::editor_settings () const
4271 {
4272         XMLNode* node = 0;
4273
4274         if (_session) {
4275                 node = _session->instant_xml(X_("Editor"));
4276         } else {
4277                 node = Config->instant_xml(X_("Editor"));
4278         }
4279
4280         if (!node) {
4281                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4282                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4283                 }
4284         }
4285
4286         if (!node) {
4287                 node = new XMLNode (X_("Editor"));
4288         }
4289
4290         return node;
4291 }
4292
4293 XMLNode*
4294 ARDOUR_UI::keyboard_settings () const
4295 {
4296         XMLNode* node = 0;
4297
4298         node = Config->extra_xml(X_("Keyboard"));
4299
4300         if (!node) {
4301                 node = new XMLNode (X_("Keyboard"));
4302         }
4303
4304         return node;
4305 }
4306
4307 void
4308 ARDOUR_UI::create_xrun_marker (framepos_t where)
4309 {
4310         if (_session) {
4311                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
4312                 _session->locations()->add (location);
4313         }
4314 }
4315
4316 void
4317 ARDOUR_UI::halt_on_xrun_message ()
4318 {
4319         cerr << "HALT on xrun\n";
4320         MessageDialog msg (*editor, _("Recording was stopped because your system could not keep up."));
4321         msg.run ();
4322 }
4323
4324 void
4325 ARDOUR_UI::xrun_handler (framepos_t where)
4326 {
4327         if (!_session) {
4328                 return;
4329         }
4330
4331         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4332
4333         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4334                 create_xrun_marker(where);
4335         }
4336
4337         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4338                 halt_on_xrun_message ();
4339         }
4340 }
4341
4342 void
4343 ARDOUR_UI::disk_overrun_handler ()
4344 {
4345         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4346
4347         if (!have_disk_speed_dialog_displayed) {
4348                 have_disk_speed_dialog_displayed = true;
4349                 MessageDialog* msg = new MessageDialog (*editor, string_compose (_("\
4350 The disk system on your computer\n\
4351 was not able to keep up with %1.\n\
4352 \n\
4353 Specifically, it failed to write data to disk\n\
4354 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4355                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4356                 msg->show ();
4357         }
4358 }
4359
4360
4361 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4362 static MessageDialog *scan_dlg = NULL;
4363 static ProgressBar   *scan_pbar = NULL;
4364 static HBox          *scan_tbox = NULL;
4365 static Gtk::Button   *scan_timeout_button;
4366
4367 void
4368 ARDOUR_UI::cancel_plugin_scan ()
4369 {
4370         PluginManager::instance().cancel_plugin_scan();
4371 }
4372
4373 void
4374 ARDOUR_UI::cancel_plugin_timeout ()
4375 {
4376         PluginManager::instance().cancel_plugin_timeout();
4377         scan_timeout_button->set_sensitive (false);
4378 }
4379
4380 void
4381 ARDOUR_UI::plugin_scan_timeout (int timeout)
4382 {
4383         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4384                 return;
4385         }
4386         if (timeout > 0) {
4387                 scan_pbar->set_sensitive (false);
4388                 scan_timeout_button->set_sensitive (true);
4389                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4390                 scan_tbox->show();
4391         } else {
4392                 scan_pbar->set_sensitive (false);
4393                 scan_timeout_button->set_sensitive (false);
4394         }
4395         gui_idle_handler();
4396 }
4397
4398 void
4399 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4400 {
4401         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4402                 return;
4403         }
4404
4405         const bool cancelled = PluginManager::instance().cancelled();
4406         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4407                 if (cancelled && scan_dlg->is_mapped()) {
4408                         scan_dlg->hide();
4409                         gui_idle_handler();
4410                         return;
4411                 }
4412                 if (cancelled || !can_cancel) {
4413                         return;
4414                 }
4415         }
4416
4417         static Gtk::Button *cancel_button;
4418         if (!scan_dlg) {
4419                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4420                 VBox* vbox = scan_dlg->get_vbox();
4421                 vbox->set_size_request(400,-1);
4422                 scan_dlg->set_title (_("Scanning for plugins"));
4423
4424                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4425                 cancel_button->set_name ("EditorGTKButton");
4426                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4427                 cancel_button->show();
4428
4429                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4430
4431                 scan_tbox = manage( new HBox() );
4432
4433                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4434                 scan_timeout_button->set_name ("EditorGTKButton");
4435                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4436                 scan_timeout_button->show();
4437
4438                 scan_pbar = manage(new ProgressBar());
4439                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4440                 scan_pbar->set_text(_("Scan Timeout"));
4441                 scan_pbar->show();
4442
4443                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4444                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4445
4446                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4447         }
4448
4449         assert(scan_dlg && scan_tbox && cancel_button);
4450
4451         if (type == X_("closeme")) {
4452                 scan_tbox->hide();
4453                 scan_dlg->hide();
4454         } else {
4455                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4456                 scan_dlg->show();
4457         }
4458         if (!can_cancel || !cancelled) {
4459                 scan_timeout_button->set_sensitive(false);
4460         }
4461         cancel_button->set_sensitive(can_cancel && !cancelled);
4462
4463         gui_idle_handler();
4464 }
4465
4466 void
4467 ARDOUR_UI::gui_idle_handler ()
4468 {
4469         int timeout = 30;
4470         /* due to idle calls, gtk_events_pending() may always return true */
4471         while (gtk_events_pending() && --timeout) {
4472                 gtk_main_iteration ();
4473         }
4474 }
4475
4476 void
4477 ARDOUR_UI::disk_underrun_handler ()
4478 {
4479         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4480
4481         if (!have_disk_speed_dialog_displayed) {
4482                 have_disk_speed_dialog_displayed = true;
4483                 MessageDialog* msg = new MessageDialog (
4484                         *editor, string_compose (_("The disk system on your computer\n\
4485 was not able to keep up with %1.\n\
4486 \n\
4487 Specifically, it failed to read data from disk\n\
4488 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4489                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4490                 msg->show ();
4491         }
4492 }
4493
4494 void
4495 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4496 {
4497         have_disk_speed_dialog_displayed = false;
4498         delete msg;
4499 }
4500
4501 void
4502 ARDOUR_UI::session_dialog (std::string msg)
4503 {
4504         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4505
4506         MessageDialog* d;
4507
4508         if (editor) {
4509                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4510         } else {
4511                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4512         }
4513
4514         d->show_all ();
4515         d->run ();
4516         delete d;
4517 }
4518
4519 int
4520 ARDOUR_UI::pending_state_dialog ()
4521 {
4522         HBox* hbox = manage (new HBox());
4523         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4524         ArdourDialog dialog (_("Crash Recovery"), true);
4525         Label  message (string_compose (_("\
4526 This session appears to have been in the\n\
4527 middle of recording when %1 or\n\
4528 the computer was shutdown.\n\
4529 \n\
4530 %1 can recover any captured audio for\n\
4531 you, or it can ignore it. Please decide\n\
4532 what you would like to do.\n"), PROGRAM_NAME));
4533         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4534         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4535         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4536         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4537         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
4538         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
4539         dialog.set_default_response (RESPONSE_ACCEPT);
4540         dialog.set_position (WIN_POS_CENTER);
4541         message.show();
4542         image->show();
4543         hbox->show();
4544
4545         switch (dialog.run ()) {
4546         case RESPONSE_ACCEPT:
4547                 return 1;
4548         default:
4549                 return 0;
4550         }
4551 }
4552
4553 int
4554 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4555 {
4556         HBox* hbox = new HBox();
4557         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4558         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4559         Label  message (string_compose (_("\
4560 This session was created with a sample rate of %1 Hz, but\n\
4561 %2 is currently running at %3 Hz.  If you load this session,\n\
4562 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4563
4564         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4565         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4566         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4567         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4568         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4569         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4570         dialog.set_default_response (RESPONSE_ACCEPT);
4571         dialog.set_position (WIN_POS_CENTER);
4572         message.show();
4573         image->show();
4574         hbox->show();
4575
4576         switch (dialog.run()) {
4577         case RESPONSE_ACCEPT:
4578                 return 0;
4579         default:
4580                 break;
4581         }
4582
4583         return 1;
4584 }
4585
4586 void
4587 ARDOUR_UI::use_config ()
4588 {
4589         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
4590         if (node) {
4591                 set_transport_controllable_state (*node);
4592         }
4593 }
4594
4595 void
4596 ARDOUR_UI::update_transport_clocks (framepos_t pos)
4597 {
4598         if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
4599                 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4600         } else {
4601                 primary_clock->set (pos);
4602         }
4603
4604         if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
4605                 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4606         } else {
4607                 secondary_clock->set (pos);
4608         }
4609
4610         if (big_clock_window) {
4611                 big_clock->set (pos);
4612         }
4613         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
4614 }
4615
4616 void
4617 ARDOUR_UI::step_edit_status_change (bool yn)
4618 {
4619         // XXX should really store pre-step edit status of things
4620         // we make insensitive
4621
4622         if (yn) {
4623                 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
4624                 rec_button.set_sensitive (false);
4625         } else {
4626                 rec_button.unset_active_state ();;
4627                 rec_button.set_sensitive (true);
4628         }
4629 }
4630
4631 void
4632 ARDOUR_UI::record_state_changed ()
4633 {
4634         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
4635
4636         if (!_session || !big_clock_window) {
4637                 /* why bother - the clock isn't visible */
4638                 return;
4639         }
4640
4641         if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
4642                 big_clock->set_active (true);
4643         } else {
4644                 big_clock->set_active (false);
4645         }
4646 }
4647
4648 bool
4649 ARDOUR_UI::first_idle ()
4650 {
4651         if (_session) {
4652                 _session->allow_auto_play (true);
4653         }
4654
4655         if (editor) {
4656                 editor->first_idle();
4657         }
4658
4659         Keyboard::set_can_save_keybindings (true);
4660         return false;
4661 }
4662
4663 void
4664 ARDOUR_UI::store_clock_modes ()
4665 {
4666         XMLNode* node = new XMLNode(X_("ClockModes"));
4667
4668         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
4669                 XMLNode* child = new XMLNode (X_("Clock"));
4670
4671                 child->add_property (X_("name"), (*x)->name());
4672                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
4673                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
4674
4675                 node->add_child_nocopy (*child);
4676         }
4677
4678         _session->add_extra_xml (*node);
4679         _session->set_dirty ();
4680 }
4681
4682 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
4683         : Controllable (name), ui (u), type(tp)
4684 {
4685
4686 }
4687
4688 void
4689 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
4690 {
4691         if (val < 0.5) {
4692                 /* do nothing: these are radio-style actions */
4693                 return;
4694         }
4695
4696         const char *action = 0;
4697
4698         switch (type) {
4699         case Roll:
4700                 action = X_("Roll");
4701                 break;
4702         case Stop:
4703                 action = X_("Stop");
4704                 break;
4705         case GotoStart:
4706                 action = X_("GotoStart");
4707                 break;
4708         case GotoEnd:
4709                 action = X_("GotoEnd");
4710                 break;
4711         case AutoLoop:
4712                 action = X_("Loop");
4713                 break;
4714         case PlaySelection:
4715                 action = X_("PlaySelection");
4716                 break;
4717         case RecordEnable:
4718                 action = X_("Record");
4719                 break;
4720         default:
4721                 break;
4722         }
4723
4724         if (action == 0) {
4725                 return;
4726         }
4727
4728         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
4729
4730         if (act) {
4731                 act->activate ();
4732         }
4733 }
4734
4735 double
4736 ARDOUR_UI::TransportControllable::get_value (void) const
4737 {
4738         float val = 0.0;
4739
4740         switch (type) {
4741         case Roll:
4742                 break;
4743         case Stop:
4744                 break;
4745         case GotoStart:
4746                 break;
4747         case GotoEnd:
4748                 break;
4749         case AutoLoop:
4750                 break;
4751         case PlaySelection:
4752                 break;
4753         case RecordEnable:
4754                 break;
4755         default:
4756                 break;
4757         }
4758
4759         return val;
4760 }
4761
4762 void
4763 ARDOUR_UI::setup_profile ()
4764 {
4765         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
4766                 Profile->set_small_screen ();
4767         }
4768
4769         if (g_getenv ("ARDOUR_SAE")) {
4770                 Profile->set_sae ();
4771                 Profile->set_single_package ();
4772         }
4773
4774         if (g_getenv ("TRX")) {
4775                 Profile->set_trx ();
4776         }
4777
4778         if (g_getenv ("MIXBUS")) {
4779                 Profile->set_mixbus ();
4780         }
4781 }
4782
4783 int
4784 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
4785 {
4786         MissingFileDialog dialog (s, str, type);
4787
4788         dialog.show ();
4789         dialog.present ();
4790
4791         int result = dialog.run ();
4792         dialog.hide ();
4793
4794         switch (result) {
4795         case RESPONSE_OK:
4796                 break;
4797         default:
4798                 return 1; // quit entire session load
4799         }
4800
4801         result = dialog.get_action ();
4802
4803         return result;
4804 }
4805
4806 int
4807 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
4808 {
4809         AmbiguousFileDialog dialog (file, hits);
4810
4811         dialog.show ();
4812         dialog.present ();
4813
4814         dialog.run ();
4815
4816         return dialog.get_which ();
4817 }
4818
4819 /** Allocate our thread-local buffers */
4820 void
4821 ARDOUR_UI::get_process_buffers ()
4822 {
4823         _process_thread->get_buffers ();
4824 }
4825
4826 /** Drop our thread-local buffers */
4827 void
4828 ARDOUR_UI::drop_process_buffers ()
4829 {
4830         _process_thread->drop_buffers ();
4831 }
4832
4833 void
4834 ARDOUR_UI::feedback_detected ()
4835 {
4836         _feedback_exists = true;
4837 }
4838
4839 void
4840 ARDOUR_UI::successful_graph_sort ()
4841 {
4842         _feedback_exists = false;
4843 }
4844
4845 void
4846 ARDOUR_UI::midi_panic ()
4847 {
4848         if (_session) {
4849                 _session->midi_panic();
4850         }
4851 }
4852
4853 void
4854 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
4855 {
4856         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
4857         const char* end_big = "</span>";
4858         const char* start_mono = "<tt>";
4859         const char* end_mono = "</tt>";
4860
4861         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
4862                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
4863                                              "From now on, use the -2000 version with older versions of %3"),
4864                                            xml_path, backup_path, PROGRAM_NAME,
4865                                            start_big, end_big,
4866                                            start_mono, end_mono), true);
4867
4868         msg.run ();
4869 }
4870
4871
4872 void
4873 ARDOUR_UI::reset_peak_display ()
4874 {
4875         if (!_session || !_session->master_out() || !editor_meter) return;
4876         editor_meter->clear_meters();
4877         editor_meter_max_peak = -INFINITY;
4878         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
4879 }
4880
4881 void
4882 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
4883 {
4884         if (!_session || !_session->master_out()) return;
4885         if (group == _session->master_out()->route_group()) {
4886                 reset_peak_display ();
4887         }
4888 }
4889
4890 void
4891 ARDOUR_UI::reset_route_peak_display (Route* route)
4892 {
4893         if (!_session || !_session->master_out()) return;
4894         if (_session->master_out().get() == route) {
4895                 reset_peak_display ();
4896         }
4897 }
4898
4899 int
4900 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
4901 {
4902         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
4903         audio_midi_setup->set_position (WIN_POS_CENTER);
4904
4905         int response;
4906
4907         while (true) {
4908                 response = audio_midi_setup->run();
4909                 switch (response) {
4910                 case Gtk::RESPONSE_OK:
4911                         if (!AudioEngine::instance()->running()) {
4912                                 continue;
4913                         } else {
4914                                 return 0;
4915                         }
4916                         return 0;
4917                 default:
4918                         return -1;
4919                 }
4920         }
4921 }
4922
4923
4924 gint
4925 ARDOUR_UI::transport_numpad_timeout ()
4926 {
4927         _numpad_locate_happening = false;
4928         if (_numpad_timeout_connection.connected() )
4929                 _numpad_timeout_connection.disconnect();
4930         return 1;
4931 }
4932
4933 void
4934 ARDOUR_UI::transport_numpad_decimal ()
4935 {
4936         _numpad_timeout_connection.disconnect();
4937
4938         if (_numpad_locate_happening) {
4939                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
4940                 _numpad_locate_happening = false;
4941         } else {
4942                 _pending_locate_num = 0;
4943                 _numpad_locate_happening = true;
4944                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
4945         }
4946 }
4947
4948 void
4949 ARDOUR_UI::transport_numpad_event (int num)
4950 {
4951         if ( _numpad_locate_happening ) {
4952                 _pending_locate_num = _pending_locate_num*10 + num;
4953         } else {
4954                 switch (num) {
4955                         case 0:  toggle_roll(false, false);             break;
4956                         case 1:  transport_rewind(1);                           break;
4957                         case 2:  transport_forward(1);                          break;
4958                         case 3:  transport_record(true);                        break;
4959                         case 4:  toggle_session_auto_loop();            break;
4960                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
4961                         case 6:  toggle_punch();                                        break;
4962                         case 7:  toggle_click();                                break;
4963                         case 8:  toggle_auto_return();                  break;
4964                         case 9:  toggle_follow_edits();         break;
4965                 }
4966         }
4967 }
4968
4969 void
4970 ARDOUR_UI::set_flat_buttons ()
4971 {
4972         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
4973 }
4974
4975 void
4976 ARDOUR_UI::audioengine_became_silent ()
4977 {
4978         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
4979                            true,
4980                            Gtk::MESSAGE_WARNING,
4981                            Gtk::BUTTONS_NONE,
4982                            true);
4983
4984         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
4985
4986         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
4987         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
4988         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
4989         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
4990         Gtk::HBox pay_button_box;
4991         Gtk::HBox subscribe_button_box;
4992
4993         pay_button_box.pack_start (pay_button, true, false);
4994         subscribe_button_box.pack_start (subscribe_button, true, false);
4995
4996         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 */
4997
4998         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
4999         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5000
5001         msg.get_vbox()->pack_start (pay_label);
5002         msg.get_vbox()->pack_start (pay_button_box);
5003         msg.get_vbox()->pack_start (subscribe_label);
5004         msg.get_vbox()->pack_start (subscribe_button_box);
5005
5006         msg.get_vbox()->show_all ();
5007
5008         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5009         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5010         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5011
5012         int r = msg.run ();
5013
5014         switch (r) {
5015         case Gtk::RESPONSE_YES:
5016                 AudioEngine::instance()->reset_silence_countdown ();
5017                 break;
5018
5019         case Gtk::RESPONSE_NO:
5020                 /* save and quit */
5021                 save_state_canfail ("");
5022                 exit (0);
5023                 break;
5024
5025         case Gtk::RESPONSE_CANCEL:
5026         default:
5027                 /* don't reset, save session and exit */
5028                 break;
5029         }
5030 }
5031
5032 void
5033 ARDOUR_UI::hide_application ()
5034 {
5035     Application::instance ()-> hide ();
5036 }
5037
5038 void
5039 ARDOUR_UI::cancel_solo ()
5040 {
5041         if (_session) {
5042                 if (_session->soloing()) {
5043                         _session->set_solo (_session->get_routes(), false);
5044                 } else if (_session->listening()) {
5045                         _session->set_listen (_session->get_routes(), false);
5046                 }
5047
5048                 _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window
5049         }
5050 }