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