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