Hide lua script selector before showing lua parameter dialog.
[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; big_clock = 0;
667                 delete primary_clock; primary_clock = 0;
668                 delete secondary_clock; secondary_clock = 0;
669                 delete _process_thread; _process_thread = 0;
670                 delete meterbridge; meterbridge = 0;
671                 delete luawindow; luawindow = 0;
672                 delete editor; editor = 0;
673                 delete mixer; mixer = 0;
674                 delete nsm; nsm = 0;
675                 delete gui_object_state; gui_object_state = 0;
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 void
1810 ARDOUR_UI::session_add_midi_bus (RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
1811 {
1812
1813         if (_session == 0) {
1814                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1815                 return;
1816         }
1817
1818         try {
1819                 RouteList routes = _session->new_midi_route (route_group, how_many, name_template, instrument);
1820                 if (routes.size() != how_many) {
1821                         error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
1822                 }
1823
1824         }
1825         catch (...) {
1826                 MessageDialog msg (_main_window,
1827                                    string_compose (_("There are insufficient ports available\n\
1828 to create a new track or bus.\n\
1829 You should save %1, exit and\n\
1830 restart with more ports."), PROGRAM_NAME));
1831                 msg.run ();
1832         }
1833 }
1834
1835 void
1836 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
1837 {
1838         ChanCount one_midi_channel;
1839         one_midi_channel.set (DataType::MIDI, 1);
1840
1841         if (disk) {
1842                 session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, instrument);
1843         } else {
1844                 session_add_midi_bus (route_group, how_many, name_template, instrument);
1845         }
1846 }
1847
1848 void
1849 ARDOUR_UI::session_add_audio_route (
1850         bool track,
1851         int32_t input_channels,
1852         int32_t output_channels,
1853         ARDOUR::TrackMode mode,
1854         RouteGroup* route_group,
1855         uint32_t how_many,
1856         string const & name_template
1857         )
1858 {
1859         list<boost::shared_ptr<AudioTrack> > tracks;
1860         RouteList routes;
1861
1862         if (_session == 0) {
1863                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1864                 return;
1865         }
1866
1867         try {
1868                 if (track) {
1869                         tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
1870
1871                         if (tracks.size() != how_many) {
1872                                 error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
1873                                       << endmsg;
1874                         }
1875
1876                 } else {
1877
1878                         routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
1879
1880                         if (routes.size() != how_many) {
1881                                 error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
1882                                       << endmsg;
1883                         }
1884                 }
1885         }
1886
1887         catch (...) {
1888                 MessageDialog msg (_main_window,
1889                                    string_compose (_("There are insufficient ports available\n\
1890 to create a new track or bus.\n\
1891 You should save %1, exit and\n\
1892 restart with more ports."), PROGRAM_NAME));
1893                 pop_back_splash (msg);
1894                 msg.run ();
1895         }
1896 }
1897
1898 void
1899 ARDOUR_UI::transport_goto_start ()
1900 {
1901         if (_session) {
1902                 _session->goto_start();
1903
1904                 /* force displayed area in editor to start no matter
1905                    what "follow playhead" setting is.
1906                 */
1907
1908                 if (editor) {
1909                         editor->center_screen (_session->current_start_frame ());
1910                 }
1911         }
1912 }
1913
1914 void
1915 ARDOUR_UI::transport_goto_zero ()
1916 {
1917         if (_session) {
1918                 _session->request_locate (0);
1919
1920                 /* force displayed area in editor to start no matter
1921                    what "follow playhead" setting is.
1922                 */
1923
1924                 if (editor) {
1925                         editor->reset_x_origin (0);
1926                 }
1927         }
1928 }
1929
1930 void
1931 ARDOUR_UI::transport_goto_wallclock ()
1932 {
1933         if (_session && editor) {
1934
1935                 time_t now;
1936                 struct tm tmnow;
1937                 framepos_t frames;
1938
1939                 time (&now);
1940                 localtime_r (&now, &tmnow);
1941
1942                 framecnt_t frame_rate = _session->frame_rate();
1943
1944                 if (frame_rate == 0) {
1945                         /* no frame rate available */
1946                         return;
1947                 }
1948
1949                 frames = tmnow.tm_hour * (60 * 60 * frame_rate);
1950                 frames += tmnow.tm_min * (60 * frame_rate);
1951                 frames += tmnow.tm_sec * frame_rate;
1952
1953                 _session->request_locate (frames, _session->transport_rolling ());
1954
1955                 /* force displayed area in editor to start no matter
1956                    what "follow playhead" setting is.
1957                 */
1958
1959                 if (editor) {
1960                         editor->center_screen (frames);
1961                 }
1962         }
1963 }
1964
1965 void
1966 ARDOUR_UI::transport_goto_end ()
1967 {
1968         if (_session) {
1969                 framepos_t const frame = _session->current_end_frame();
1970                 _session->request_locate (frame);
1971
1972                 /* force displayed area in editor to start no matter
1973                    what "follow playhead" setting is.
1974                 */
1975
1976                 if (editor) {
1977                         editor->center_screen (frame);
1978                 }
1979         }
1980 }
1981
1982 void
1983 ARDOUR_UI::transport_stop ()
1984 {
1985         if (!_session) {
1986                 return;
1987         }
1988
1989         if (_session->is_auditioning()) {
1990                 _session->cancel_audition ();
1991                 return;
1992         }
1993
1994         _session->request_stop (false, true);
1995 }
1996
1997 /** Check if any tracks are record enabled. If none are, record enable all of them.
1998  * @return true if track record-enabled status was changed, false otherwise.
1999  */
2000 bool
2001 ARDOUR_UI::trx_record_enable_all_tracks ()
2002 {
2003         if (!_session) {
2004                 return false;
2005         }
2006
2007         boost::shared_ptr<RouteList> rl = _session->get_tracks ();
2008         bool none_record_enabled = true;
2009
2010         for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
2011                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
2012                 assert (t);
2013
2014                 if (t->record_enabled()) {
2015                         none_record_enabled = false;
2016                         break;
2017                 }
2018         }
2019
2020         if (none_record_enabled) {
2021                 _session->set_record_enabled (rl, true, Session::rt_cleanup);
2022         }
2023
2024         return none_record_enabled;
2025 }
2026
2027 void
2028 ARDOUR_UI::transport_record (bool roll)
2029 {
2030         if (_session) {
2031                 switch (_session->record_status()) {
2032                 case Session::Disabled:
2033                         if (_session->ntracks() == 0) {
2034                                 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."));
2035                                 msg.run ();
2036                                 return;
2037                         }
2038                         if (Profile->get_trx()) {
2039                                 roll = trx_record_enable_all_tracks ();
2040                         }
2041                         _session->maybe_enable_record ();
2042                         if (roll) {
2043                                 transport_roll ();
2044                         }
2045                         break;
2046                 case Session::Recording:
2047                         if (roll) {
2048                                 _session->request_stop();
2049                         } else {
2050                                 _session->disable_record (false, true);
2051                         }
2052                         break;
2053
2054                 case Session::Enabled:
2055                         _session->disable_record (false, true);
2056                 }
2057         }
2058 }
2059
2060 void
2061 ARDOUR_UI::transport_roll ()
2062 {
2063         if (!_session) {
2064                 return;
2065         }
2066
2067         if (_session->is_auditioning()) {
2068                 return;
2069         }
2070
2071 #if 0
2072         if (_session->config.get_external_sync()) {
2073                 switch (Config->get_sync_source()) {
2074                 case Engine:
2075                         break;
2076                 default:
2077                         /* transport controlled by the master */
2078                         return;
2079                 }
2080         }
2081 #endif
2082
2083         bool rolling = _session->transport_rolling();
2084
2085         if (_session->get_play_loop()) {
2086
2087                 /* If loop playback is not a mode, then we should cancel
2088                    it when this action is requested. If it is a mode
2089                    we just leave it in place.
2090                 */
2091
2092                 if (!Config->get_loop_is_mode()) {
2093                         /* XXX it is not possible to just leave seamless loop and keep
2094                            playing at present (nov 4th 2009)
2095                         */
2096                         if (!Config->get_seamless_loop()) {
2097                                 /* stop loop playback and stop rolling */
2098                                 _session->request_play_loop (false, true);
2099                         } else if (rolling) {
2100                                 /* stop loop playback but keep rolling */
2101                                 _session->request_play_loop (false, false);
2102                         }
2103                 }
2104
2105         } else if (_session->get_play_range () ) {
2106                 /* stop playing a range if we currently are */
2107                 _session->request_play_range (0, true);
2108         }
2109
2110         if (!rolling) {
2111                 _session->request_transport_speed (1.0f);
2112         }
2113 }
2114
2115 bool
2116 ARDOUR_UI::get_smart_mode() const
2117 {
2118         return ( editor->get_smart_mode() );
2119 }
2120
2121
2122 void
2123 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
2124 {
2125         if (!_session) {
2126                 return;
2127         }
2128
2129         if (_session->is_auditioning()) {
2130                 _session->cancel_audition ();
2131                 return;
2132         }
2133
2134         if (_session->config.get_external_sync()) {
2135                 switch (Config->get_sync_source()) {
2136                 case Engine:
2137                         break;
2138                 default:
2139                         /* transport controlled by the master */
2140                         return;
2141                 }
2142         }
2143
2144         bool rolling = _session->transport_rolling();
2145         bool affect_transport = true;
2146
2147         if (rolling && roll_out_of_bounded_mode) {
2148                 /* drop out of loop/range playback but leave transport rolling */
2149                 if (_session->get_play_loop()) {
2150                         if (_session->actively_recording()) {
2151
2152                                 /* just stop using the loop, then actually stop
2153                                  * below
2154                                  */
2155                                 _session->request_play_loop (false, affect_transport);
2156
2157                         } else {
2158                                 if (Config->get_seamless_loop()) {
2159                                         /* the disk buffers contain copies of the loop - we can't
2160                                            just keep playing, so stop the transport. the user
2161                                            can restart as they wish.
2162                                         */
2163                                         affect_transport = true;
2164                                 } else {
2165                                         /* disk buffers are normal, so we can keep playing */
2166                                         affect_transport = false;
2167                                 }
2168                                 _session->request_play_loop (false, affect_transport);
2169                         }
2170                 } else if (_session->get_play_range ()) {
2171                         affect_transport = false;
2172                         _session->request_play_range (0, true);
2173                 }
2174         }
2175
2176         if (affect_transport) {
2177                 if (rolling) {
2178                         _session->request_stop (with_abort, true);
2179                 } else {
2180                         /* the only external sync condition we can be in here
2181                          * would be Engine (JACK) sync, in which case we still
2182                          * want to do this.
2183                          */
2184
2185                         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
2186                                 _session->request_play_range (&editor->get_selection().time, true);
2187                                 _session->set_requested_return_frame( editor->get_selection().time.front().start );  //force an auto-return here
2188                         }
2189                         _session->request_transport_speed (1.0f);
2190                 }
2191         }
2192 }
2193
2194 void
2195 ARDOUR_UI::toggle_session_auto_loop ()
2196 {
2197         if (!_session) {
2198                 return;
2199         }
2200
2201         Location * looploc = _session->locations()->auto_loop_location();
2202
2203         if (!looploc) {
2204                 return;
2205         }
2206
2207         if (_session->get_play_loop()) {
2208
2209                 /* looping enabled, our job is to disable it */
2210
2211                 _session->request_play_loop (false);
2212
2213         } else {
2214
2215                 /* looping not enabled, our job is to enable it.
2216
2217                    loop-is-NOT-mode: this action always starts the transport rolling.
2218                    loop-IS-mode:     this action simply sets the loop play mechanism, but
2219                                         does not start transport.
2220                 */
2221                 if (Config->get_loop_is_mode()) {
2222                         _session->request_play_loop (true, false);
2223                 } else {
2224                         _session->request_play_loop (true, true);
2225                 }
2226         }
2227
2228         //show the loop markers
2229         looploc->set_hidden (false, this);
2230 }
2231
2232 void
2233 ARDOUR_UI::transport_play_selection ()
2234 {
2235         if (!_session) {
2236                 return;
2237         }
2238
2239         editor->play_selection ();
2240 }
2241
2242 void
2243 ARDOUR_UI::transport_play_preroll ()
2244 {
2245         if (!_session) {
2246                 return;
2247         }
2248         editor->play_with_preroll ();
2249 }
2250
2251 void
2252 ARDOUR_UI::transport_rewind (int option)
2253 {
2254         float current_transport_speed;
2255
2256         if (_session) {
2257                 current_transport_speed = _session->transport_speed();
2258
2259                 if (current_transport_speed >= 0.0f) {
2260                         switch (option) {
2261                         case 0:
2262                                 _session->request_transport_speed (-1.0f);
2263                                 break;
2264                         case 1:
2265                                 _session->request_transport_speed (-4.0f);
2266                                 break;
2267                         case -1:
2268                                 _session->request_transport_speed (-0.5f);
2269                                 break;
2270                         }
2271                 } else {
2272                         /* speed up */
2273                         _session->request_transport_speed (current_transport_speed * 1.5f);
2274                 }
2275         }
2276 }
2277
2278 void
2279 ARDOUR_UI::transport_forward (int option)
2280 {
2281         if (!_session) {
2282                 return;
2283         }
2284
2285         float current_transport_speed = _session->transport_speed();
2286
2287         if (current_transport_speed <= 0.0f) {
2288                 switch (option) {
2289                 case 0:
2290                         _session->request_transport_speed (1.0f);
2291                         break;
2292                 case 1:
2293                         _session->request_transport_speed (4.0f);
2294                         break;
2295                 case -1:
2296                         _session->request_transport_speed (0.5f);
2297                         break;
2298                 }
2299         } else {
2300                 /* speed up */
2301                 _session->request_transport_speed (current_transport_speed * 1.5f);
2302         }
2303 }
2304
2305 void
2306 ARDOUR_UI::toggle_record_enable (uint32_t rid)
2307 {
2308         if (!_session) {
2309                 return;
2310         }
2311
2312         boost::shared_ptr<Route> r;
2313
2314         if ((r = _session->route_by_remote_id (rid)) != 0) {
2315
2316                 boost::shared_ptr<Track> t;
2317
2318                 if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2319                         t->set_record_enabled (!t->record_enabled(), Controllable::UseGroup);
2320                 }
2321         }
2322 }
2323
2324 void
2325 ARDOUR_UI::map_transport_state ()
2326 {
2327         if (!_session) {
2328                 auto_loop_button.unset_active_state ();
2329                 play_selection_button.unset_active_state ();
2330                 roll_button.unset_active_state ();
2331                 stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
2332                 return;
2333         }
2334
2335         shuttle_box->map_transport_state ();
2336
2337         float sp = _session->transport_speed();
2338
2339         if (sp != 0.0f) {
2340
2341                 /* we're rolling */
2342
2343                 if (_session->get_play_range()) {
2344
2345                         play_selection_button.set_active_state (Gtkmm2ext::ExplicitActive);
2346                         roll_button.unset_active_state ();
2347                         auto_loop_button.unset_active_state ();
2348
2349                 } else if (_session->get_play_loop ()) {
2350
2351                         auto_loop_button.set_active (true);
2352                         play_selection_button.set_active (false);
2353                         if (Config->get_loop_is_mode()) {
2354                                 roll_button.set_active (true);
2355                         } else {
2356                                 roll_button.set_active (false);
2357                         }
2358
2359                 } else {
2360
2361                         roll_button.set_active (true);
2362                         play_selection_button.set_active (false);
2363                         auto_loop_button.set_active (false);
2364                 }
2365
2366                 if (UIConfiguration::instance().get_follow_edits() && !_session->config.get_external_sync()) {
2367                         /* light up both roll and play-selection if they are joined */
2368                         roll_button.set_active (true);
2369                         play_selection_button.set_active (true);
2370                 }
2371
2372                 stop_button.set_active (false);
2373
2374         } else {
2375
2376                 stop_button.set_active (true);
2377                 roll_button.set_active (false);
2378                 play_selection_button.set_active (false);
2379                 if (Config->get_loop_is_mode ()) {
2380                         auto_loop_button.set_active (_session->get_play_loop());
2381                 } else {
2382                         auto_loop_button.set_active (false);
2383                 }
2384                 update_disk_space ();
2385         }
2386 }
2387
2388 void
2389 ARDOUR_UI::blink_handler (bool blink_on)
2390 {
2391         transport_rec_enable_blink (blink_on);
2392         solo_blink (blink_on);
2393         sync_blink (blink_on);
2394         audition_blink (blink_on);
2395         feedback_blink (blink_on);
2396         error_blink (blink_on);
2397 }
2398
2399 void
2400 ARDOUR_UI::update_clocks ()
2401 {
2402         if (!_session) return;
2403
2404         if (editor && !editor->dragging_playhead()) {
2405                 Clock (_session->audible_frame(), false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); /* EMIT_SIGNAL */
2406         }
2407 }
2408
2409 void
2410 ARDOUR_UI::start_clocking ()
2411 {
2412         if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2413                 clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2414         } else {
2415                 clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2416         }
2417 }
2418
2419 void
2420 ARDOUR_UI::stop_clocking ()
2421 {
2422         clock_signal_connection.disconnect ();
2423 }
2424
2425 bool
2426 ARDOUR_UI::save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar)
2427 {
2428         char buf[256];
2429
2430         snprintf (buf, sizeof (buf), _("Copied %" PRId64 " of %" PRId64), cnt, total);
2431
2432         label->set_text (buf);
2433         bar->set_fraction (fraction);
2434
2435         /* process events, redraws, etc. */
2436
2437         while (gtk_events_pending()) {
2438                 gtk_main_iteration ();
2439         }
2440
2441         return true; /* continue with save-as */
2442 }
2443
2444 void
2445 ARDOUR_UI::save_session_as ()
2446 {
2447         if (!_session) {
2448                 return;
2449         }
2450
2451         if (!save_as_dialog) {
2452                 save_as_dialog = new SaveAsDialog;
2453         }
2454
2455         save_as_dialog->set_name (_session->name());
2456
2457         int response = save_as_dialog->run ();
2458
2459         save_as_dialog->hide ();
2460
2461         switch (response) {
2462         case Gtk::RESPONSE_OK:
2463                 break;
2464         default:
2465                 return;
2466         }
2467
2468
2469         Session::SaveAs sa;
2470
2471         sa.new_parent_folder = save_as_dialog->new_parent_folder ();
2472         sa.new_name = save_as_dialog->new_name ();
2473         sa.switch_to = save_as_dialog->switch_to();
2474         sa.copy_media = save_as_dialog->copy_media();
2475         sa.copy_external = save_as_dialog->copy_external();
2476         sa.include_media = save_as_dialog->include_media ();
2477
2478         /* Only bother with a progress dialog if we're going to copy
2479            media into the save-as target. Without that choice, this
2480            will be very fast because we're only talking about a few kB's to
2481            perhaps a couple of MB's of data.
2482         */
2483
2484         ArdourDialog progress_dialog (_("Save As"), true);
2485
2486         if (sa.include_media && sa.copy_media) {
2487
2488                 Gtk::Label label;
2489                 Gtk::ProgressBar progress_bar;
2490
2491                 progress_dialog.get_vbox()->pack_start (label);
2492                 progress_dialog.get_vbox()->pack_start (progress_bar);
2493                 label.show ();
2494                 progress_bar.show ();
2495
2496                 /* this signal will be emitted from within this, the calling thread,
2497                  * after every file is copied. It provides information on percentage
2498                  * complete (in terms of total data to copy), the number of files
2499                  * copied so far, and the total number to copy.
2500                  */
2501
2502                 ScopedConnection c;
2503
2504                 sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
2505
2506                 progress_dialog.show_all ();
2507                 progress_dialog.present ();
2508         }
2509
2510         if (_session->save_as (sa)) {
2511                 /* ERROR MESSAGE */
2512                 MessageDialog msg (string_compose (_("Save As failed: %1"), sa.failure_message));
2513                 msg.run ();
2514         }
2515
2516         if (!sa.include_media) {
2517                 unload_session (false);
2518                 load_session (sa.final_session_folder_name, sa.new_name);
2519         }
2520 }
2521
2522 void
2523 ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
2524 {
2525                 char timebuf[128];
2526                 time_t n;
2527                 struct tm local_time;
2528
2529                 time (&n);
2530                 localtime_r (&n, &local_time);
2531                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2532
2533                 save_state (timebuf, switch_to_it);
2534 }
2535
2536
2537 bool
2538 ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
2539 {
2540         string snapname;
2541
2542         prompter.get_result (snapname);
2543
2544         bool do_save = (snapname.length() != 0);
2545
2546         if (do_save) {
2547                 char illegal = Session::session_name_is_legal(snapname);
2548                 if (illegal) {
2549                         MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2550                                              "snapshot names may not contain a '%1' character"), illegal));
2551                         msg.run ();
2552                         return false;
2553                 }
2554         }
2555
2556         vector<std::string> p;
2557         get_state_files_in_directory (_session->session_directory().root_path(), p);
2558         vector<string> n = get_file_names_no_extension (p);
2559
2560         if (find (n.begin(), n.end(), snapname) != n.end()) {
2561
2562                 do_save = overwrite_file_dialog (prompter,
2563                                                  _("Confirm Snapshot Overwrite"),
2564                                                  _("A snapshot already exists with that name. Do you want to overwrite it?"));
2565         }
2566
2567         if (do_save) {
2568                 save_state (snapname, switch_to_it);
2569         }
2570         else {
2571                 return false;
2572         }
2573
2574         return true;
2575 }
2576
2577
2578 /** Ask the user for the name of a new snapshot and then take it.
2579  */
2580
2581 void
2582 ARDOUR_UI::snapshot_session (bool switch_to_it)
2583 {
2584         ArdourPrompter prompter (true);
2585
2586         prompter.set_name ("Prompter");
2587         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2588         if (switch_to_it) {
2589                 prompter.set_title (_("Save as..."));
2590                 prompter.set_prompt (_("New session name"));
2591         } else {
2592                 prompter.set_title (_("Take Snapshot"));
2593                 prompter.set_prompt (_("Name of new snapshot"));
2594         }
2595
2596         if (switch_to_it) {
2597                 prompter.set_initial_text (_session->snap_name());
2598         } else {
2599                 char timebuf[128];
2600                 time_t n;
2601                 struct tm local_time;
2602
2603                 time (&n);
2604                 localtime_r (&n, &local_time);
2605                 strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
2606                 prompter.set_initial_text (timebuf);
2607         }
2608
2609         bool finished = false;
2610         while (!finished) {
2611                 switch (prompter.run()) {
2612                 case RESPONSE_ACCEPT:
2613                 {
2614                         finished = process_snapshot_session_prompter (prompter, switch_to_it);
2615                         break;
2616                 }
2617
2618                 default:
2619                         finished = true;
2620                         break;
2621                 }
2622         }
2623 }
2624
2625 /** Ask the user for a new session name and then rename the session to it.
2626  */
2627
2628 void
2629 ARDOUR_UI::rename_session ()
2630 {
2631         if (!_session) {
2632                 return;
2633         }
2634
2635         ArdourPrompter prompter (true);
2636         string name;
2637
2638         prompter.set_name ("Prompter");
2639         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2640         prompter.set_title (_("Rename Session"));
2641         prompter.set_prompt (_("New session name"));
2642
2643   again:
2644         switch (prompter.run()) {
2645         case RESPONSE_ACCEPT:
2646         {
2647                 prompter.get_result (name);
2648
2649                 bool do_rename = (name.length() != 0);
2650
2651                 if (do_rename) {
2652                         char illegal = Session::session_name_is_legal (name);
2653
2654                         if (illegal) {
2655                                 MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
2656                                                                      "session names may not contain a '%1' character"), illegal));
2657                                 msg.run ();
2658                                 goto again;
2659                         }
2660
2661                         switch (_session->rename (name)) {
2662                         case -1: {
2663                                 MessageDialog msg (_("That name is already in use by another directory/folder. Please try again."));
2664                                 msg.set_position (WIN_POS_MOUSE);
2665                                 msg.run ();
2666                                 goto again;
2667                                 break;
2668                         }
2669                         case 0:
2670                                 break;
2671                         default: {
2672                                 MessageDialog msg (_("Renaming this session failed.\nThings could be seriously messed up at this point"));
2673                                 msg.set_position (WIN_POS_MOUSE);
2674                                 msg.run ();
2675                                 break;
2676                         }
2677                         }
2678                 }
2679
2680                 break;
2681         }
2682
2683         default:
2684                 break;
2685         }
2686 }
2687
2688 void
2689 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2690 {
2691         if (!_session || _session->deletion_in_progress()) {
2692                 return;
2693         }
2694
2695         XMLNode* node = new XMLNode (X_("UI"));
2696
2697         WM::Manager::instance().add_state (*node);
2698
2699         node->add_child_nocopy (gui_object_state->get_state());
2700
2701         _session->add_extra_xml (*node);
2702
2703         if (export_video_dialog) {
2704                 _session->add_extra_xml (export_video_dialog->get_state());
2705         }
2706
2707         save_state_canfail (name, switch_to_it);
2708 }
2709
2710 int
2711 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2712 {
2713         if (_session) {
2714                 int ret;
2715
2716                 if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2717                         return ret;
2718                 }
2719         }
2720
2721         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2722         return 0;
2723 }
2724
2725 void
2726 ARDOUR_UI::primary_clock_value_changed ()
2727 {
2728         if (_session) {
2729                 _session->request_locate (primary_clock->current_time ());
2730         }
2731 }
2732
2733 void
2734 ARDOUR_UI::big_clock_value_changed ()
2735 {
2736         if (_session) {
2737                 _session->request_locate (big_clock->current_time ());
2738         }
2739 }
2740
2741 void
2742 ARDOUR_UI::secondary_clock_value_changed ()
2743 {
2744         if (_session) {
2745                 _session->request_locate (secondary_clock->current_time ());
2746         }
2747 }
2748
2749 void
2750 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
2751 {
2752         if (_session == 0) {
2753                 return;
2754         }
2755
2756         if (_session->step_editing()) {
2757                 return;
2758         }
2759
2760         Session::RecordState const r = _session->record_status ();
2761         bool const h = _session->have_rec_enabled_track ();
2762
2763         if (r == Session::Enabled || (r == Session::Recording && !h)) {
2764                 if (onoff) {
2765                         rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2766                 } else {
2767                         rec_button.set_active_state (Gtkmm2ext::Off);
2768                 }
2769         } else if (r == Session::Recording && h) {
2770                 rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
2771         } else {
2772                 rec_button.unset_active_state ();
2773         }
2774 }
2775
2776 bool
2777 ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
2778 {
2779         string name;
2780
2781         prompter.get_result (name);
2782
2783         if (name.length()) {
2784                 int failed = _session->save_template (name);
2785
2786                 if (failed == -2) { /* file already exists. */
2787                         bool overwrite = overwrite_file_dialog (prompter,
2788                                                                 _("Confirm Template Overwrite"),
2789                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
2790
2791                         if (overwrite) {
2792                                 _session->save_template (name, true);
2793                         }
2794                         else {
2795                                 return false;
2796                         }
2797                 }
2798         }
2799
2800         return true;
2801 }
2802
2803 void
2804 ARDOUR_UI::save_template ()
2805 {
2806         ArdourPrompter prompter (true);
2807
2808         if (!check_audioengine (_main_window)) {
2809                 return;
2810         }
2811
2812         prompter.set_name (X_("Prompter"));
2813         prompter.set_title (_("Save Template"));
2814         prompter.set_prompt (_("Name for template:"));
2815         prompter.set_initial_text(_session->name() + _("-template"));
2816         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
2817
2818         bool finished = false;
2819         while (!finished) {
2820                 switch (prompter.run()) {
2821                 case RESPONSE_ACCEPT:
2822                         finished = process_save_template_prompter (prompter);
2823                         break;
2824
2825                 default:
2826                         finished = true;
2827                         break;
2828                 }
2829         }
2830 }
2831
2832 void
2833 ARDOUR_UI::edit_metadata ()
2834 {
2835         SessionMetadataEditor dialog;
2836         dialog.set_session (_session);
2837         dialog.grab_focus ();
2838         dialog.run ();
2839 }
2840
2841 void
2842 ARDOUR_UI::import_metadata ()
2843 {
2844         SessionMetadataImporter dialog;
2845         dialog.set_session (_session);
2846         dialog.run ();
2847 }
2848
2849 bool
2850 ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path)
2851 {
2852         std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2853
2854         MessageDialog msg (str,
2855                            false,
2856                            Gtk::MESSAGE_WARNING,
2857                            Gtk::BUTTONS_YES_NO,
2858                            true);
2859
2860
2861         msg.set_name (X_("OpenExistingDialog"));
2862         msg.set_title (_("Open Existing Session"));
2863         msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
2864         msg.set_position (Gtk::WIN_POS_CENTER);
2865         pop_back_splash (msg);
2866
2867         switch (msg.run()) {
2868         case RESPONSE_YES:
2869                 return true;
2870                 break;
2871         }
2872         return false;
2873 }
2874
2875 int
2876 ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name)
2877 {
2878         BusProfile bus_profile;
2879
2880         if (nsm) {
2881
2882                 bus_profile.master_out_channels = 2;
2883                 bus_profile.input_ac = AutoConnectPhysical;
2884                 bus_profile.output_ac = AutoConnectMaster;
2885                 bus_profile.requested_physical_in = 0; // use all available
2886                 bus_profile.requested_physical_out = 0; // use all available
2887
2888         } else {
2889
2890                 /* get settings from advanced section of NSD */
2891
2892                 if (sd.create_master_bus()) {
2893                         bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
2894                 } else {
2895                         bus_profile.master_out_channels = 0;
2896                 }
2897
2898                 if (sd.connect_inputs()) {
2899                         bus_profile.input_ac = AutoConnectPhysical;
2900                 } else {
2901                         bus_profile.input_ac = AutoConnectOption (0);
2902                 }
2903
2904                 bus_profile.output_ac = AutoConnectOption (0);
2905
2906                 if (sd.connect_outputs ()) {
2907                         if (sd.connect_outs_to_master()) {
2908                                 bus_profile.output_ac = AutoConnectMaster;
2909                         } else if (sd.connect_outs_to_physical()) {
2910                                 bus_profile.output_ac = AutoConnectPhysical;
2911                         }
2912                 }
2913
2914                 bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
2915                 bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
2916         }
2917
2918         if (build_session (session_path, session_name, bus_profile)) {
2919                 return -1;
2920         }
2921
2922         return 0;
2923 }
2924
2925 void
2926 ARDOUR_UI::load_from_application_api (const std::string& path)
2927 {
2928         ARDOUR_COMMAND_LINE::session_name = path;
2929         /* Cancel SessionDialog if it's visible to make OSX delegates work.
2930          *
2931          * ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
2932          * race-condition:
2933          *  - ShouldLoad does not arrive in time, ARDOUR_COMMAND_LINE::session_name is empty:
2934          *    -> ARDOUR_UI::get_session_parameters starts a SessionDialog.
2935          *  - ShouldLoad signal arrives, this function is called and sets ARDOUR_COMMAND_LINE::session_name
2936          *    -> SessionDialog is not displayed
2937          */
2938
2939         if (_session_dialog) {
2940                 std::string session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
2941                 std::string session_path = path;
2942                 if (Glib::file_test (session_path, Glib::FILE_TEST_IS_REGULAR)) {
2943                         session_path = Glib::path_get_dirname (session_path);
2944                 }
2945                 // signal the existing dialog in ARDOUR_UI::get_session_parameters()
2946                 _session_dialog->set_provided_session (session_name, session_path);
2947                 _session_dialog->response (RESPONSE_NONE);
2948                 _session_dialog->hide();
2949                 return;
2950         }
2951
2952         int rv;
2953         if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2954                 /* /path/to/foo => /path/to/foo, foo */
2955                 rv = load_session (path, basename_nosuffix (path));
2956         } else {
2957                 /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2958                 rv =load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2959         }
2960
2961         // if load_session fails -> pop up SessionDialog.
2962         if (rv) {
2963                 ARDOUR_COMMAND_LINE::session_name = "";
2964
2965                 if (get_session_parameters (true, false)) {
2966                         exit (1);
2967                 }
2968         }
2969 }
2970
2971 /** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
2972 int
2973 ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
2974 {
2975         string session_name;
2976         string session_path;
2977         string template_name;
2978         int ret = -1;
2979         bool likely_new = false;
2980         bool cancel_not_quit;
2981
2982         /* deal with any existing DIRTY session now, rather than later. don't
2983          * treat a non-dirty session this way, so that it stays visible
2984          * as we bring up the new session dialog.
2985          */
2986
2987         if (_session && ARDOUR_UI::instance()->video_timeline) {
2988                 ARDOUR_UI::instance()->video_timeline->sync_session_state();
2989         }
2990
2991         /* if there is already a session, relabel the button
2992            on the SessionDialog so that we don't Quit directly
2993         */
2994         cancel_not_quit = (_session != 0);
2995
2996         if (_session && _session->dirty()) {
2997                 if (unload_session (false)) {
2998                         /* unload cancelled by user */
2999                         return 0;
3000                 }
3001                 ARDOUR_COMMAND_LINE::session_name = "";
3002         }
3003
3004         if (!load_template.empty()) {
3005                 should_be_new = true;
3006                 template_name = load_template;
3007         }
3008
3009         session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name);
3010         session_path = ARDOUR_COMMAND_LINE::session_name;
3011
3012         if (!session_path.empty()) {
3013                 if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) {
3014                         if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
3015                                 /* session/snapshot file, change path to be dir */
3016                                 session_path = Glib::path_get_dirname (session_path);
3017                         }
3018                 }
3019         }
3020
3021         SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit);
3022
3023         _session_dialog = &session_dialog;
3024         while (ret != 0) {
3025
3026                 if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
3027
3028                         /* if they named a specific statefile, use it, otherwise they are
3029                            just giving a session folder, and we want to use it as is
3030                            to find the session.
3031                         */
3032
3033                         string::size_type suffix = ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix);
3034
3035                         if (suffix != string::npos) {
3036                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
3037                                 session_name = ARDOUR_COMMAND_LINE::session_name.substr (0, suffix);
3038                                 session_name = Glib::path_get_basename (session_name);
3039                         } else {
3040                                 session_path = ARDOUR_COMMAND_LINE::session_name;
3041                                 session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
3042                         }
3043                 } else {
3044                         session_path = "";
3045                         session_name = "";
3046                         session_dialog.clear_given ();
3047                 }
3048
3049                 if (should_be_new || session_name.empty()) {
3050                         /* need the dialog to get info from user */
3051
3052                         cerr << "run dialog\n";
3053
3054                         switch (session_dialog.run()) {
3055                         case RESPONSE_ACCEPT:
3056                                 break;
3057                         case RESPONSE_NONE:
3058                                 /* this is used for async * app->ShouldLoad(). */
3059                                 continue; // while loop
3060                                 break;
3061                         default:
3062                                 if (quit_on_cancel) {
3063                                         // JE - Currently (July 2014) this section can only get reached if the
3064                                         // user quits from the main 'Session Setup' dialog (i.e. reaching this
3065                                         // point does NOT indicate an abnormal termination). Therefore, let's
3066                                         // behave gracefully (i.e. let's do some cleanup) before we call exit()
3067                                         ARDOUR::cleanup ();
3068                                         pthread_cancel_all ();
3069
3070                                         exit (1);
3071                                 } else {
3072                                         return ret;
3073                                 }
3074                         }
3075
3076                         session_dialog.hide ();
3077                 }
3078
3079                 /* if we run the startup dialog again, offer more than just "new session" */
3080
3081                 should_be_new = false;
3082
3083                 session_name = session_dialog.session_name (likely_new);
3084                 session_path = session_dialog.session_folder ();
3085
3086                 if (nsm) {
3087                         likely_new = true;
3088                 }
3089
3090                 string::size_type suffix = session_name.find (statefile_suffix);
3091
3092                 if (suffix != string::npos) {
3093                         session_name = session_name.substr (0, suffix);
3094                 }
3095
3096                 /* this shouldn't happen, but we catch it just in case it does */
3097
3098                 if (session_name.empty()) {
3099                         continue;
3100                 }
3101
3102                 if (session_dialog.use_session_template()) {
3103                         template_name = session_dialog.session_template_name();
3104                         _session_is_new = true;
3105                 }
3106
3107                 if (session_name[0] == G_DIR_SEPARATOR ||
3108 #ifdef PLATFORM_WINDOWS
3109                     (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
3110 #else
3111                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
3112                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
3113 #endif
3114                          )
3115                 {
3116
3117                         /* absolute path or cwd-relative path specified for session name: infer session folder
3118                            from what was given.
3119                         */
3120
3121                         session_path = Glib::path_get_dirname (session_name);
3122                         session_name = Glib::path_get_basename (session_name);
3123
3124                 } else {
3125
3126                         session_path = session_dialog.session_folder();
3127
3128                         char illegal = Session::session_name_is_legal (session_name);
3129
3130                         if (illegal) {
3131                                 MessageDialog msg (session_dialog,
3132                                                    string_compose (_("To ensure compatibility with various systems\n"
3133                                                                      "session names may not contain a '%1' character"),
3134                                                                    illegal));
3135                                 msg.run ();
3136                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3137                                 continue;
3138                         }
3139                 }
3140
3141                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
3142
3143
3144                         if (likely_new && !nsm) {
3145
3146                                 std::string existing = Glib::build_filename (session_path, session_name);
3147
3148                                 if (!ask_about_loading_existing_session (existing)) {
3149                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3150                                         continue;
3151                                 }
3152                         }
3153
3154                         _session_is_new = false;
3155
3156                 } else {
3157
3158                         if (!likely_new) {
3159                                 pop_back_splash (session_dialog);
3160                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
3161                                 msg.run ();
3162                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3163                                 continue;
3164                         }
3165
3166                         char illegal = Session::session_name_is_legal(session_name);
3167
3168                         if (illegal) {
3169                                 pop_back_splash (session_dialog);
3170                                 MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
3171                                                                                     "session names may not contain a '%1' character"), illegal));
3172                                 msg.run ();
3173                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
3174                                 continue;
3175                         }
3176
3177                         _session_is_new = true;
3178                 }
3179
3180                 if (likely_new && template_name.empty()) {
3181
3182                         ret = build_session_from_dialog (session_dialog, session_path, session_name);
3183
3184                 } else {
3185
3186                         ret = load_session (session_path, session_name, template_name);
3187
3188                         if (ret == -2) {
3189                                 /* not connected to the AudioEngine, so quit to avoid an infinite loop */
3190                                 exit (1);
3191                         }
3192
3193                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
3194                                 _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
3195                                 exit (1);
3196                         }
3197
3198                         /* clear this to avoid endless attempts to load the
3199                            same session.
3200                         */
3201
3202                         ARDOUR_COMMAND_LINE::session_name = "";
3203                 }
3204         }
3205
3206         _session_dialog = NULL;
3207
3208         return ret;
3209 }
3210
3211 void
3212 ARDOUR_UI::close_session()
3213 {
3214         if (!check_audioengine (_main_window)) {
3215                 return;
3216         }
3217
3218         if (unload_session (true)) {
3219                 return;
3220         }
3221
3222         ARDOUR_COMMAND_LINE::session_name = "";
3223
3224         if (get_session_parameters (true, false)) {
3225                 exit (1);
3226         }
3227 }
3228
3229 /** @param snap_name Snapshot name (without .ardour suffix).
3230  *  @return -2 if the load failed because we are not connected to the AudioEngine.
3231  */
3232 int
3233 ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
3234 {
3235         Session *new_session;
3236         int unload_status;
3237         int retval = -1;
3238
3239         if (_session) {
3240                 unload_status = unload_session ();
3241
3242                 if (unload_status < 0) {
3243                         goto out;
3244                 } else if (unload_status > 0) {
3245                         retval = 0;
3246                         goto out;
3247                 }
3248         }
3249
3250         session_loaded = false;
3251
3252         loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME));
3253
3254         try {
3255                 new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template);
3256         }
3257
3258         /* this one is special */
3259
3260         catch (AudioEngine::PortRegistrationFailure& err) {
3261
3262                 MessageDialog msg (err.what(),
3263                                    true,
3264                                    Gtk::MESSAGE_INFO,
3265                                    Gtk::BUTTONS_CLOSE);
3266
3267                 msg.set_title (_("Port Registration Error"));
3268                 msg.set_secondary_text (_("Click the Close button to try again."));
3269                 msg.set_position (Gtk::WIN_POS_CENTER);
3270                 pop_back_splash (msg);
3271                 msg.present ();
3272
3273                 int response = msg.run ();
3274
3275                 msg.hide ();
3276
3277                 switch (response) {
3278                 case RESPONSE_CANCEL:
3279                         exit (1);
3280                 default:
3281                         break;
3282                 }
3283                 goto out;
3284         }
3285         catch (SessionException e) {
3286                 MessageDialog msg (string_compose(
3287                                            _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
3288                                            path, snap_name, e.what()),
3289                                    true,
3290                                    Gtk::MESSAGE_INFO,
3291                                    BUTTONS_OK);
3292
3293                 msg.set_title (_("Loading Error"));
3294                 msg.set_position (Gtk::WIN_POS_CENTER);
3295                 pop_back_splash (msg);
3296                 msg.present ();
3297
3298                 dump_errors (cerr);
3299
3300                 (void) msg.run ();
3301                 msg.hide ();
3302
3303                 goto out;
3304         }
3305         catch (...) {
3306
3307                 MessageDialog msg (string_compose(
3308                                            _("Session \"%1 (snapshot %2)\" did not load successfully"),
3309                                            path, snap_name),
3310                                    true,
3311                                    Gtk::MESSAGE_INFO,
3312                                    BUTTONS_OK);
3313
3314                 msg.set_title (_("Loading Error"));
3315                 msg.set_position (Gtk::WIN_POS_CENTER);
3316                 pop_back_splash (msg);
3317                 msg.present ();
3318
3319                 dump_errors (cerr);
3320
3321                 (void) msg.run ();
3322                 msg.hide ();
3323
3324                 goto out;
3325         }
3326
3327         {
3328                 list<string> const u = new_session->unknown_processors ();
3329                 if (!u.empty()) {
3330                         MissingPluginDialog d (_session, u);
3331                         d.run ();
3332                 }
3333         }
3334
3335         if (!new_session->writable()) {
3336                 MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."),
3337                                    true,
3338                                    Gtk::MESSAGE_INFO,
3339                                    BUTTONS_OK);
3340
3341                 msg.set_title (_("Read-only Session"));
3342                 msg.set_position (Gtk::WIN_POS_CENTER);
3343                 pop_back_splash (msg);
3344                 msg.present ();
3345                 (void) msg.run ();
3346                 msg.hide ();
3347         }
3348
3349
3350         /* Now the session been created, add the transport controls */
3351         new_session->add_controllable(roll_controllable);
3352         new_session->add_controllable(stop_controllable);
3353         new_session->add_controllable(goto_start_controllable);
3354         new_session->add_controllable(goto_end_controllable);
3355         new_session->add_controllable(auto_loop_controllable);
3356         new_session->add_controllable(play_selection_controllable);
3357         new_session->add_controllable(rec_controllable);
3358
3359         set_session (new_session);
3360
3361         session_loaded = true;
3362
3363         if (_session) {
3364                 _session->set_clean ();
3365         }
3366
3367 #ifdef WINDOWS_VST_SUPPORT
3368         fst_stop_threading();
3369 #endif
3370
3371         {
3372                 Timers::TimerSuspender t;
3373                 flush_pending ();
3374         }
3375
3376 #ifdef WINDOWS_VST_SUPPORT
3377         fst_start_threading();
3378 #endif
3379         retval = 0;
3380
3381   out:
3382         return retval;
3383 }
3384
3385 int
3386 ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
3387 {
3388         Session *new_session;
3389         int x;
3390
3391         session_loaded = false;
3392         x = unload_session ();
3393
3394         if (x < 0) {
3395                 return -1;
3396         } else if (x > 0) {
3397                 return 0;
3398         }
3399
3400         _session_is_new = true;
3401
3402         try {
3403                 new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
3404         }
3405
3406         catch (SessionException e) {
3407                 dump_errors (cerr);
3408                 MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
3409                 msg.set_title (_("Loading Error"));
3410                 msg.set_position (Gtk::WIN_POS_CENTER);
3411                 pop_back_splash (msg);
3412                 msg.run ();
3413                 return -1;
3414         }
3415         catch (...) {
3416                 dump_errors (cerr);
3417                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
3418                 msg.set_title (_("Loading Error"));
3419                 msg.set_position (Gtk::WIN_POS_CENTER);
3420                 pop_back_splash (msg);
3421                 msg.run ();
3422                 return -1;
3423         }
3424
3425         /* Give the new session the default GUI state, if such things exist */
3426
3427         XMLNode* n;
3428         n = Config->instant_xml (X_("Editor"));
3429         if (n) {
3430                 n->remove_nodes_and_delete ("Selection"); // no not apply selection to new sessions.
3431                 new_session->add_instant_xml (*n, false);
3432         }
3433         n = Config->instant_xml (X_("Mixer"));
3434         if (n) {
3435                 new_session->add_instant_xml (*n, false);
3436         }
3437
3438         /* Put the playhead at 0 and scroll fully left */
3439         n = new_session->instant_xml (X_("Editor"));
3440         if (n) {
3441                 n->add_property (X_("playhead"), X_("0"));
3442                 n->add_property (X_("left-frame"), X_("0"));
3443         }
3444
3445         set_session (new_session);
3446
3447         session_loaded = true;
3448
3449         new_session->save_state(new_session->name());
3450
3451         return 0;
3452 }
3453
3454 void
3455 ARDOUR_UI::launch_chat ()
3456 {
3457         MessageDialog dialog(_("<b>Just ask and wait for an answer.\nIt may take from minutes to hours.</b>"), true);
3458
3459         dialog.set_title (_("About the Chat"));
3460         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."));
3461
3462         switch (dialog.run()) {
3463         case RESPONSE_OK:
3464 #ifdef __APPLE__
3465                 open_uri("http://webchat.freenode.net/?channels=ardour-osx");
3466 #elif defined PLATFORM_WINDOWS
3467                 open_uri("http://webchat.freenode.net/?channels=ardour-windows");
3468 #else
3469                 open_uri("http://webchat.freenode.net/?channels=ardour");
3470 #endif
3471                 break;
3472         default:
3473                 break;
3474         }
3475 }
3476
3477 void
3478 ARDOUR_UI::launch_manual ()
3479 {
3480         PBD::open_uri (Config->get_tutorial_manual_url());
3481 }
3482
3483 void
3484 ARDOUR_UI::launch_reference ()
3485 {
3486         PBD::open_uri (Config->get_reference_manual_url());
3487 }
3488
3489 void
3490 ARDOUR_UI::launch_tracker ()
3491 {
3492         PBD::open_uri ("http://tracker.ardour.org");
3493 }
3494
3495 void
3496 ARDOUR_UI::launch_subscribe ()
3497 {
3498         PBD::open_uri ("https://community.ardour.org/s/subscribe");
3499 }
3500
3501 void
3502 ARDOUR_UI::launch_cheat_sheet ()
3503 {
3504 #ifdef __APPLE__
3505         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheat_sheet_osx.pdf");
3506 #else
3507         PBD::open_uri ("http://manual.ardour.org/files/a3_mnemonic_cheatsheet.pdf");
3508 #endif
3509 }
3510
3511 void
3512 ARDOUR_UI::launch_website ()
3513 {
3514         PBD::open_uri ("http://ardour.org");
3515 }
3516
3517 void
3518 ARDOUR_UI::launch_website_dev ()
3519 {
3520         PBD::open_uri ("http://ardour.org/development.html");
3521 }
3522
3523 void
3524 ARDOUR_UI::launch_forums ()
3525 {
3526         PBD::open_uri ("https://community.ardour.org/forums");
3527 }
3528
3529 void
3530 ARDOUR_UI::launch_howto_report ()
3531 {
3532         PBD::open_uri ("http://ardour.org/reporting_bugs");
3533 }
3534
3535 void
3536 ARDOUR_UI::loading_message (const std::string& msg)
3537 {
3538         if (ARDOUR_COMMAND_LINE::no_splash) {
3539                 return;
3540         }
3541
3542         if (!splash) {
3543                 show_splash ();
3544         }
3545
3546         splash->message (msg);
3547 }
3548
3549 void
3550 ARDOUR_UI::show_splash ()
3551 {
3552         if (splash == 0) {
3553                 try {
3554                         splash = new Splash;
3555                 } catch (...) {
3556                         return;
3557                 }
3558         }
3559
3560         splash->display ();
3561 }
3562
3563 void
3564 ARDOUR_UI::hide_splash ()
3565 {
3566         delete splash;
3567         splash = 0;
3568 }
3569
3570 void
3571 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* list_title, const bool msg_delete)
3572 {
3573         size_t removed;
3574
3575         removed = rep.paths.size();
3576
3577         if (removed == 0) {
3578                 MessageDialog msgd (_main_window,
3579                                     _("No files were ready for clean-up"),
3580                                     true,
3581                                     Gtk::MESSAGE_INFO,
3582                                     Gtk::BUTTONS_OK);
3583                 msgd.set_title (_("Clean-up"));
3584                 msgd.set_secondary_text (_("If this seems suprising, \n\
3585 check for any existing snapshots.\n\
3586 These may still include regions that\n\
3587 require some unused files to continue to exist."));
3588
3589                 msgd.run ();
3590                 return;
3591         }
3592
3593         ArdourDialog results (_("Clean-up"), true, false);
3594
3595         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
3596             CleanupResultsModelColumns() {
3597                     add (visible_name);
3598                     add (fullpath);
3599             }
3600             Gtk::TreeModelColumn<std::string> visible_name;
3601             Gtk::TreeModelColumn<std::string> fullpath;
3602         };
3603
3604
3605         CleanupResultsModelColumns results_columns;
3606         Glib::RefPtr<Gtk::ListStore> results_model;
3607         Gtk::TreeView results_display;
3608
3609         results_model = ListStore::create (results_columns);
3610         results_display.set_model (results_model);
3611         results_display.append_column (list_title, results_columns.visible_name);
3612
3613         results_display.set_name ("CleanupResultsList");
3614         results_display.set_headers_visible (true);
3615         results_display.set_headers_clickable (false);
3616         results_display.set_reorderable (false);
3617
3618         Gtk::ScrolledWindow list_scroller;
3619         Gtk::Label txt;
3620         Gtk::VBox dvbox;
3621         Gtk::HBox dhbox;  // the hbox for the image and text
3622         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
3623         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
3624
3625         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
3626
3627         const string dead_directory = _session->session_directory().dead_path();
3628
3629         /* subst:
3630            %1 - number of files removed
3631            %2 - location of "dead"
3632            %3 - size of files affected
3633            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
3634         */
3635
3636         const char* bprefix;
3637         double space_adjusted = 0;
3638
3639         if (rep.space < 1000) {
3640                 bprefix = X_("");
3641                 space_adjusted = rep.space;
3642         } else if (rep.space < 1000000) {
3643                 bprefix = _("kilo");
3644                 space_adjusted = floorf((float)rep.space / 1000.0);
3645         } else if (rep.space < 1000000 * 1000) {
3646                 bprefix = _("mega");
3647                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
3648         } else {
3649                 bprefix = _("giga");
3650                 space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
3651         }
3652
3653         if (msg_delete) {
3654                 txt.set_markup (string_compose (P_("\
3655 The following file was deleted from %2,\n\
3656 releasing %3 %4bytes of disk space", "\
3657 The following %1 files were deleted from %2,\n\
3658 releasing %3 %4bytes of disk space", removed),
3659                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3660         } else {
3661                 txt.set_markup (string_compose (P_("\
3662 The following file was not in use and \n\
3663 has been moved to: %2\n\n\
3664 After a restart of %5\n\n\
3665 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3666 will release an additional %3 %4bytes of disk space.\n", "\
3667 The following %1 files were not in use and \n\
3668 have been moved to: %2\n\n\
3669 After a restart of %5\n\n\
3670 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
3671 will release an additional %3 %4bytes of disk space.\n", removed),
3672                                         removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
3673         }
3674
3675         dhbox.pack_start (*dimage, true, false, 5);
3676         dhbox.pack_start (txt, true, false, 5);
3677
3678         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
3679                 TreeModel::Row row = *(results_model->append());
3680                 row[results_columns.visible_name] = *i;
3681                 row[results_columns.fullpath] = *i;
3682         }
3683
3684         list_scroller.add (results_display);
3685         list_scroller.set_size_request (-1, 150);
3686         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
3687
3688         dvbox.pack_start (dhbox, true, false, 5);
3689         dvbox.pack_start (list_scroller, true, false, 5);
3690         ddhbox.pack_start (dvbox, true, false, 5);
3691
3692         results.get_vbox()->pack_start (ddhbox, true, false, 5);
3693         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
3694         results.set_default_response (RESPONSE_CLOSE);
3695         results.set_position (Gtk::WIN_POS_MOUSE);
3696
3697         results_display.show();
3698         list_scroller.show();
3699         txt.show();
3700         dvbox.show();
3701         dhbox.show();
3702         ddhbox.show();
3703         dimage->show();
3704
3705         //results.get_vbox()->show();
3706         results.set_resizable (false);
3707
3708         results.run ();
3709
3710 }
3711
3712 void
3713 ARDOUR_UI::cleanup ()
3714 {
3715         if (_session == 0) {
3716                 /* shouldn't happen: menu item is insensitive */
3717                 return;
3718         }
3719
3720
3721         MessageDialog checker (_("Are you sure you want to clean-up?"),
3722                                 true,
3723                                 Gtk::MESSAGE_QUESTION,
3724                                 Gtk::BUTTONS_NONE);
3725
3726         checker.set_title (_("Clean-up"));
3727
3728         checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
3729 ALL undo/redo information will be lost if you clean-up.\n\
3730 Clean-up will move all unused files to a \"dead\" location."));
3731
3732         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3733         checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
3734         checker.set_default_response (RESPONSE_CANCEL);
3735
3736         checker.set_name (_("CleanupDialog"));
3737         checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
3738         checker.set_position (Gtk::WIN_POS_MOUSE);
3739
3740         switch (checker.run()) {
3741         case RESPONSE_ACCEPT:
3742                 break;
3743         default:
3744                 return;
3745         }
3746
3747         ARDOUR::CleanupReport rep;
3748
3749         editor->prepare_for_cleanup ();
3750
3751         /* do not allow flush until a session is reloaded */
3752
3753         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
3754         if (act) {
3755                 act->set_sensitive (false);
3756         }
3757
3758         if (_session->cleanup_sources (rep)) {
3759                 editor->finish_cleanup ();
3760                 return;
3761         }
3762
3763         editor->finish_cleanup ();
3764
3765         checker.hide();
3766         display_cleanup_results (rep, _("Cleaned Files"), false);
3767 }
3768
3769 void
3770 ARDOUR_UI::flush_trash ()
3771 {
3772         if (_session == 0) {
3773                 /* shouldn't happen: menu item is insensitive */
3774                 return;
3775         }
3776
3777         ARDOUR::CleanupReport rep;
3778
3779         if (_session->cleanup_trash_sources (rep)) {
3780                 return;
3781         }
3782
3783         display_cleanup_results (rep, _("deleted file"), true);
3784 }
3785
3786 void
3787 ARDOUR_UI::cleanup_peakfiles ()
3788 {
3789         if (_session == 0) {
3790                 /* shouldn't happen: menu item is insensitive */
3791                 return;
3792         }
3793
3794         if (! _session->can_cleanup_peakfiles ()) {
3795                 return;
3796         }
3797
3798         // get all region-views in this session
3799         RegionSelection rs;
3800         TrackViewList empty;
3801         empty.clear();
3802         editor->get_regions_after(rs, (framepos_t) 0, empty);
3803         std::list<RegionView*> views = rs.by_layer();
3804
3805         // remove displayed audio-region-views waveforms
3806         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3807                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3808                 if (!arv) { continue ; }
3809                 arv->delete_waves();
3810         }
3811
3812         // cleanup peak files:
3813         // - stop pending peakfile threads
3814         // - close peakfiles if any
3815         // - remove peak dir in session
3816         // - setup peakfiles (background thread)
3817         _session->cleanup_peakfiles ();
3818
3819         // re-add waves to ARV
3820         for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
3821                 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
3822                 if (!arv) { continue ; }
3823                 arv->create_waves();
3824         }
3825 }
3826
3827 void
3828 ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
3829 {
3830         uint32_t order_hint = UINT32_MAX;
3831
3832         if (editor->get_selection().tracks.empty()) {
3833                 return;
3834         }
3835
3836         /*
3837           we want the new routes to have their order keys set starting from
3838           the highest order key in the selection + 1 (if available).
3839         */
3840
3841         if (place == AddRouteDialog::AfterSelection) {
3842                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
3843                 if (rtav) {
3844                         order_hint = rtav->route()->order_key();
3845                         order_hint++;
3846                 }
3847         } else if (place == AddRouteDialog::BeforeSelection) {
3848                 RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
3849                 if (rtav) {
3850                         order_hint = rtav->route()->order_key();
3851                 }
3852         } else if (place == AddRouteDialog::First) {
3853                 order_hint = 0;
3854         } else {
3855                 /* leave order_hint at UINT32_MAX */
3856         }
3857
3858         if (order_hint == UINT32_MAX) {
3859                 /** AddRouteDialog::Last or selection with first/last not a RouteTimeAxisView
3860                  * not setting an order hint will place new routes last.
3861                  */
3862                 return;
3863         }
3864
3865         _session->set_order_hint (order_hint);
3866
3867         /* create a gap in the existing route order keys to accomodate new routes.*/
3868         boost::shared_ptr <RouteList> rd = _session->get_routes();
3869         for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
3870                 boost::shared_ptr<Route> rt (*ri);
3871
3872                 if (rt->is_monitor()) {
3873                         continue;
3874                 }
3875
3876                 if (rt->order_key () >= order_hint) {
3877                         rt->set_order_key (rt->order_key () + add_route_dialog->count());
3878                 }
3879         }
3880 }
3881
3882 void
3883 ARDOUR_UI::start_duplicate_routes ()
3884 {
3885         if (!duplicate_routes_dialog) {
3886                 duplicate_routes_dialog = new DuplicateRouteDialog;
3887         }
3888
3889         if (duplicate_routes_dialog->restart (_session)) {
3890                 return;
3891         }
3892
3893         duplicate_routes_dialog->present ();
3894 }
3895
3896 void
3897 ARDOUR_UI::add_route (Gtk::Window* /* ignored */)
3898 {
3899         int count;
3900
3901         if (!_session) {
3902                 return;
3903         }
3904
3905         if (add_route_dialog->is_visible()) {
3906                 /* we're already doing this */
3907                 return;
3908         }
3909
3910         ResponseType r = (ResponseType) add_route_dialog->run ();
3911
3912         add_route_dialog->hide();
3913
3914         switch (r) {
3915                 case RESPONSE_ACCEPT:
3916                         break;
3917                 default:
3918                         return;
3919                         break;
3920         }
3921
3922         if ((count = add_route_dialog->count()) <= 0) {
3923                 return;
3924         }
3925
3926         setup_order_hint(add_route_dialog->insert_at());
3927
3928         string template_path = add_route_dialog->track_template();
3929         DisplaySuspender ds;
3930
3931         if (!template_path.empty()) {
3932                 if (add_route_dialog->name_template_is_default())  {
3933                         _session->new_route_from_template (count, template_path, string());
3934                 } else {
3935                         _session->new_route_from_template (count, template_path, add_route_dialog->name_template());
3936                 }
3937                 return;
3938         }
3939
3940         ChanCount input_chan= add_route_dialog->channels ();
3941         ChanCount output_chan;
3942         string name_template = add_route_dialog->name_template ();
3943         PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
3944         RouteGroup* route_group = add_route_dialog->route_group ();
3945         AutoConnectOption oac = Config->get_output_auto_connect();
3946
3947         if (oac & AutoConnectMaster) {
3948                 output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
3949                 output_chan.set (DataType::MIDI, 0);
3950         } else {
3951                 output_chan = input_chan;
3952         }
3953
3954         /* XXX do something with name template */
3955
3956         switch (add_route_dialog->type_wanted()) {
3957         case AddRouteDialog::AudioTrack:
3958                 session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template);
3959                 break;
3960         case AddRouteDialog::MidiTrack:
3961                 session_add_midi_track (route_group, count, name_template, instrument);
3962                 break;
3963         case AddRouteDialog::MixedTrack:
3964                 session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, instrument);
3965                 break;
3966         case AddRouteDialog::AudioBus:
3967                 session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template);
3968                 break;
3969         case AddRouteDialog::MidiBus:
3970                 session_add_midi_bus (route_group, count, name_template, instrument);
3971                 break;
3972         }
3973 }
3974
3975 void
3976 ARDOUR_UI::add_lua_script ()
3977 {
3978         if (!_session) {
3979                 return;
3980         }
3981
3982         LuaScriptInfoPtr spi;
3983         ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
3984         switch (ss.run ()) {
3985                 case Gtk::RESPONSE_ACCEPT:
3986                         spi = ss.script();
3987                         break;
3988                 default:
3989                         return;
3990         }
3991         ss.hide();
3992
3993         std::string script = "";
3994
3995         try {
3996                 script = Glib::file_get_contents (spi->path);
3997         } catch (Glib::FileError e) {
3998                 string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
3999                 MessageDialog am (msg);
4000                 am.run ();
4001                 return;
4002         }
4003
4004         LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
4005         std::vector<std::string> reg = _session->registered_lua_functions ();
4006
4007         ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
4008         switch (spd.run ()) {
4009                 case Gtk::RESPONSE_ACCEPT:
4010                         break;
4011                 default:
4012                         return;
4013         }
4014
4015         try {
4016                 _session->register_lua_function (spd.name(), script, lsp);
4017         } catch (luabridge::LuaException const& e) {
4018                 string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
4019                 MessageDialog am (msg);
4020                 am.run ();
4021         } catch (SessionException e) {
4022                 string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
4023                 MessageDialog am (msg);
4024                 am.run ();
4025         }
4026 }
4027
4028 void
4029 ARDOUR_UI::remove_lua_script ()
4030 {
4031         if (!_session) {
4032                 return;
4033         }
4034         if (_session->registered_lua_function_count () ==  0) {
4035                 string msg = _("There are no active Lua session scripts present in this session.");
4036                 MessageDialog am (msg);
4037                 am.run ();
4038                 return;
4039         }
4040
4041         std::vector<std::string> reg = _session->registered_lua_functions ();
4042         SessionScriptManager sm ("Remove Lua Session Script", reg);
4043         switch (sm.run ()) {
4044                 case Gtk::RESPONSE_ACCEPT:
4045                         break;
4046                 default:
4047                         return;
4048         }
4049         try {
4050                 _session->unregister_lua_function (sm.name());
4051         } catch (luabridge::LuaException const& e) {
4052                 string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
4053                 MessageDialog am (msg);
4054                 am.run ();
4055         }
4056 }
4057
4058 void
4059 ARDOUR_UI::stop_video_server (bool ask_confirm)
4060 {
4061         if (!video_server_process && ask_confirm) {
4062                 warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
4063         }
4064         if (video_server_process) {
4065                 if(ask_confirm) {
4066                         ArdourDialog confirm (_("Stop Video-Server"), true);
4067                         Label m (_("Do you really want to stop the Video Server?"));
4068                         confirm.get_vbox()->pack_start (m, true, true);
4069                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
4070                         confirm.add_button (_("Yes, Stop It"), Gtk::RESPONSE_ACCEPT);
4071                         confirm.show_all ();
4072                         if (confirm.run() == RESPONSE_CANCEL) {
4073                                 return;
4074                         }
4075                 }
4076                 delete video_server_process;
4077                 video_server_process =0;
4078         }
4079 }
4080
4081 void
4082 ARDOUR_UI::start_video_server_menu (Gtk::Window* float_window)
4083 {
4084   ARDOUR_UI::start_video_server( float_window, true);
4085 }
4086
4087 bool
4088 ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
4089 {
4090         if (!_session) {
4091                 return false;
4092         }
4093         if (popup_msg) {
4094                 if (ARDOUR_UI::instance()->video_timeline->check_server()) {
4095                         if (video_server_process) {
4096                                 popup_error(_("The Video Server is already started."));
4097                         } else {
4098                                 popup_error(_("An external Video Server is configured and can be reached. Not starting a new instance."));
4099                         }
4100                 }
4101         }
4102
4103         int firsttime = 0;
4104         while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4105                 if (firsttime++) {
4106                         warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4107                 }
4108                 VideoServerDialog *video_server_dialog = new VideoServerDialog (_session);
4109                 if (float_window) {
4110                         video_server_dialog->set_transient_for (*float_window);
4111                 }
4112
4113                 if (!Config->get_show_video_server_dialog() && firsttime < 2) {
4114                         video_server_dialog->hide();
4115                 } else {
4116                         ResponseType r = (ResponseType) video_server_dialog->run ();
4117                         video_server_dialog->hide();
4118                         if (r != RESPONSE_ACCEPT) { return false; }
4119                         if (video_server_dialog->show_again()) {
4120                                 Config->set_show_video_server_dialog(false);
4121                         }
4122                 }
4123
4124                 std::string icsd_exec = video_server_dialog->get_exec_path();
4125                 std::string icsd_docroot = video_server_dialog->get_docroot();
4126                 if (icsd_docroot.empty()) {
4127 #ifndef PLATFORM_WINDOWS
4128                         icsd_docroot = X_("/");
4129 #else
4130                         icsd_docroot = X_("C:\\");
4131 #endif
4132                 }
4133
4134                 GStatBuf sb;
4135                 if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
4136                         warning << _("Specified docroot is not an existing directory.") << endmsg;
4137                         continue;
4138                 }
4139 #ifndef PLATFORM_WINDOWS
4140                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4141                      || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
4142                         warning << _("Given Video Server is not an executable file.") << endmsg;
4143                         continue;
4144                 }
4145 #else
4146                 if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
4147                      || (sb.st_mode & (S_IXUSR)) == 0 ) {
4148                         warning << _("Given Video Server is not an executable file.") << endmsg;
4149                         continue;
4150                 }
4151 #endif
4152
4153                 char **argp;
4154                 argp=(char**) calloc(9,sizeof(char*));
4155                 argp[0] = strdup(icsd_exec.c_str());
4156                 argp[1] = strdup("-P");
4157                 argp[2] = (char*) calloc(16,sizeof(char)); snprintf(argp[2], 16, "%s", video_server_dialog->get_listenaddr().c_str());
4158                 argp[3] = strdup("-p");
4159                 argp[4] = (char*) calloc(6,sizeof(char)); snprintf(argp[4], 6, "%i", video_server_dialog->get_listenport());
4160                 argp[5] = strdup("-C");
4161                 argp[6] = (char*) calloc(6,sizeof(char)); snprintf(argp[6], 6, "%i", video_server_dialog->get_cachesize());
4162                 argp[7] = strdup(icsd_docroot.c_str());
4163                 argp[8] = 0;
4164                 stop_video_server();
4165
4166                 if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
4167                         Config->set_video_advanced_setup(false);
4168                 } else {
4169                         std::ostringstream osstream;
4170                         osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
4171                         Config->set_video_server_url(osstream.str());
4172                         Config->set_video_server_docroot(icsd_docroot);
4173                         Config->set_video_advanced_setup(true);
4174                 }
4175
4176                 if (video_server_process) {
4177                         delete video_server_process;
4178                 }
4179
4180                 video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
4181                 if (video_server_process->start()) {
4182                         warning << _("Cannot launch the video-server") << endmsg;
4183                         continue;
4184                 }
4185                 int timeout = 120; // 6 sec
4186                 while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
4187                         Glib::usleep (50000);
4188                         gui_idle_handler();
4189                         if (--timeout <= 0 || !video_server_process->is_running()) break;
4190                 }
4191                 if (timeout <= 0) {
4192                         warning << _("Video-server was started but does not respond to requests...") << endmsg;
4193                 } else {
4194                         if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) {
4195                                 delete video_server_process;
4196                                 video_server_process = 0;
4197                         }
4198                 }
4199         }
4200         return true;
4201 }
4202
4203 void
4204 ARDOUR_UI::add_video (Gtk::Window* float_window)
4205 {
4206         if (!_session) {
4207                 return;
4208         }
4209
4210         if (!start_video_server(float_window, false)) {
4211                 warning << _("Could not connect to the Video Server. Start it or configure its access URL in Preferences.") << endmsg;
4212                 return;
4213         }
4214
4215         if (float_window) {
4216                 add_video_dialog->set_transient_for (*float_window);
4217         }
4218
4219         if (add_video_dialog->is_visible()) {
4220                 /* we're already doing this */
4221                 return;
4222         }
4223
4224         ResponseType r = (ResponseType) add_video_dialog->run ();
4225         add_video_dialog->hide();
4226         if (r != RESPONSE_ACCEPT) { return; }
4227
4228         bool local_file, orig_local_file;
4229         std::string path = add_video_dialog->file_name(local_file);
4230
4231         std::string orig_path = path;
4232         orig_local_file = local_file;
4233
4234         bool auto_set_session_fps = add_video_dialog->auto_set_session_fps();
4235
4236         if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) {
4237                 warning << string_compose(_("could not open %1"), path) << endmsg;
4238                 return;
4239         }
4240         if (!local_file && path.length() == 0) {
4241                 warning << _("no video-file selected") << endmsg;
4242                 return;
4243         }
4244
4245         std::string audio_from_video;
4246         bool detect_ltc = false;
4247
4248         switch (add_video_dialog->import_option()) {
4249                 case VTL_IMPORT_TRANSCODE:
4250                         {
4251                                 TranscodeVideoDialog *transcode_video_dialog;
4252                                 transcode_video_dialog = new TranscodeVideoDialog (_session, path);
4253                                 ResponseType r = (ResponseType) transcode_video_dialog->run ();
4254                                 transcode_video_dialog->hide();
4255                                 if (r != RESPONSE_ACCEPT) {
4256                                         delete transcode_video_dialog;
4257                                         return;
4258                                 }
4259
4260                                 audio_from_video = transcode_video_dialog->get_audiofile();
4261
4262                                 if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
4263                                         detect_ltc = true;
4264                                 }
4265                                 else if (!audio_from_video.empty()) {
4266                                         editor->embed_audio_from_video(
4267                                                         audio_from_video,
4268                                                         video_timeline->get_offset(),
4269                                                         (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
4270                                                         );
4271                                 }
4272                                 switch (transcode_video_dialog->import_option()) {
4273                                         case VTL_IMPORT_TRANSCODED:
4274                                                 path = transcode_video_dialog->get_filename();
4275                                                 local_file = true;
4276                                                 break;
4277                                         case VTL_IMPORT_REFERENCE:
4278                                                 break;
4279                                         default:
4280                                                 delete transcode_video_dialog;
4281                                                 return;
4282                                 }
4283                                 delete transcode_video_dialog;
4284                         }
4285                         break;
4286                 default:
4287                 case VTL_IMPORT_NONE:
4288                         break;
4289         }
4290
4291         /* strip _session->session_directory().video_path() from video file if possible */
4292         if (local_file && !path.compare(0, _session->session_directory().video_path().size(), _session->session_directory().video_path())) {
4293                  path=path.substr(_session->session_directory().video_path().size());
4294                  if (path.at(0) == G_DIR_SEPARATOR) {
4295                          path=path.substr(1);
4296                  }
4297         }
4298
4299         video_timeline->set_update_session_fps(auto_set_session_fps);
4300
4301         if (video_timeline->video_file_info(path, local_file)) {
4302                 XMLNode* node = new XMLNode(X_("Videotimeline"));
4303                 node->add_property (X_("Filename"), path);
4304                 node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
4305                 node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
4306                 if (orig_local_file) {
4307                         node->add_property (X_("OriginalVideoFile"), orig_path);
4308                 } else {
4309                         node->remove_property (X_("OriginalVideoFile"));
4310                 }
4311                 _session->add_extra_xml (*node);
4312                 _session->set_dirty ();
4313
4314                 if (!audio_from_video.empty() && detect_ltc) {
4315                         std::vector<LTCFileReader::LTCMap> ltc_seq;
4316
4317                         try {
4318                                 /* TODO ask user about TV standard (LTC alignment if any) */
4319                                 LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
4320                                 /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
4321
4322                                 ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
4323
4324                                 /* TODO seek near end of file, and read LTC until end.
4325                                  * if it fails to find any LTC frames, scan complete file
4326                                  *
4327                                  * calculate drift of LTC compared to video-duration,
4328                                  * ask user for reference (timecode from start/mid/end)
4329                                  */
4330                         } catch (...) {
4331                                 // LTCFileReader will have written error messages
4332                         }
4333
4334                         ::g_unlink(audio_from_video.c_str());
4335
4336                         if (ltc_seq.size() == 0) {
4337                                 PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
4338                         } else {
4339                                 /* the very first TC in the file is somteimes not aligned properly */
4340                                 int i = ltc_seq.size() -1;
4341                                 ARDOUR::frameoffset_t video_start_offset =
4342                                         _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
4343                                 PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
4344                                 video_timeline->set_offset(video_start_offset);
4345                         }
4346                 }
4347
4348                 _session->maybe_update_session_range(
4349                         std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
4350                         std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
4351
4352
4353                 if (add_video_dialog->launch_xjadeo() && local_file) {
4354                         editor->set_xjadeo_sensitive(true);
4355                         editor->toggle_xjadeo_proc(1);
4356                 } else {
4357                         editor->toggle_xjadeo_proc(0);
4358                 }
4359                 editor->toggle_ruler_video(true);
4360         }
4361 }
4362
4363 void
4364 ARDOUR_UI::remove_video ()
4365 {
4366         video_timeline->close_session();
4367         editor->toggle_ruler_video(false);
4368
4369         /* reset state */
4370         video_timeline->set_offset_locked(false);
4371         video_timeline->set_offset(0);
4372
4373         /* delete session state */
4374         XMLNode* node = new XMLNode(X_("Videotimeline"));
4375         _session->add_extra_xml(*node);
4376         node = new XMLNode(X_("Videomonitor"));
4377         _session->add_extra_xml(*node);
4378         node = new XMLNode(X_("Videoexport"));
4379         _session->add_extra_xml(*node);
4380         stop_video_server();
4381 }
4382
4383 void
4384 ARDOUR_UI::flush_videotimeline_cache (bool localcacheonly)
4385 {
4386         if (localcacheonly) {
4387                 video_timeline->vmon_update();
4388         } else {
4389                 video_timeline->flush_cache();
4390         }
4391         editor->queue_visual_videotimeline_update();
4392 }
4393
4394 void
4395 ARDOUR_UI::export_video (bool range)
4396 {
4397         if (ARDOUR::Config->get_show_video_export_info()) {
4398                 ExportVideoInfobox infobox (_session);
4399                 Gtk::ResponseType rv = (Gtk::ResponseType) infobox.run();
4400                 if (infobox.show_again()) {
4401                         ARDOUR::Config->set_show_video_export_info(false);
4402                 }
4403                 switch (rv) {
4404                         case GTK_RESPONSE_YES:
4405                                 PBD::open_uri (ARDOUR::Config->get_reference_manual_url() + "/video-timeline/operations/#export");
4406                                 break;
4407                         default:
4408                                 break;
4409                 }
4410         }
4411         export_video_dialog->set_session (_session);
4412         export_video_dialog->apply_state(editor->get_selection().time, range);
4413         export_video_dialog->run ();
4414         export_video_dialog->hide ();
4415 }
4416
4417 XMLNode*
4418 ARDOUR_UI::mixer_settings () const
4419 {
4420         XMLNode* node = 0;
4421
4422         if (_session) {
4423                 node = _session->instant_xml(X_("Mixer"));
4424         } else {
4425                 node = Config->instant_xml(X_("Mixer"));
4426         }
4427
4428         if (!node) {
4429                 node = new XMLNode (X_("Mixer"));
4430         }
4431
4432         return node;
4433 }
4434
4435 XMLNode*
4436 ARDOUR_UI::main_window_settings () const
4437 {
4438         XMLNode* node = 0;
4439
4440         if (_session) {
4441                 node = _session->instant_xml(X_("Main"));
4442         } else {
4443                 node = Config->instant_xml(X_("Main"));
4444         }
4445
4446         if (!node) {
4447                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4448                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4449                 }
4450         }
4451
4452         if (!node) {
4453                 node = new XMLNode (X_("Main"));
4454         }
4455
4456         return node;
4457 }
4458
4459 XMLNode*
4460 ARDOUR_UI::editor_settings () const
4461 {
4462         XMLNode* node = 0;
4463
4464         if (_session) {
4465                 node = _session->instant_xml(X_("Editor"));
4466         } else {
4467                 node = Config->instant_xml(X_("Editor"));
4468         }
4469
4470         if (!node) {
4471                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
4472                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
4473                 }
4474         }
4475
4476         if (!node) {
4477                 node = new XMLNode (X_("Editor"));
4478         }
4479
4480         return node;
4481 }
4482
4483 XMLNode*
4484 ARDOUR_UI::keyboard_settings () const
4485 {
4486         XMLNode* node = 0;
4487
4488         node = Config->extra_xml(X_("Keyboard"));
4489
4490         if (!node) {
4491                 node = new XMLNode (X_("Keyboard"));
4492         }
4493
4494         return node;
4495 }
4496
4497 void
4498 ARDOUR_UI::create_xrun_marker (framepos_t where)
4499 {
4500         if (_session) {
4501                 Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
4502                 _session->locations()->add (location);
4503         }
4504 }
4505
4506 void
4507 ARDOUR_UI::halt_on_xrun_message ()
4508 {
4509         cerr << "HALT on xrun\n";
4510         MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
4511         msg.run ();
4512 }
4513
4514 void
4515 ARDOUR_UI::xrun_handler (framepos_t where)
4516 {
4517         if (!_session) {
4518                 return;
4519         }
4520
4521         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::xrun_handler, where)
4522
4523         if (_session && Config->get_create_xrun_marker() && _session->actively_recording()) {
4524                 create_xrun_marker(where);
4525         }
4526
4527         if (_session && Config->get_stop_recording_on_xrun() && _session->actively_recording()) {
4528                 halt_on_xrun_message ();
4529         }
4530 }
4531
4532 void
4533 ARDOUR_UI::disk_overrun_handler ()
4534 {
4535         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
4536
4537         if (!have_disk_speed_dialog_displayed) {
4538                 have_disk_speed_dialog_displayed = true;
4539                 MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
4540 The disk system on your computer\n\
4541 was not able to keep up with %1.\n\
4542 \n\
4543 Specifically, it failed to write data to disk\n\
4544 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
4545                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4546                 msg->show ();
4547         }
4548 }
4549
4550
4551 /* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
4552 static MessageDialog *scan_dlg = NULL;
4553 static ProgressBar   *scan_pbar = NULL;
4554 static HBox          *scan_tbox = NULL;
4555 static Gtk::Button   *scan_timeout_button;
4556
4557 void
4558 ARDOUR_UI::cancel_plugin_scan ()
4559 {
4560         PluginManager::instance().cancel_plugin_scan();
4561 }
4562
4563 void
4564 ARDOUR_UI::cancel_plugin_timeout ()
4565 {
4566         PluginManager::instance().cancel_plugin_timeout();
4567         scan_timeout_button->set_sensitive (false);
4568 }
4569
4570 void
4571 ARDOUR_UI::plugin_scan_timeout (int timeout)
4572 {
4573         if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
4574                 return;
4575         }
4576         if (timeout > 0) {
4577                 scan_pbar->set_sensitive (false);
4578                 scan_timeout_button->set_sensitive (true);
4579                 scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
4580                 scan_tbox->show();
4581         } else {
4582                 scan_pbar->set_sensitive (false);
4583                 scan_timeout_button->set_sensitive (false);
4584         }
4585         gui_idle_handler();
4586 }
4587
4588 void
4589 ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
4590 {
4591         if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
4592                 return;
4593         }
4594
4595         const bool cancelled = PluginManager::instance().cancelled();
4596         if (type != X_("closeme") && (!UIConfiguration::instance().get_show_plugin_scan_window()) && !_initial_verbose_plugin_scan) {
4597                 if (cancelled && scan_dlg->is_mapped()) {
4598                         scan_dlg->hide();
4599                         gui_idle_handler();
4600                         return;
4601                 }
4602                 if (cancelled || !can_cancel) {
4603                         return;
4604                 }
4605         }
4606
4607         static Gtk::Button *cancel_button;
4608         if (!scan_dlg) {
4609                 scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
4610                 VBox* vbox = scan_dlg->get_vbox();
4611                 vbox->set_size_request(400,-1);
4612                 scan_dlg->set_title (_("Scanning for plugins"));
4613
4614                 cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
4615                 cancel_button->set_name ("EditorGTKButton");
4616                 cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
4617                 cancel_button->show();
4618
4619                 scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
4620
4621                 scan_tbox = manage( new HBox() );
4622
4623                 scan_timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
4624                 scan_timeout_button->set_name ("EditorGTKButton");
4625                 scan_timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
4626                 scan_timeout_button->show();
4627
4628                 scan_pbar = manage(new ProgressBar());
4629                 scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
4630                 scan_pbar->set_text(_("Scan Timeout"));
4631                 scan_pbar->show();
4632
4633                 scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
4634                 scan_tbox->pack_start (*scan_timeout_button, PACK_SHRINK, 4);
4635
4636                 scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
4637         }
4638
4639         assert(scan_dlg && scan_tbox && cancel_button);
4640
4641         if (type == X_("closeme")) {
4642                 scan_tbox->hide();
4643                 scan_dlg->hide();
4644         } else {
4645                 scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
4646                 scan_dlg->show();
4647         }
4648         if (!can_cancel || !cancelled) {
4649                 scan_timeout_button->set_sensitive(false);
4650         }
4651         cancel_button->set_sensitive(can_cancel && !cancelled);
4652
4653         gui_idle_handler();
4654 }
4655
4656 void
4657 ARDOUR_UI::gui_idle_handler ()
4658 {
4659         int timeout = 30;
4660         /* due to idle calls, gtk_events_pending() may always return true */
4661         while (gtk_events_pending() && --timeout) {
4662                 gtk_main_iteration ();
4663         }
4664 }
4665
4666 void
4667 ARDOUR_UI::disk_underrun_handler ()
4668 {
4669         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
4670
4671         if (!have_disk_speed_dialog_displayed) {
4672                 have_disk_speed_dialog_displayed = true;
4673                 MessageDialog* msg = new MessageDialog (
4674                         _main_window, string_compose (_("The disk system on your computer\n\
4675 was not able to keep up with %1.\n\
4676 \n\
4677 Specifically, it failed to read data from disk\n\
4678 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
4679                 msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
4680                 msg->show ();
4681         }
4682 }
4683
4684 void
4685 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
4686 {
4687         have_disk_speed_dialog_displayed = false;
4688         delete msg;
4689 }
4690
4691 void
4692 ARDOUR_UI::session_dialog (std::string msg)
4693 {
4694         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
4695
4696         MessageDialog* d;
4697
4698         d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
4699         d->show_all ();
4700         d->run ();
4701         delete d;
4702 }
4703
4704 int
4705 ARDOUR_UI::pending_state_dialog ()
4706 {
4707         HBox* hbox = manage (new HBox());
4708         Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
4709         ArdourDialog dialog (_("Crash Recovery"), true);
4710         Label  message (string_compose (_("\
4711 This session appears to have been in the\n\
4712 middle of recording when %1 or\n\
4713 the computer was shutdown.\n\
4714 \n\
4715 %1 can recover any captured audio for\n\
4716 you, or it can ignore it. Please decide\n\
4717 what you would like to do.\n"), PROGRAM_NAME));
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 (_("Ignore crash data"), RESPONSE_REJECT);
4723         dialog.add_button (_("Recover from crash"), 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 1;
4733         default:
4734                 return 0;
4735         }
4736 }
4737
4738 int
4739 ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
4740 {
4741         HBox* hbox = new HBox();
4742         Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
4743         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
4744         Label  message (string_compose (_("\
4745 This session was created with a sample rate of %1 Hz, but\n\
4746 %2 is currently running at %3 Hz.  If you load this session,\n\
4747 audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
4748
4749         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
4750         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
4751         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
4752         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
4753         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
4754         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
4755         dialog.set_default_response (RESPONSE_ACCEPT);
4756         dialog.set_position (WIN_POS_CENTER);
4757         message.show();
4758         image->show();
4759         hbox->show();
4760
4761         switch (dialog.run()) {
4762         case RESPONSE_ACCEPT:
4763                 return 0;
4764         default:
4765                 break;
4766         }
4767
4768         return 1;
4769 }
4770
4771 void
4772 ARDOUR_UI::use_config ()
4773 {
4774         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
4775         if (node) {
4776                 set_transport_controllable_state (*node);
4777         }
4778 }
4779
4780 void
4781 ARDOUR_UI::update_transport_clocks (framepos_t pos)
4782 {
4783         if (UIConfiguration::instance().get_primary_clock_delta_edit_cursor()) {
4784                 primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4785         } else {
4786                 primary_clock->set (pos);
4787         }
4788
4789         if (UIConfiguration::instance().get_secondary_clock_delta_edit_cursor()) {
4790                 secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD));
4791         } else {
4792                 secondary_clock->set (pos);
4793         }
4794
4795         if (big_clock_window) {
4796                 big_clock->set (pos);
4797         }
4798         ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos);
4799 }
4800
4801 void
4802 ARDOUR_UI::step_edit_status_change (bool yn)
4803 {
4804         // XXX should really store pre-step edit status of things
4805         // we make insensitive
4806
4807         if (yn) {
4808                 rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
4809                 rec_button.set_sensitive (false);
4810         } else {
4811                 rec_button.unset_active_state ();;
4812                 rec_button.set_sensitive (true);
4813         }
4814 }
4815
4816 void
4817 ARDOUR_UI::record_state_changed ()
4818 {
4819         ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
4820
4821         if (!_session || !big_clock_window) {
4822                 /* why bother - the clock isn't visible */
4823                 return;
4824         }
4825
4826         if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
4827                 big_clock->set_active (true);
4828         } else {
4829                 big_clock->set_active (false);
4830         }
4831 }
4832
4833 bool
4834 ARDOUR_UI::first_idle ()
4835 {
4836         if (_session) {
4837                 _session->allow_auto_play (true);
4838         }
4839
4840         if (editor) {
4841                 editor->first_idle();
4842         }
4843
4844         Keyboard::set_can_save_keybindings (true);
4845         return false;
4846 }
4847
4848 void
4849 ARDOUR_UI::store_clock_modes ()
4850 {
4851         XMLNode* node = new XMLNode(X_("ClockModes"));
4852
4853         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
4854                 XMLNode* child = new XMLNode (X_("Clock"));
4855
4856                 child->add_property (X_("name"), (*x)->name());
4857                 child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
4858                 child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
4859
4860                 node->add_child_nocopy (*child);
4861         }
4862
4863         _session->add_extra_xml (*node);
4864         _session->set_dirty ();
4865 }
4866
4867 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
4868         : Controllable (name), ui (u), type(tp)
4869 {
4870
4871 }
4872
4873 void
4874 ARDOUR_UI::TransportControllable::set_value (double val, PBD::Controllable::GroupControlDisposition /*group_override*/)
4875 {
4876         if (val < 0.5) {
4877                 /* do nothing: these are radio-style actions */
4878                 return;
4879         }
4880
4881         const char *action = 0;
4882
4883         switch (type) {
4884         case Roll:
4885                 action = X_("Roll");
4886                 break;
4887         case Stop:
4888                 action = X_("Stop");
4889                 break;
4890         case GotoStart:
4891                 action = X_("GotoStart");
4892                 break;
4893         case GotoEnd:
4894                 action = X_("GotoEnd");
4895                 break;
4896         case AutoLoop:
4897                 action = X_("Loop");
4898                 break;
4899         case PlaySelection:
4900                 action = X_("PlaySelection");
4901                 break;
4902         case RecordEnable:
4903                 action = X_("Record");
4904                 break;
4905         default:
4906                 break;
4907         }
4908
4909         if (action == 0) {
4910                 return;
4911         }
4912
4913         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
4914
4915         if (act) {
4916                 act->activate ();
4917         }
4918 }
4919
4920 double
4921 ARDOUR_UI::TransportControllable::get_value (void) const
4922 {
4923         float val = 0.0;
4924
4925         switch (type) {
4926         case Roll:
4927                 break;
4928         case Stop:
4929                 break;
4930         case GotoStart:
4931                 break;
4932         case GotoEnd:
4933                 break;
4934         case AutoLoop:
4935                 break;
4936         case PlaySelection:
4937                 break;
4938         case RecordEnable:
4939                 break;
4940         default:
4941                 break;
4942         }
4943
4944         return val;
4945 }
4946
4947 void
4948 ARDOUR_UI::setup_profile ()
4949 {
4950         if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
4951                 Profile->set_small_screen ();
4952         }
4953
4954         if (g_getenv ("TRX")) {
4955                 Profile->set_trx ();
4956         }
4957
4958         if (g_getenv ("MIXBUS")) {
4959                 Profile->set_mixbus ();
4960         }
4961 }
4962
4963 int
4964 ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
4965 {
4966         MissingFileDialog dialog (s, str, type);
4967
4968         dialog.show ();
4969         dialog.present ();
4970
4971         int result = dialog.run ();
4972         dialog.hide ();
4973
4974         switch (result) {
4975         case RESPONSE_OK:
4976                 break;
4977         default:
4978                 return 1; // quit entire session load
4979         }
4980
4981         result = dialog.get_action ();
4982
4983         return result;
4984 }
4985
4986 int
4987 ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
4988 {
4989         AmbiguousFileDialog dialog (file, hits);
4990
4991         dialog.show ();
4992         dialog.present ();
4993
4994         dialog.run ();
4995
4996         return dialog.get_which ();
4997 }
4998
4999 /** Allocate our thread-local buffers */
5000 void
5001 ARDOUR_UI::get_process_buffers ()
5002 {
5003         _process_thread->get_buffers ();
5004 }
5005
5006 /** Drop our thread-local buffers */
5007 void
5008 ARDOUR_UI::drop_process_buffers ()
5009 {
5010         _process_thread->drop_buffers ();
5011 }
5012
5013 void
5014 ARDOUR_UI::feedback_detected ()
5015 {
5016         _feedback_exists = true;
5017 }
5018
5019 void
5020 ARDOUR_UI::successful_graph_sort ()
5021 {
5022         _feedback_exists = false;
5023 }
5024
5025 void
5026 ARDOUR_UI::midi_panic ()
5027 {
5028         if (_session) {
5029                 _session->midi_panic();
5030         }
5031 }
5032
5033 void
5034 ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
5035 {
5036         const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
5037         const char* end_big = "</span>";
5038         const char* start_mono = "<tt>";
5039         const char* end_mono = "</tt>";
5040
5041         MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
5042                                              "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
5043                                              "From now on, use the -2000 version with older versions of %3"),
5044                                            xml_path, backup_path, PROGRAM_NAME,
5045                                            start_big, end_big,
5046                                            start_mono, end_mono), true);
5047
5048         msg.run ();
5049 }
5050
5051
5052 void
5053 ARDOUR_UI::reset_peak_display ()
5054 {
5055         if (!_session || !_session->master_out() || !editor_meter) return;
5056         editor_meter->clear_meters();
5057         editor_meter_max_peak = -INFINITY;
5058         editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
5059 }
5060
5061 void
5062 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
5063 {
5064         if (!_session || !_session->master_out()) return;
5065         if (group == _session->master_out()->route_group()) {
5066                 reset_peak_display ();
5067         }
5068 }
5069
5070 void
5071 ARDOUR_UI::reset_route_peak_display (Route* route)
5072 {
5073         if (!_session || !_session->master_out()) return;
5074         if (_session->master_out().get() == route) {
5075                 reset_peak_display ();
5076         }
5077 }
5078
5079 int
5080 ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
5081 {
5082         audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
5083         audio_midi_setup->set_position (WIN_POS_CENTER);
5084
5085         int response;
5086
5087         while (true) {
5088                 response = audio_midi_setup->run();
5089                 switch (response) {
5090                 case Gtk::RESPONSE_OK:
5091                         if (!AudioEngine::instance()->running()) {
5092                                 continue;
5093                         } else {
5094                                 return 0;
5095                         }
5096                         return 0;
5097                 default:
5098                         return -1;
5099                 }
5100         }
5101 }
5102
5103
5104 gint
5105 ARDOUR_UI::transport_numpad_timeout ()
5106 {
5107         _numpad_locate_happening = false;
5108         if (_numpad_timeout_connection.connected() )
5109                 _numpad_timeout_connection.disconnect();
5110         return 1;
5111 }
5112
5113 void
5114 ARDOUR_UI::transport_numpad_decimal ()
5115 {
5116         _numpad_timeout_connection.disconnect();
5117
5118         if (_numpad_locate_happening) {
5119                 if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
5120                 _numpad_locate_happening = false;
5121         } else {
5122                 _pending_locate_num = 0;
5123                 _numpad_locate_happening = true;
5124                 _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
5125         }
5126 }
5127
5128 void
5129 ARDOUR_UI::transport_numpad_event (int num)
5130 {
5131         if ( _numpad_locate_happening ) {
5132                 _pending_locate_num = _pending_locate_num*10 + num;
5133         } else {
5134                 switch (num) {
5135                         case 0:  toggle_roll(false, false);             break;
5136                         case 1:  transport_rewind(1);                           break;
5137                         case 2:  transport_forward(1);                          break;
5138                         case 3:  transport_record(true);                        break;
5139                         case 4:  toggle_session_auto_loop();            break;
5140                         case 5:  transport_record(false); toggle_session_auto_loop();   break;
5141                         case 6:  toggle_punch();                                        break;
5142                         case 7:  toggle_click();                                break;
5143                         case 8:  toggle_auto_return();                  break;
5144                         case 9:  toggle_follow_edits();         break;
5145                 }
5146         }
5147 }
5148
5149 void
5150 ARDOUR_UI::set_flat_buttons ()
5151 {
5152         CairoWidget::set_flat_buttons( UIConfiguration::instance().get_flat_buttons() );
5153 }
5154
5155 void
5156 ARDOUR_UI::audioengine_became_silent ()
5157 {
5158         MessageDialog msg (string_compose (_("This is a free/demo copy of %1. It has just switched to silent mode."), PROGRAM_NAME),
5159                            true,
5160                            Gtk::MESSAGE_WARNING,
5161                            Gtk::BUTTONS_NONE,
5162                            true);
5163
5164         msg.set_title (string_compose (_("%1 is now silent"), PROGRAM_NAME));
5165
5166         Gtk::Label pay_label (string_compose (_("Please consider paying for a copy of %1 - you can pay whatever you want."), PROGRAM_NAME));
5167         Gtk::Label subscribe_label (_("Better yet become a subscriber - subscriptions start at US$1 per month."));
5168         Gtk::Button pay_button (_("Pay for a copy (via the web)"));
5169         Gtk::Button subscribe_button (_("Become a subscriber (via the web)"));
5170         Gtk::HBox pay_button_box;
5171         Gtk::HBox subscribe_button_box;
5172
5173         pay_button_box.pack_start (pay_button, true, false);
5174         subscribe_button_box.pack_start (subscribe_button, true, false);
5175
5176         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 */
5177
5178         pay_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://ardour.org/download")));
5179         subscribe_button.signal_clicked().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (openuri), (const char*) "https://community.ardour.org/s/subscribe")));
5180
5181         msg.get_vbox()->pack_start (pay_label);
5182         msg.get_vbox()->pack_start (pay_button_box);
5183         msg.get_vbox()->pack_start (subscribe_label);
5184         msg.get_vbox()->pack_start (subscribe_button_box);
5185
5186         msg.get_vbox()->show_all ();
5187
5188         msg.add_button (_("Remain silent"), Gtk::RESPONSE_CANCEL);
5189         msg.add_button (_("Save and quit"), Gtk::RESPONSE_NO);
5190         msg.add_button (_("Give me more time"), Gtk::RESPONSE_YES);
5191
5192         int r = msg.run ();
5193
5194         switch (r) {
5195         case Gtk::RESPONSE_YES:
5196                 AudioEngine::instance()->reset_silence_countdown ();
5197                 break;
5198
5199         case Gtk::RESPONSE_NO:
5200                 /* save and quit */
5201                 save_state_canfail ("");
5202                 exit (0);
5203                 break;
5204
5205         case Gtk::RESPONSE_CANCEL:
5206         default:
5207                 /* don't reset, save session and exit */
5208                 break;
5209         }
5210 }
5211
5212 void
5213 ARDOUR_UI::hide_application ()
5214 {
5215     Application::instance ()-> hide ();
5216 }
5217
5218 void
5219 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
5220 {
5221         /* icons, titles, WM stuff */
5222
5223         static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
5224
5225         if (window_icons.empty()) {
5226                 Glib::RefPtr<Gdk::Pixbuf> icon;
5227                 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
5228                         window_icons.push_back (icon);
5229                 }
5230                 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
5231                         window_icons.push_back (icon);
5232                 }
5233                 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
5234                         window_icons.push_back (icon);
5235                 }
5236                 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
5237                         window_icons.push_back (icon);
5238                 }
5239         }
5240
5241         if (!window_icons.empty()) {
5242                 window.set_default_icon_list (window_icons);
5243         }
5244
5245         Gtkmm2ext::WindowTitle title (Glib::get_application_name());
5246
5247         if (!name.empty()) {
5248                 title += name;
5249         }
5250
5251         window.set_title (title.get_string());
5252         window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
5253
5254         window.set_flags (CAN_FOCUS);
5255         window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
5256
5257         /* This is a hack to ensure that GTK-accelerators continue to
5258          * work. Once we switch over to entirely native bindings, this will be
5259          * unnecessary and should be removed
5260          */
5261         window.add_accel_group (ActionManager::ui_manager->get_accel_group());
5262
5263         window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
5264         window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
5265         window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5266         window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
5267 }
5268
5269 bool
5270 ARDOUR_UI::key_event_handler (GdkEventKey* ev, Gtk::Window* event_window)
5271 {
5272         Gtkmm2ext::Bindings* bindings = 0;
5273         Gtk::Window* window = 0;
5274
5275         /* until we get ardour bindings working, we are not handling key
5276          * releases yet.
5277          */
5278
5279         if (ev->type != GDK_KEY_PRESS) {
5280                 return false;
5281         }
5282
5283         if (event_window == &_main_window) {
5284
5285                 window = event_window;
5286
5287                 /* find current tab contents */
5288
5289                 Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
5290
5291                 /* see if it uses the ardour binding system */
5292
5293                 if (w) {
5294                         bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
5295                 }
5296
5297                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
5298
5299         } else {
5300
5301                 window = event_window;
5302
5303                 /* see if window uses ardour binding system */
5304
5305                 bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
5306         }
5307
5308         /* An empty binding set is treated as if it doesn't exist */
5309
5310         if (bindings && bindings->empty()) {
5311                 bindings = 0;
5312         }
5313
5314         return key_press_focus_accelerator_handler (*window, ev, bindings);
5315 }
5316
5317 static Gtkmm2ext::Bindings*
5318 get_bindings_from_widget_heirarchy (GtkWidget* w)
5319 {
5320         void* p;
5321
5322         while (w) {
5323                 if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) {
5324                         break;
5325                 }
5326                 w = gtk_widget_get_parent (w);
5327         }
5328
5329         return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
5330 }
5331
5332 bool
5333 ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
5334 {
5335         GtkWindow* win = window.gobj();
5336         GtkWidget* focus = gtk_window_get_focus (win);
5337         bool special_handling_of_unmodified_accelerators = false;
5338         const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
5339
5340         if (focus) {
5341
5342                 /* some widget has keyboard focus */
5343
5344                 if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
5345
5346                         /* A particular kind of focusable widget currently has keyboard
5347                          * focus. All unmodified key events should go to that widget
5348                          * first and not be used as an accelerator by default
5349                          */
5350
5351                         special_handling_of_unmodified_accelerators = true;
5352
5353                 } else {
5354
5355                         Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus);
5356                         if (focus_bindings) {
5357                                 bindings = focus_bindings;
5358                                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
5359                         }
5360                 }
5361         }
5362
5363         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",
5364                                                           win,
5365                                                           ev->keyval,
5366                                                           show_gdk_event_state (ev->state),
5367                                                           special_handling_of_unmodified_accelerators,
5368                                                           Keyboard::some_magic_widget_has_focus(),
5369                                                           focus,
5370                                                           (focus ? gtk_widget_get_name (focus) : "no focus widget"),
5371                                                           ((ev->state & mask) ? "yes" : "no")));
5372
5373         /* This exists to allow us to override the way GTK handles
5374            key events. The normal sequence is:
5375
5376            a) event is delivered to a GtkWindow
5377            b) accelerators/mnemonics are activated
5378            c) if (b) didn't handle the event, propagate to
5379                the focus widget and/or focus chain
5380
5381            The problem with this is that if the accelerators include
5382            keys without modifiers, such as the space bar or the
5383            letter "e", then pressing the key while typing into
5384            a text entry widget results in the accelerator being
5385            activated, instead of the desired letter appearing
5386            in the text entry.
5387
5388            There is no good way of fixing this, but this
5389            represents a compromise. The idea is that
5390            key events involving modifiers (not Shift)
5391            get routed into the activation pathway first, then
5392            get propagated to the focus widget if necessary.
5393
5394            If the key event doesn't involve modifiers,
5395            we deliver to the focus widget first, thus allowing
5396            it to get "normal text" without interference
5397            from acceleration.
5398
5399            Of course, this can also be problematic: if there
5400            is a widget with focus, then it will swallow
5401            all "normal text" accelerators.
5402         */
5403
5404
5405         if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
5406
5407                 /* no special handling or there are modifiers in effect: accelerate first */
5408
5409                 DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
5410                 DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\n",
5411                                                                   ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
5412
5413                 DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
5414                 KeyboardKey k (ev->state, ev->keyval);
5415
5416                 if (bindings) {
5417
5418                         DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
5419
5420                         if (bindings->activate (k, Bindings::Press)) {
5421                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5422                                 return true;
5423                         }
5424                 }
5425
5426                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5427
5428                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5429                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5430                         return true;
5431                 }
5432
5433                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
5434
5435                 if (gtk_window_propagate_key_event (win, ev)) {
5436                         DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
5437                         return true;
5438                 }
5439
5440         } else {
5441
5442                 /* no modifiers, propagate first */
5443
5444                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
5445
5446                 if (gtk_window_propagate_key_event (win, ev)) {
5447                         DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
5448                         return true;
5449                 }
5450
5451                 DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
5452                 KeyboardKey k (ev->state, ev->keyval);
5453
5454                 if (bindings) {
5455
5456                         DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
5457
5458
5459                         if (bindings->activate (k, Bindings::Press)) {
5460                                 DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5461                                 return true;
5462                         }
5463
5464                 }
5465
5466                 DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
5467
5468                 if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
5469                         DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
5470                         return true;
5471                 }
5472         }
5473
5474         DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
5475         return true;
5476 }
5477
5478 void
5479 ARDOUR_UI::load_bindings ()
5480 {
5481         if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
5482                 error << _("Global keybindings are missing") << endmsg;
5483         }
5484 }
5485
5486 void
5487 ARDOUR_UI::cancel_solo ()
5488 {
5489         if (_session) {
5490                 if (_session->soloing()) {
5491                         _session->set_solo (_session->get_routes(), false);
5492                 } else if (_session->listening()) {
5493                         _session->set_listen (_session->get_routes(), false);
5494                 }
5495
5496                 _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window
5497         }
5498 }