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