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