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