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