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