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