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