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