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