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