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