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