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