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