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