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