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