1 /*
2  * Copyright (C) 2005-2007 Doug McLain <doug@nostar.net>
3  * Copyright (C) 2005-2017 Tim Mayberry <mojofunk@gmail.com>
4  * Copyright (C) 2005-2019 Paul Davis <paul@linuxaudiosystems.com>
5  * Copyright (C) 2005 Karsten Wiese <fzuuzf@googlemail.com>
6  * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
7  * Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
8  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
9  * Copyright (C) 2008-2010 Sakari Bergen <sakari.bergen@beatwaves.net>
10  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
11  * Copyright (C) 2013-2015 Colin Fletcher <colin.m.fletcher@googlemail.com>
12  * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
13  * Copyright (C) 2013-2016 Nick Mainsbridge <mainsbridge@gmail.com>
14  * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
15  * Copyright (C) 2015 André Nusser <andre.nusser@googlemail.com>
16  * Copyright (C) 2016-2018 Len Ovens <len@ovenwerks.net>
17  * Copyright (C) 2017 Johannes Mueller <github@johannes-mueller.org>
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 2 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License along
30  * with this program; if not, write to the Free Software Foundation, Inc.,
31  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32  */
33 
34 #ifdef WAF_BUILD
35 #include "gtk2ardour-config.h"
36 #include "gtk2ardour-version.h"
37 #endif
38 
39 #include <algorithm>
40 #include <cmath>
41 #include <iostream>
42 #include <cerrno>
43 
44 #include <stdarg.h>
45 
46 #ifndef PLATFORM_WINDOWS
47 #include <sys/resource.h>
48 #endif
49 
50 #ifdef __FreeBSD__
51 #include <sys/types.h>
52 #include <sys/sysctl.h>
53 #endif
54 
55 #include <stdint.h>
56 #include <fcntl.h>
57 #include <signal.h>
58 #include <unistd.h>
59 #include <time.h>
60 
61 #include <glib.h>
62 #include "pbd/gstdio_compat.h"
63 
64 #include <gtkmm/accelmap.h>
65 #include <gtkmm/messagedialog.h>
66 #include <gtkmm/stock.h>
67 #include <gtkmm/uimanager.h>
68 
69 #include "pbd/error.h"
70 #include "pbd/basename.h"
71 #include "pbd/compose.h"
72 #include "pbd/convert.h"
73 #include "pbd/failed_constructor.h"
74 #include "pbd/file_archive.h"
75 #include "pbd/enumwriter.h"
76 #include "pbd/memento_command.h"
77 #include "pbd/openuri.h"
78 #include "pbd/stl_delete.h"
79 #include "pbd/types_convert.h"
80 #include "pbd/unwind.h"
81 #include "pbd/file_utils.h"
82 #include "pbd/localtime_r.h"
83 #include "pbd/pthread_utils.h"
84 #include "pbd/replace_all.h"
85 #include "pbd/scoped_file_descriptor.h"
86 #include "pbd/xml++.h"
87 
88 #include "gtkmm2ext/application.h"
89 #include "gtkmm2ext/bindings.h"
90 #include "gtkmm2ext/gtk_ui.h"
91 #include "gtkmm2ext/utils.h"
92 #include "gtkmm2ext/window_title.h"
93 
94 #include "widgets/fastmeter.h"
95 #include "widgets/prompter.h"
96 #include "widgets/tooltips.h"
97 
98 #include "ardour/ardour.h"
99 #include "ardour/audio_backend.h"
100 #include "ardour/audio_track.h"
101 #include "ardour/audioengine.h"
102 #include "ardour/audiofilesource.h"
103 #include "ardour/automation_watch.h"
104 #include "ardour/disk_reader.h"
105 #include "ardour/disk_writer.h"
106 #include "ardour/filename_extensions.h"
107 #include "ardour/filesystem_paths.h"
108 #include "ardour/ltc_file_reader.h"
109 #include "ardour/monitor_control.h"
110 #include "ardour/midi_track.h"
111 #include "ardour/port.h"
112 #include "ardour/plugin_manager.h"
113 #include "ardour/process_thread.h"
114 #include "ardour/profile.h"
115 #include "ardour/recent_sessions.h"
116 #include "ardour/record_enable_control.h"
117 #include "ardour/revision.h"
118 #include "ardour/session_directory.h"
119 #include "ardour/session_route.h"
120 #include "ardour/session_state_utils.h"
121 #include "ardour/session_utils.h"
122 #include "ardour/source_factory.h"
123 #include "ardour/transport_master.h"
124 #include "ardour/transport_master_manager.h"
125 #include "ardour/system_exec.h"
126 #include "ardour/track.h"
127 #include "ardour/vca_manager.h"
128 #include "ardour/utils.h"
129 
130 #include "LuaBridge/LuaBridge.h"
131 
132 #ifdef WINDOWS_VST_SUPPORT
133 #include <fst.h>
134 #endif
135 #ifdef AUDIOUNIT_SUPPORT
136 #include "ardour/audio_unit.h"
137 #endif
138 
139 // fix for OSX (nsm.h has a check function, AU/Apple defines check)
140 #ifdef check
141 #undef check
142 #endif
143 
144 #include "temporal/time.h"
145 
146 #include "about.h"
147 #include "editing.h"
148 #include "enums_convert.h"
149 #include "actions.h"
150 #include "add_route_dialog.h"
151 #include "ambiguous_file_dialog.h"
152 #include "ardour_message.h"
153 #include "ardour_ui.h"
154 #include "audio_clock.h"
155 #include "audio_region_view.h"
156 #include "big_clock_window.h"
157 #include "big_transport_window.h"
158 #include "bundle_manager.h"
159 #include "dsp_stats_window.h"
160 #include "duplicate_routes_dialog.h"
161 #include "debug.h"
162 #include "engine_dialog.h"
163 #include "export_video_dialog.h"
164 #include "export_video_infobox.h"
165 #include "gain_meter.h"
166 #include "global_port_matrix.h"
167 #include "gui_object.h"
168 #include "gui_thread.h"
169 #include "idleometer.h"
170 #include "keyboard.h"
171 #include "keyeditor.h"
172 #include "location_ui.h"
173 #include "lua_script_manager.h"
174 #include "luawindow.h"
175 #include "main_clock.h"
176 #include "missing_file_dialog.h"
177 #include "missing_plugin_dialog.h"
178 #include "mixer_ui.h"
179 #include "meterbridge.h"
180 #include "meter_patterns.h"
181 #include "mouse_cursors.h"
182 #include "nsm.h"
183 #include "opts.h"
184 #include "pingback.h"
185 #include "plugin_dspload_window.h"
186 #include "processor_box.h"
187 #include "public_editor.h"
188 #include "rc_option_editor.h"
189 #include "recorder_ui.h"
190 #include "route_time_axis.h"
191 #include "route_params_ui.h"
192 #include "save_as_dialog.h"
193 #include "save_template_dialog.h"
194 #include "script_selector.h"
195 #include "session_archive_dialog.h"
196 #include "session_dialog.h"
197 #include "session_metadata_dialog.h"
198 #include "session_option_editor.h"
199 #include "speaker_dialog.h"
200 #include "splash.h"
201 #include "template_dialog.h"
202 #include "time_axis_view_item.h"
203 #include "time_info_box.h"
204 #include "timers.h"
205 #include "transport_masters_dialog.h"
206 #include "utils.h"
207 #include "utils_videotl.h"
208 #include "video_server_dialog.h"
209 #include "virtual_keyboard_window.h"
210 #include "add_video_dialog.h"
211 #include "transcode_video_dialog.h"
212 #include "plugin_selector.h"
213 
214 #include "pbd/i18n.h"
215 
216 using namespace ARDOUR;
217 using namespace ARDOUR_UI_UTILS;
218 using namespace PBD;
219 using namespace Gtkmm2ext;
220 using namespace ArdourWidgets;
221 using namespace Gtk;
222 using namespace std;
223 using namespace Editing;
224 
225 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
226 
227 sigc::signal<void, samplepos_t> ARDOUR_UI::Clock;
228 sigc::signal<void> ARDOUR_UI::CloseAllDialogs;
229 
230 static bool
ask_about_configuration_copy(string const & old_dir,string const & new_dir,int version)231 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
232 {
233 	ArdourMessageDialog msg (string_compose (
234 	                          _("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
235 	                            "Would you like these files to be copied and used for %1 %2.x?\n\n"
236 	                            "(This will require you to restart %1.)"),
237 	                             PROGRAM_NAME, PROGRAM_VERSION, version),
238 	                         false, /* no markup */
239 	                         Gtk::MESSAGE_INFO,
240 	                         Gtk::BUTTONS_YES_NO,
241 	                         true /* modal, though it hardly matters since it is the only window */
242 	);
243 
244 	msg.set_default_response (Gtk::RESPONSE_YES);
245 	msg.show_all ();
246 
247 	return (msg.run() == Gtk::RESPONSE_YES);
248 }
249 
250 static void
libxml_generic_error_func(void *,const char * msg,...)251 libxml_generic_error_func (void* /* parsing_context*/,
252                            const char* msg,
253                            ...)
254 {
255 	va_list ap;
256 	char buf[2048];
257 
258 	va_start (ap, msg);
259 	vsnprintf (buf, sizeof (buf), msg, ap);
260 	error << buf << endmsg;
261 	va_end (ap);
262 }
263 
264 static void
libxml_structured_error_func(void *,xmlErrorPtr err)265 libxml_structured_error_func (void* /* parsing_context*/,
266                               xmlErrorPtr err)
267 {
268 	string msg;
269 
270 	if (err->message)
271 		msg = err->message;
272 
273 	replace_all (msg, "\n", "");
274 
275 	if (!msg.empty()) {
276 		if (err->file && err->line) {
277 			error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
278 
279 			if (err->int2) {
280 				error << ':' << err->int2;
281 			}
282 
283 			error << endmsg;
284 		} else {
285 			error << X_("XML error: ") << msg << endmsg;
286 		}
287 	}
288 }
289 
290 
ARDOUR_UI(int * argcp,char ** argvp[],const char * localedir)291 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
292 	: Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
293 	, session_load_in_progress (false)
294 	, gui_object_state (new GUIObjectState)
295 	, primary_clock   (new MainClock (X_("primary"),   X_("transport"), true ))
296 	, secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
297 	, big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
298 	, video_timeline(0)
299 	, ignore_dual_punch (false)
300 	, main_window_visibility (0)
301 	, editor (0)
302 	, mixer (0)
303 	, recorder (0)
304 	, nsm (0)
305 	, _was_dirty (false)
306 	, _mixer_on_top (false)
307 	, _shared_popup_menu (0)
308 	, startup_fsm (0)
309 	, secondary_clock_spacer (0)
310 	, latency_disable_button (ArdourButton::led_default_elements)
311 	, time_info_box (0)
312 	, auto_return_button (ArdourButton::led_default_elements)
313 	, follow_edits_button (ArdourButton::led_default_elements)
314 	, auditioning_alert_button (_("Audition"))
315 	, solo_alert_button (_("Solo"))
316 	, feedback_alert_button (_("Feedback"))
317 	, error_alert_button ( ArdourButton::just_led_default_elements )
318 	, editor_meter_peak_display()
319 	, editor_meter(0)
320 	, _clear_editor_meter( true)
321 	, _editor_meter_peaked (false)
322 	, _numpad_locate_happening (false)
323 	, _session_is_new (false)
324 	, last_key_press_time (0)
325 	, save_as_dialog (0)
326 	, meterbridge (0)
327 	, luawindow (0)
328 	, rc_option_editor (0)
329 	, speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
330 	, add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
331 	, about (X_("about"), _("About"))
332 	, location_ui (X_("locations"), S_("Ranges|Locations"))
333 	, route_params (X_("inspector"), _("Tracks and Busses"))
334 	, audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
335 	, export_video_dialog (X_("video-export"), _("Video Export Dialog"))
336 	, lua_script_window (X_("script-manager"), _("Script Manager"))
337 	, idleometer (X_("idle-o-meter"), _("Idle'o'Meter"))
338 	, plugin_dsp_load_window (X_("plugin-dsp-load"), _("Plugin DSP Load"))
339 	, dsp_statistics_window (X_("dsp-statistics"), _("Performance Meters"))
340 	, transport_masters_window (X_("transport-masters"), _("Transport Masters"))
341 	, session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
342 	, add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
343 	, bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
344 	, big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
345 	, big_transport_window (X_("big-transport"), _("Transport Controls"), boost::bind (&ARDOUR_UI::create_big_transport_window, this))
346 	, virtual_keyboard_window (X_("virtual-keyboard"), _("Virtual Keyboard"), boost::bind (&ARDOUR_UI::create_virtual_keyboard_window, this))
347 	, audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
348 	, midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
349 	, key_editor (X_("key-editor"), _("Keyboard Shortcuts"), boost::bind (&ARDOUR_UI::create_key_editor, this))
350 	, video_server_process (0)
351 	, have_configure_timeout (false)
352 	, last_configure_time (0)
353 	, last_peak_grab (0)
354 	, have_disk_speed_dialog_displayed (false)
355 	, _status_bar_visibility (X_("status-bar"))
356 	, _feedback_exists (false)
357 	, _ambiguous_latency (false)
358 	, _log_not_acknowledged (LogLevelNone)
359 	, duplicate_routes_dialog (0)
360 	, editor_visibility_button (S_("Window|Edit"))
361 	, mixer_visibility_button (S_("Window|Mix"))
362 	, prefs_visibility_button (S_("Window|Prefs"))
363 	, recorder_visibility_button (S_("Window|Rec"))
364 {
365 	Gtkmm2ext::init (localedir);
366 
367 	UIConfiguration::instance().post_gui_init ();
368 
369 	if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
370 		{
371 			/* "touch" the been-here-before path now that config has been migrated */
372 			PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
373 		}
374 		ArdourMessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
375 		msg.run ();
376 		/* configuration was modified, exit immediately */
377 		_exit (EXIT_SUCCESS);
378 	}
379 
380 
381 	if (theArdourUI == 0) {
382 		theArdourUI = this;
383 	}
384 
385 	/* track main window visibility */
386 
387 	main_window_visibility = new VisibilityTracker (_main_window);
388 
389 	/* stop libxml from spewing to stdout/stderr */
390 
391 	xmlSetGenericErrorFunc (this, libxml_generic_error_func);
392 	xmlSetStructuredErrorFunc (this, libxml_structured_error_func);
393 
394 	/* Set this up early */
395 
396 	ActionManager::init ();
397 
398 	/* we like keyboards */
399 
400 	keyboard = new ArdourKeyboard(*this);
401 
402 	XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
403 	if (node) {
404 		keyboard->set_state (*node, Stateful::loading_state_version);
405 	}
406 
407 	/* actions do not need to be defined when we load keybindings. They
408 	 * will be lazily discovered. But bindings do need to exist when we
409 	 * create windows/tabs with their own binding sets.
410 	 */
411 
412 	keyboard->setup_keybindings ();
413 
414 	if ((global_bindings = Bindings::get_bindings (X_("Global"))) == 0) {
415 		error << _("Global keybindings are missing") << endmsg;
416 	}
417 
418 	install_actions ();
419 
420 	UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
421 	boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
422 	UIConfiguration::instance().map_parameters (pc);
423 
424 	transport_ctrl.setup (this);
425 
426 	ARDOUR::DiskWriter::Overrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
427 	ARDOUR::DiskReader::Underrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
428 
429 	ARDOUR::Session::VersionMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_format_mismatch, this, _1, _2), gui_context());
430 
431 	/* handle dialog requests */
432 
433 	ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
434 
435 	/* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
436 
437 	ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
438 
439 	/* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
440 
441 	ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
442 
443 	/* handle sr mismatch with a dialog - cross-thread from engine */
444 	ARDOUR::Session::NotifyAboutSampleRateMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::sr_mismatch_message, this, _1, _2), gui_context ());
445 
446 	/* handle requests to quit (coming from JACK session) */
447 
448 	ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::finish, this), gui_context ());
449 
450 	/* tell the user about feedback */
451 
452 	ARDOUR::Session::FeedbackDetected.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::feedback_detected, this), gui_context ());
453 	ARDOUR::Session::SuccessfulGraphSort.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::successful_graph_sort, this), gui_context ());
454 
455 	/* indicate global latency compensation en/disable */
456 	ARDOUR::Latent::DisableSwitchChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::latency_switch_changed, this), gui_context ());
457 
458 	/* handle requests to deal with missing files */
459 
460 	ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
461 
462 	/* and ambiguous files */
463 
464 	ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
465 
466 	ARDOUR::GUIIdle.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::gui_idle_handler, this), gui_context());
467 
468 	Config->ParameterChanged.connect ( forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::set_flat_buttons, this), gui_context() );
469 	set_flat_buttons();
470 
471 	theme_changed.connect (sigc::mem_fun(*this, &ARDOUR_UI::on_theme_changed));
472 	UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::on_theme_changed));
473 	UIConfiguration::instance().DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::on_theme_changed));
474 
475 	/* lets get this party started */
476 
477 	setup_gtk_ardour_enums ();
478 	setup_profile ();
479 
480 	SessionEvent::create_per_thread_pool ("GUI", 4096);
481 
482 	UIConfiguration::instance().reset_dpi ();
483 
484 	TimeAxisViewItem::set_constant_heights ();
485 
486 	/* The following must happen after ARDOUR::init() so that Config is set up */
487 
488 	const XMLNode* ui_xml = Config->extra_xml (X_("UI"));
489 
490 	if (ui_xml) {
491 		key_editor.set_state (*ui_xml, 0);
492 		session_option_editor.set_state (*ui_xml, 0);
493 		speaker_config_window.set_state (*ui_xml, 0);
494 		about.set_state (*ui_xml, 0);
495 		add_route_dialog.set_state (*ui_xml, 0);
496 		add_video_dialog.set_state (*ui_xml, 0);
497 		route_params.set_state (*ui_xml, 0);
498 		bundle_manager.set_state (*ui_xml, 0);
499 		location_ui.set_state (*ui_xml, 0);
500 		big_clock_window.set_state (*ui_xml, 0);
501 		big_transport_window.set_state (*ui_xml, 0);
502 		virtual_keyboard_window.set_state (*ui_xml, 0);
503 		audio_port_matrix.set_state (*ui_xml, 0);
504 		midi_port_matrix.set_state (*ui_xml, 0);
505 		export_video_dialog.set_state (*ui_xml, 0);
506 		lua_script_window.set_state (*ui_xml, 0);
507 		idleometer.set_state (*ui_xml, 0);
508 		plugin_dsp_load_window.set_state (*ui_xml, 0);
509 		dsp_statistics_window.set_state (*ui_xml, 0);
510 		transport_masters_window.set_state (*ui_xml, 0);
511 	}
512 
513 	/* set default parent for dialogs and windows */
514 	WM::Manager::instance().set_transient_for (&_main_window);
515 
516 	/* Separate windows */
517 
518 	WM::Manager::instance().register_window (&key_editor);
519 	WM::Manager::instance().register_window (&session_option_editor);
520 	WM::Manager::instance().register_window (&speaker_config_window);
521 	WM::Manager::instance().register_window (&about);
522 	WM::Manager::instance().register_window (&add_route_dialog);
523 	WM::Manager::instance().register_window (&add_video_dialog);
524 	WM::Manager::instance().register_window (&route_params);
525 	WM::Manager::instance().register_window (&audio_midi_setup);
526 	WM::Manager::instance().register_window (&export_video_dialog);
527 	WM::Manager::instance().register_window (&lua_script_window);
528 	WM::Manager::instance().register_window (&bundle_manager);
529 	WM::Manager::instance().register_window (&location_ui);
530 	WM::Manager::instance().register_window (&big_clock_window);
531 	WM::Manager::instance().register_window (&big_transport_window);
532 	WM::Manager::instance().register_window (&virtual_keyboard_window);
533 	WM::Manager::instance().register_window (&audio_port_matrix);
534 	WM::Manager::instance().register_window (&midi_port_matrix);
535 	WM::Manager::instance().register_window (&idleometer);
536 	WM::Manager::instance().register_window (&plugin_dsp_load_window);
537 	WM::Manager::instance().register_window (&dsp_statistics_window);
538 	WM::Manager::instance().register_window (&transport_masters_window);
539 
540 	/* session-sensitive windows */
541 	ActionManager::session_sensitive_actions.push_back (ActionManager::get_action (X_("Window"), X_("toggle-session-options-editor")));
542 	ActionManager::session_sensitive_actions.push_back (ActionManager::get_action (X_("Window"), X_("toggle-transport-masters")));
543 
544 	/* do not retain position for add route dialog */
545 	add_route_dialog.set_state_mask (WindowProxy::Size);
546 
547 	/* Trigger setting up the color scheme and loading the GTK RC file */
548 
549 	UIConfiguration::instance().load_rc_file (false);
550 
551 	_process_thread = new ProcessThread ();
552 
553 	ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
554 }
555 
556 GlobalPortMatrixWindow*
create_global_port_matrix(ARDOUR::DataType type)557 ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
558 {
559 	if (!_session) {
560 		return 0;
561 	}
562 	return new GlobalPortMatrixWindow (_session, type);
563 }
564 
565 void
attach_to_engine()566 ARDOUR_UI::attach_to_engine ()
567 {
568 	AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this, _1), gui_context());
569 	engine_running (0);
570 }
571 
572 void
engine_stopped()573 ARDOUR_UI::engine_stopped ()
574 {
575 	ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped)
576 	ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
577 	ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
578 	update_sample_rate (0);
579 	update_cpu_load ();
580 }
581 
582 void
engine_running(uint32_t cnt)583 ARDOUR_UI::engine_running (uint32_t cnt)
584 {
585 	if (cnt == 0) {
586 		post_engine();
587 	}
588 
589 	update_disk_space ();
590 	update_cpu_load ();
591 	update_sample_rate (AudioEngine::instance()->sample_rate());
592 	update_timecode_format ();
593 	update_peak_thread_work ();
594 	ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, true);
595 	ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, false);
596 }
597 
598 void
engine_halted(const char * reason,bool free_reason)599 ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
600 {
601 	if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
602 		/* we can't rely on the original string continuing to exist when we are called
603 		   again in the GUI thread, so make a copy and note that we need to
604 		   free it later.
605 		*/
606 		char *copy = strdup (reason);
607 		Gtkmm2ext::UI::instance()->call_slot (MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
608 		return;
609 	}
610 
611 	ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false);
612 	ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true);
613 
614 	update_sample_rate (0);
615 
616 	string msgstr;
617 
618 	/* if the reason is a non-empty string, it means that the backend was shutdown
619 	   rather than just Ardour.
620 	*/
621 
622 	if (strlen (reason)) {
623 		msgstr = string_compose (_("The audio backend was shutdown because:\n\n%1"), reason);
624 	} else {
625 		msgstr = string_compose (_("\
626 The audio backend has either been shutdown or it\n\
627 disconnected %1 because %1\n\
628 was not fast enough. Try to restart\n\
629 the audio backend and save the session."), PROGRAM_NAME);
630 	}
631 
632 	ArdourMessageDialog msg (_main_window, msgstr);
633 	msg.run ();
634 
635 	if (free_reason) {
636 		free (const_cast<char*> (reason));
637 	}
638 }
639 
640 void
post_engine()641 ARDOUR_UI::post_engine ()
642 {
643 	/* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine
644 	 */
645 #ifdef AUDIOUNIT_SUPPORT
646 	std::string au_msg;
647 	if (AUPluginInfo::au_get_crashlog(au_msg)) {
648 		popup_error(_("Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see the log window for further details."));
649 		error << _("Audio Unit Plugin Scan Failed:") << endmsg;
650 		info << au_msg << endmsg;
651 	}
652 #endif
653 
654 	/* connect to important signals */
655 
656 	AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
657 	AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
658 	AudioEngine::instance()->BufferSizeChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
659 	AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
660 	AudioEngine::instance()->BecameSilent.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::audioengine_became_silent, this), gui_context());
661 
662 	if (setup_windows ()) {
663 		throw failed_constructor ();
664 	}
665 
666 	transport_ctrl.map_actions ();
667 
668 	/* Do this after setup_windows (), as that's when the _status_bar_visibility is created */
669 	XMLNode* n = Config->extra_xml (X_("UI"));
670 	if (n) {
671 		_status_bar_visibility.set_state (*n);
672 	}
673 
674 	check_memory_locking();
675 
676 	/* this is the first point at which all the possible actions are
677 	 * available, because some of the available actions are dependent on
678 	 * aspects of the engine/backend.
679 	 */
680 
681 	if (ARDOUR_COMMAND_LINE::show_key_actions) {
682 		stringstream sstr;
683 		Bindings::save_all_bindings_as_html (sstr);
684 
685 		if (sstr.str().empty()) {
686 			return;
687 		}
688 		gchar* file_name;
689 		GError *err = NULL;
690 		gint fd;
691 
692 		if ((fd = g_file_open_tmp ("akprintXXXXXX.html", &file_name, &err)) < 0) {
693 			if (err) {
694 				error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg;
695 				g_error_free (err);
696 			}
697 			return;
698 		}
699 
700 #ifdef PLATFORM_WINDOWS
701 		::close (fd);
702 #endif
703 
704 		err = NULL;
705 
706 		if (!g_file_set_contents (file_name, sstr.str().c_str(), sstr.str().size(), &err)) {
707 #ifndef PLATFORM_WINDOWS
708 			::close (fd);
709 #endif
710 			g_unlink (file_name);
711 			if (err) {
712 				error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg;
713 				g_error_free (err);
714 			}
715 			return;
716 		}
717 
718 #ifndef PLATFORM_WINDOWS
719 		::close (fd);
720 #endif
721 
722 		PBD::open_uri (string_compose ("file:///%1", file_name));
723 
724 		halt_connection.disconnect ();
725 		AudioEngine::instance()->stop ();
726 		exit (EXIT_SUCCESS);
727 
728 	}
729 
730 	if (ARDOUR_COMMAND_LINE::show_actions) {
731 
732 
733 		vector<string> paths;
734 		vector<string> labels;
735 		vector<string> tooltips;
736 		vector<string> keys;
737 		vector<Glib::RefPtr<Gtk::Action> > actions;
738 		string ver_in = revision;
739 		string ver = ver_in.substr(0, ver_in.find("-"));
740 
741 		stringstream output;
742 		output << "\n<h2>Menu actions</h2>" << endl;
743 		output << "<p>\n  Every single menu item in " << PROGRAM_NAME << "'s GUI is accessible by control" << endl;
744 		output << "  surfaces or scripts.\n</p>\n" << endl;
745 		output << "<p>\n  The list below shows all available values of <em>action-name</em> as of" << endl;
746 		output << "  " << PROGRAM_NAME << " " << ver << ". You can get the current list at any" << endl;
747 		output << "  time by running " << PROGRAM_NAME << " with the -A flag.\n</p>\n" << endl;
748 		output << "<table class=\"dl\">\n  <thead>" << endl;
749 		output << "      <tr><th>Action Name</th><th>Menu Name</th></tr>" << endl;
750 		output << "  </thead>\n  <tbody>" << endl;
751 
752 		ActionManager::get_all_actions (paths, labels, tooltips, keys, actions);
753 
754 		vector<string>::iterator p;
755 		vector<string>::iterator l;
756 
757 		for (p = paths.begin(), l = labels.begin(); p != paths.end(); ++p, ++l) {
758 			output << " <tr><th><kbd class=\"osc\">" << *p << "</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 (EXIT_SUCCESS);
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 
~ARDOUR_UI()834 ARDOUR_UI::~ARDOUR_UI ()
835 {
836 	UIConfiguration::instance().save_state();
837 
838 	ARDOUR_UI_UTILS::inhibit_screensaver (false);
839 
840 	stop_video_server();
841 
842 	/* unsubscribe from AudioEngine::Stopped */
843 	if (recorder) {
844 		recorder->cleanup ();
845 	}
846 
847 	if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
848 		// don't bother at 'real' exit. the OS cleans up for us.
849 		delete big_clock; big_clock = 0;
850 		delete primary_clock; primary_clock = 0;
851 		delete secondary_clock; secondary_clock = 0;
852 		delete _process_thread; _process_thread = 0;
853 		delete time_info_box; time_info_box = 0;
854 		delete meterbridge; meterbridge = 0;
855 		delete luawindow; luawindow = 0;
856 		delete recorder; recorder = 0;
857 		delete editor; editor = 0;
858 		delete mixer; mixer = 0;
859 		delete rc_option_editor; rc_option_editor = 0; // failed to wrap object warning
860 		delete nsm; nsm = 0;
861 		delete gui_object_state; gui_object_state = 0;
862 		delete _shared_popup_menu ; _shared_popup_menu = 0;
863 		delete main_window_visibility;
864 		FastMeter::flush_pattern_cache ();
865 		ArdourFader::flush_pattern_cache ();
866 	} else if (mixer) {
867 		/* drop references to any PluginInfoPtr */
868 		delete mixer->plugin_selector ();
869 	}
870 
871 
872 #ifndef NDEBUG
873 	/* Small trick to flush main-thread event pool.
874 	 * Other thread-pools are destroyed at pthread_exit(),
875 	 * but tmain thread termination is too late to trigger Pool::~Pool()
876 	 */
877 	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.
878 	delete ev->event_pool();
879 #endif
880 }
881 
882 gint
configure_timeout()883 ARDOUR_UI::configure_timeout ()
884 {
885 	if (last_configure_time == 0) {
886 		/* no configure events yet */
887 		return true;
888 	}
889 
890 	/* force a gap of 0.5 seconds since the last configure event
891 	 */
892 
893 	if (get_microseconds() - last_configure_time < 500000) {
894 		return true;
895 	} else {
896 		have_configure_timeout = false;
897 		save_ardour_state ();
898 		return false;
899 	}
900 }
901 
902 gboolean
configure_handler(GdkEventConfigure *)903 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
904 {
905 	if (have_configure_timeout) {
906 		last_configure_time = get_microseconds();
907 	} else {
908 		Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
909 		have_configure_timeout = true;
910 	}
911 
912 	return FALSE;
913 }
914 
915 void
set_transport_controllable_state(const XMLNode & node)916 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
917 {
918 	std::string str;
919 
920 	if (node.get_property ("roll", str)){
921 		roll_controllable->set_id (str);
922 	}
923 	if (node.get_property ("stop", str)) {
924 		stop_controllable->set_id (str);
925 	}
926 	if (node.get_property ("goto-start", str)) {
927 		goto_start_controllable->set_id (str);
928 	}
929 	if (node.get_property ("goto-end", str)) {
930 		goto_end_controllable->set_id (str);
931 	}
932 	if (node.get_property ("auto-loop", str)) {
933 		auto_loop_controllable->set_id (str);
934 	}
935 	if (node.get_property ("play-selection", str)) {
936 		play_selection_controllable->set_id (str);
937 	}
938 	if (node.get_property ("rec", str)) {
939 		rec_controllable->set_id (str);
940 	}
941 	if (node.get_property ("shuttle", str)) {
942 		shuttle_box.controllable()->set_id (str);
943 	}
944 }
945 
946 XMLNode&
get_transport_controllable_state()947 ARDOUR_UI::get_transport_controllable_state ()
948 {
949 	XMLNode* node = new XMLNode(X_("TransportControllables"));
950 
951 	node->set_property (X_("roll"), roll_controllable->id());
952 	node->set_property (X_("stop"), stop_controllable->id());
953 	node->set_property (X_("goto-start"), goto_start_controllable->id());
954 	node->set_property (X_("goto-end"), goto_end_controllable->id());
955 	node->set_property (X_("auto-loop"), auto_loop_controllable->id());
956 	node->set_property (X_("play-selection"), play_selection_controllable->id());
957 	node->set_property (X_("rec"), rec_controllable->id());
958 	node->set_property (X_("shuttle"), shuttle_box.controllable()->id());
959 
960 	return *node;
961 }
962 
963 void
session_dirty_changed()964 ARDOUR_UI::session_dirty_changed ()
965 {
966 	update_autosave ();
967 	update_title ();
968 }
969 
970 void
update_autosave()971 ARDOUR_UI::update_autosave ()
972 {
973 	if (_session && _session->dirty()) {
974 		if (_autosave_connection.connected()) {
975 			_autosave_connection.disconnect();
976 		}
977 
978 		_autosave_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &ARDOUR_UI::autosave_session),
979 				Config->get_periodic_safety_backup_interval() * 1000);
980 
981 	} else {
982 		if (_autosave_connection.connected()) {
983 			_autosave_connection.disconnect();
984 		}
985 	}
986 }
987 
988 void
queue_finish()989 ARDOUR_UI::queue_finish ()
990 {
991 	Glib::signal_idle().connect (mem_fun (*this, &ARDOUR_UI::idle_finish));
992 }
993 
994 bool
idle_finish()995 ARDOUR_UI::idle_finish ()
996 {
997 	finish ();
998 	return false; /* do not call again */
999 }
1000 
1001 void
finish()1002 ARDOUR_UI::finish()
1003 {
1004 	bool delete_unnamed_session = false;
1005 
1006 	if (_session) {
1007 		const bool unnamed = _session->unnamed();
1008 
1009 		ARDOUR_UI::instance()->video_timeline->sync_session_state();
1010 
1011 		if (_session->dirty() || unnamed) {
1012 			vector<string> actions;
1013 			actions.push_back (_("Don't quit"));
1014 
1015 			if (_session->unnamed()) {
1016 				actions.push_back (_("Discard session"));
1017 				actions.push_back (_("Name session and quit"));
1018 			} else {
1019 				actions.push_back (_("Just quit"));
1020 				actions.push_back (_("Save and quit"));
1021 			}
1022 
1023 			switch (ask_about_saving_session (actions)) {
1024 			case -1:
1025 				return;
1026 				break;
1027 			case 1:
1028 				if (unnamed) {
1029 					rename_session (true);
1030 				}
1031 				/* use the default name */
1032 				if (save_state_canfail ("")) {
1033 					/* failed - don't quit */
1034 					ArdourMessageDialog msg (_main_window,
1035 							   string_compose (_("\
1036 %1 was unable to save your session.\n\n\
1037 If you still wish to quit, please use the\n\n\
1038 \"Just quit\" option."), PROGRAM_NAME));
1039 					msg.run ();
1040 					return;
1041 				}
1042 				break;
1043 			case 0:
1044 				if (unnamed) {
1045 					delete_unnamed_session = true;
1046 				}
1047 				break;
1048 			}
1049 		}
1050 
1051 		second_connection.disconnect ();
1052 		point_one_second_connection.disconnect ();
1053 		point_zero_something_second_connection.disconnect();
1054 		fps_connection.disconnect();
1055 	}
1056 
1057 	delete ARDOUR_UI::instance()->video_timeline;
1058 	ARDOUR_UI::instance()->video_timeline = NULL;
1059 	stop_video_server();
1060 
1061 	/* Save state before deleting the session, as that causes some
1062 	   windows to be destroyed before their visible state can be
1063 	   saved.
1064 	*/
1065 	save_ardour_state ();
1066 
1067 	if (key_editor.get (false)) {
1068 		key_editor->disconnect ();
1069 	}
1070 
1071 	close_all_dialogs ();
1072 
1073 	if (_session) {
1074 
1075 
1076 		if (delete_unnamed_session) {
1077 			ask_about_scratch_deletion ();
1078 		}
1079 
1080 		_session->set_clean ();
1081 		delete _session;
1082 		_session = 0;
1083 
1084 	}
1085 
1086 	halt_connection.disconnect ();
1087 	AudioEngine::instance()->stop ();
1088 #ifdef WINDOWS_VST_SUPPORT
1089 	fst_stop_threading();
1090 #endif
1091 	quit ();
1092 }
1093 
1094 void
ask_about_scratch_deletion()1095 ARDOUR_UI::ask_about_scratch_deletion ()
1096 {
1097 	if (!_session) {
1098 		return;
1099 	}
1100 
1101 	string path = _session->path();
1102 
1103 	ArdourMessageDialog msg (_main_window,
1104 	                         _("DANGER!"),
1105 	                         true,
1106 	                         Gtk::MESSAGE_WARNING,
1107 	                         Gtk::BUTTONS_NONE, true);
1108 
1109 	msg.set_secondary_text (string_compose (_("You have not named this session yet.\n"
1110 	                                          "You can continue to use it as\n\n"
1111 	                                          "%1\n\n"
1112 	                                          "or it will be deleted.\n\n"
1113 	                                          "Deletion is permanent and irreversible."), _session->name()));
1114 
1115 	msg.set_title (_("SCRATCH SESSION - DANGER!"));
1116 	msg.add_button (_("Delete this session (IRREVERSIBLE!)"), RESPONSE_OK);
1117 	msg.add_button (_("Do not delete"), RESPONSE_CANCEL);
1118 	msg.set_default_response (RESPONSE_CANCEL);
1119 	msg.set_position (Gtk::WIN_POS_MOUSE);
1120 
1121 	int r = msg.run ();
1122 
1123 	if (r == Gtk::RESPONSE_OK) {
1124 		PBD::remove_directory (path);
1125 	} else {
1126 		_session->end_unnamed_status ();
1127 	}
1128 }
1129 
1130 void
every_second()1131 ARDOUR_UI::every_second ()
1132 {
1133 	update_cpu_load ();
1134 	update_disk_space ();
1135 	update_timecode_format ();
1136 	update_peak_thread_work ();
1137 
1138 	if (nsm && nsm->is_active ()) {
1139 		nsm->check ();
1140 
1141 		if (!_was_dirty && _session->dirty ()) {
1142 			nsm->is_dirty ();
1143 			_was_dirty = true;
1144 		}
1145 		else if (_was_dirty && !_session->dirty ()){
1146 			nsm->is_clean ();
1147 			_was_dirty = false;
1148 		}
1149 	}
1150 }
1151 
1152 void
every_point_one_seconds()1153 ARDOUR_UI::every_point_one_seconds ()
1154 {
1155 	if (editor) editor->build_region_boundary_cache();
1156 }
1157 
1158 void
every_point_zero_something_seconds()1159 ARDOUR_UI::every_point_zero_something_seconds ()
1160 {
1161 	// august 2007: actual update frequency: 25Hz (40ms), not 100Hz
1162 
1163 	if (editor_meter && UIConfiguration::instance().get_show_editor_meter() && editor_meter_peak_display.is_mapped ()) {
1164 
1165 		if (_clear_editor_meter) {
1166 			editor_meter->clear_meters();
1167 			editor_meter_peak_display.set_active_state (Gtkmm2ext::Off);
1168 			_clear_editor_meter = false;
1169 			_editor_meter_peaked = false;
1170 		}
1171 
1172 		const float mpeak = editor_meter->update_meters();
1173 		const bool peaking = mpeak > UIConfiguration::instance().get_meter_peak();
1174 
1175 		if (!_editor_meter_peaked && peaking) {
1176 			editor_meter_peak_display.set_active_state ( Gtkmm2ext::ExplicitActive );
1177 			_editor_meter_peaked = true;
1178 		}
1179 	}
1180 }
1181 
1182 void
set_fps_timeout_connection()1183 ARDOUR_UI::set_fps_timeout_connection ()
1184 {
1185 	unsigned int interval = 40;
1186 	if (!_session) return;
1187 	if (_session->timecode_frames_per_second() != 0) {
1188 		/* ideally we'll use a select() to sleep and not accumulate
1189 		 * idle time to provide a regular periodic signal.
1190 		 * See linux_vst_gui_support.cc 'elapsed_time_ms'.
1191 		 * However, that'll require a dedicated thread and cross-thread
1192 		 * signals to the GUI Thread..
1193 		 */
1194 		interval = floor(500. /* update twice per FPS, since Glib::signal_timeout is very irregular */
1195 				* _session->sample_rate() / _session->nominal_sample_rate()
1196 				/ _session->timecode_frames_per_second()
1197 				);
1198 #ifdef PLATFORM_WINDOWS
1199 		// the smallest windows scheduler time-slice is ~15ms.
1200 		// periodic GUI timeouts shorter than that will cause
1201 		// WaitForSingleObject to spinlock (100% of one CPU Core)
1202 		// and gtk never enters idle mode.
1203 		// also changing timeBeginPeriod(1) does not affect that in
1204 		// any beneficial way, so we just limit the max rate for now.
1205 		interval = std::max(30u, interval); // at most ~33Hz.
1206 #else
1207 		interval = std::max(8u, interval); // at most 120Hz.
1208 #endif
1209 	}
1210 	fps_connection.disconnect();
1211 	Timers::set_fps_interval (interval);
1212 }
1213 
1214 void
update_sample_rate(samplecnt_t)1215 ARDOUR_UI::update_sample_rate (samplecnt_t)
1216 {
1217 	std::string label = string_compose (X_("<span weight=\"ultralight\">%1</span>: "), _("Audio"));
1218 
1219 	ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored)
1220 
1221 	if (!AudioEngine::instance()->running()) {
1222 
1223 		sample_rate_label.set_markup (label + _("none"));
1224 
1225 	} else {
1226 
1227 		samplecnt_t rate = AudioEngine::instance()->sample_rate();
1228 
1229 		if (rate == 0) {
1230 
1231 			/* no sample rate available */
1232 			sample_rate_label.set_markup (label + _("none"));
1233 
1234 		} else {
1235 			char buf[64];
1236 
1237 			if (fmod (rate, 1000.0) != 0.0) {
1238 				snprintf (buf, sizeof (buf), "%.1f %s / %4.1f %s",
1239 					  (float) rate / 1000.0f, _("kHz"),
1240 					  (AudioEngine::instance()->usecs_per_cycle() / 1000.0f), _("ms"));
1241 			} else {
1242 				snprintf (buf, sizeof (buf), "%" PRId64 " %s / %4.1f %s",
1243 					  rate / 1000, _("kHz"),
1244 					  (AudioEngine::instance()->usecs_per_cycle() / 1000.0f), _("ms"));
1245 			}
1246 			sample_rate_label.set_markup (label + buf);
1247 		}
1248 	}
1249 }
1250 
1251 void
update_format()1252 ARDOUR_UI::update_format ()
1253 {
1254 	if (!_session) {
1255 		format_label.set_text ("");
1256 		return;
1257 	}
1258 
1259 	stringstream s;
1260 	s << X_("<span weight=\"ultralight\">") << _("File") << X_("</span>: ");
1261 
1262 	switch (_session->config.get_native_file_header_format ()) {
1263 	case BWF:
1264 		s << _("BWF");
1265 		break;
1266 	case WAVE:
1267 		s << _("WAV");
1268 		break;
1269 	case WAVE64:
1270 		s << _("WAV64");
1271 		break;
1272 	case CAF:
1273 		s << _("CAF");
1274 		break;
1275 	case AIFF:
1276 		s << _("AIFF");
1277 		break;
1278 	case iXML:
1279 		s << _("iXML");
1280 		break;
1281 	case RF64:
1282 		s << _("RF64");
1283 		break;
1284 	case RF64_WAV:
1285 		s << _("RF64/WAV");
1286 		break;
1287 	case MBWF:
1288 		s << _("MBWF");
1289 		break;
1290 	case FLAC:
1291 		s << _("FLAC");
1292 		break;
1293 	}
1294 
1295 	s << " ";
1296 
1297 	switch (_session->config.get_native_file_data_format ()) {
1298 	case FormatFloat:
1299 		s << _("32-float");
1300 		break;
1301 	case FormatInt24:
1302 		s << _("24-int");
1303 		break;
1304 	case FormatInt16:
1305 		s << _("16-int");
1306 		break;
1307 	}
1308 
1309 	format_label.set_markup (s.str ());
1310 }
1311 
1312 void
update_path_label()1313 ARDOUR_UI::update_path_label ()
1314 {
1315 	stringstream s;
1316 	s << X_("<span weight=\"ultralight\">") << _("Path") << X_("</span>: ");
1317 	if (_session) {
1318 		s << Gtkmm2ext::markup_escape_text (_session->path());
1319 	} else {
1320 		s << "-";
1321 	}
1322 	session_path_label.set_markup (s.str ());
1323 }
1324 
1325 void
update_cpu_load()1326 ARDOUR_UI::update_cpu_load ()
1327 {
1328 	const unsigned int x = _session ? _session->get_xrun_count () : 0;
1329 	const bool fw = AudioEngine::instance()->freewheeling ();
1330 	double const c = AudioEngine::instance()->get_dsp_load ();
1331 
1332 	std::string label = string_compose (X_("<span weight=\"ultralight\">%1</span>: "), _("DSP"));
1333 	const char* const bg = (c > 90 && !fw) ? " background=\"red\" foreground=\"white\"" : "";
1334 
1335 	char buf[256];
1336 	if (x > 9999) {
1337 		snprintf (buf, sizeof (buf), "<span face=\"monospace\"%s>%2.0f%%</span> (>10k)", bg, c);
1338 	} else if (x > 0) {
1339 		snprintf (buf, sizeof (buf), "<span face=\"monospace\"%s>%2.0f%%</span> (%d)", bg, c, x);
1340 	} else {
1341 		snprintf (buf, sizeof (buf), "<span face=\"monospace\"%s>%2.0f%%</span>", bg, c);
1342 	}
1343 
1344 	dsp_load_label.set_markup (label + buf);
1345 
1346 	if (x > 9999) {
1347 		snprintf (buf, sizeof (buf), "%.1f%% X: >10k\n%s", c, _("Shift+Click to clear xruns."));
1348 	} else if (x > 0) {
1349 		snprintf (buf, sizeof (buf), "%.1f%% X: %u\n%s", c, x, _("Shift+Click to clear xruns."));
1350 	} else {
1351 		snprintf (buf, sizeof (buf), "%.1f%%", c);
1352 	}
1353 
1354 	ArdourWidgets::set_tooltip (dsp_load_label, label + buf);
1355 }
1356 
1357 void
update_peak_thread_work()1358 ARDOUR_UI::update_peak_thread_work ()
1359 {
1360 	char buf[64];
1361 	const int c = SourceFactory::peak_work_queue_length ();
1362 	if (c > 0) {
1363 		std::string label = string_compose (X_("<span weight=\"ultralight\">%1</span>: "), _("PkBld"));
1364 		const char* const bg = c > 2 ? " background=\"red\" foreground=\"white\"" : "";
1365 		snprintf (buf, sizeof (buf), "<span %s>%d</span>", bg, c);
1366 		peak_thread_work_label.set_markup (label + buf);
1367 	} else {
1368 		peak_thread_work_label.set_markup (X_(""));
1369 	}
1370 }
1371 
1372 void
count_recenabled_streams(Route & route)1373 ARDOUR_UI::count_recenabled_streams (Route& route)
1374 {
1375 	Track* track = dynamic_cast<Track*>(&route);
1376 	if (track && track->rec_enable_control()->get_value()) {
1377 		rec_enabled_streams += track->n_inputs().n_total();
1378 	}
1379 }
1380 
1381 void
format_disk_space_label(float remain_sec)1382 ARDOUR_UI::format_disk_space_label (float remain_sec)
1383 {
1384 	if (remain_sec < 0) {
1385 		disk_space_label.set_text (_("N/A"));
1386 		ArdourWidgets::set_tooltip (disk_space_label, _("Unknown"));
1387 		return;
1388 	}
1389 
1390 	char buf[64];
1391 
1392 	int sec = floor (remain_sec);
1393 	int hrs  = sec / 3600;
1394 	int mins = (sec / 60) % 60;
1395 	int secs = sec % 60;
1396 	snprintf (buf, sizeof(buf), _("%02dh:%02dm:%02ds"), hrs, mins, secs);
1397 	ArdourWidgets::set_tooltip (disk_space_label, string_compose ("%1: %2", _("Available record time"), buf));
1398 
1399 	std::string label = string_compose (X_("<span weight=\"ultralight\">%1</span>: "), _("Rec"));
1400 
1401 	if (remain_sec > 86400) {
1402 		disk_space_label.set_markup (label + _(">24h"));
1403 	} else if (remain_sec > 32400 /* 9 hours */) {
1404 		snprintf (buf, sizeof (buf), "%.0f", remain_sec / 3600.f);
1405 		disk_space_label.set_markup (label + buf + S_("hours|h"));
1406 	} else if (remain_sec > 5940 /* 99 mins */) {
1407 		snprintf (buf, sizeof (buf), "%.1f", remain_sec / 3600.f);
1408 		disk_space_label.set_markup (label + buf + S_("hours|h"));
1409 	} else {
1410 		snprintf (buf, sizeof (buf), "%.0f", remain_sec / 60.f);
1411 		disk_space_label.set_markup (label + buf + S_("minutes|m"));
1412 	}
1413 
1414 }
1415 
1416 void
update_disk_space()1417 ARDOUR_UI::update_disk_space()
1418 {
1419 	if (_session == 0) {
1420 		format_disk_space_label (-1);
1421 		return;
1422 	}
1423 
1424 	boost::optional<samplecnt_t> opt_samples = _session->available_capture_duration();
1425 	samplecnt_t fr = _session->sample_rate();
1426 
1427 	if (fr == 0) {
1428 		/* skip update - no SR available */
1429 		format_disk_space_label (-1);
1430 		return;
1431 	}
1432 
1433 	if (!opt_samples) {
1434 		/* Available space is unknown */
1435 		format_disk_space_label (-1);
1436 	} else if (opt_samples.value_or (0) == max_samplecnt) {
1437 		format_disk_space_label (max_samplecnt);
1438 	} else {
1439 		rec_enabled_streams = 0;
1440 		_session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
1441 
1442 		samplecnt_t samples = opt_samples.value_or (0);
1443 
1444 		if (rec_enabled_streams) {
1445 			samples /= rec_enabled_streams;
1446 		}
1447 
1448 		format_disk_space_label (samples / (float)fr);
1449 	}
1450 
1451 }
1452 
1453 void
update_timecode_format()1454 ARDOUR_UI::update_timecode_format ()
1455 {
1456 	std::string label = string_compose (X_("<span weight=\"ultralight\">%1</span>: "), S_("Timecode|TC"));
1457 
1458 	if (_session) {
1459 		bool matching;
1460 		boost::shared_ptr<TimecodeTransportMaster> tcmaster;
1461 		boost::shared_ptr<TransportMaster> tm = TransportMasterManager::instance().current();
1462 
1463 		if ((tm->type() == LTC || tm->type() == MTC) && (tcmaster = boost::dynamic_pointer_cast<TimecodeTransportMaster>(tm)) != 0 && tm->locked()) {
1464 			matching = (tcmaster->apparent_timecode_format() == _session->config.get_timecode_format());
1465 		} else {
1466 			matching = true;
1467 		}
1468 
1469 		const char* const bg = matching ? "" : " background=\"red\" foreground=\"white\"";
1470 
1471 		timecode_format_label.set_markup (string_compose ("%1<span%2>%3</span>",
1472 					label, bg,
1473 					Timecode::timecode_format_name (_session->config.get_timecode_format()).c_str()));
1474 	} else {
1475 		timecode_format_label.set_markup (label + _("n/a"));
1476 	}
1477 
1478 }
1479 
1480 gint
update_wall_clock()1481 ARDOUR_UI::update_wall_clock ()
1482 {
1483 	time_t now;
1484 	struct tm *tm_now;
1485 	static int last_min = -1;
1486 
1487 	time (&now);
1488 	tm_now = localtime (&now);
1489 	if (last_min != tm_now->tm_min) {
1490 		char buf[16];
1491 		sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1492 		wall_clock_label.set_text (buf);
1493 		last_min = tm_now->tm_min;
1494 	}
1495 
1496 	return TRUE;
1497 }
1498 
1499 void
session_add_midi_route(bool disk,RouteGroup * route_group,uint32_t how_many,const string & name_template,bool strict_io,PluginInfoPtr instrument,Plugin::PresetRecord * pset,ARDOUR::PresentationInfo::order_t order)1500 ARDOUR_UI::session_add_midi_route (
1501 		bool disk,
1502 		RouteGroup* route_group,
1503 		uint32_t how_many,
1504 		const string& name_template,
1505 		bool strict_io,
1506 		PluginInfoPtr instrument,
1507 		Plugin::PresetRecord* pset,
1508 		ARDOUR::PresentationInfo::order_t order)
1509 {
1510 	if (_session == 0) {
1511 		warning << _("You cannot add a track without a session already loaded.") << endmsg;
1512 		return;
1513 	}
1514 
1515 	if (Profile->get_mixbus ()) {
1516 		strict_io = true;
1517 	}
1518 
1519 	try {
1520 		if (disk) {
1521 
1522 			ChanCount one_midi_channel;
1523 			one_midi_channel.set (DataType::MIDI, 1);
1524 
1525 			list<boost::shared_ptr<MidiTrack> > tracks;
1526 			tracks = _session->new_midi_track (one_midi_channel, one_midi_channel, strict_io, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
1527 
1528 			if (tracks.size() != how_many) {
1529 				error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
1530 			}
1531 
1532 		} else {
1533 
1534 			RouteList routes;
1535 			routes = _session->new_midi_route (route_group, how_many, name_template, strict_io, instrument, pset, PresentationInfo::MidiBus, order);
1536 
1537 			if (routes.size() != how_many) {
1538 				error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
1539 			}
1540 
1541 		}
1542 	}
1543 	catch (...) {
1544 		display_insufficient_ports_message ();
1545 		return;
1546 	}
1547 }
1548 
1549 void
session_add_audio_route(bool track,int32_t input_channels,int32_t output_channels,ARDOUR::TrackMode mode,RouteGroup * route_group,uint32_t how_many,string const & name_template,bool strict_io,ARDOUR::PresentationInfo::order_t order)1550 ARDOUR_UI::session_add_audio_route (
1551 	bool track,
1552 	int32_t input_channels,
1553 	int32_t output_channels,
1554 	ARDOUR::TrackMode mode,
1555 	RouteGroup* route_group,
1556 	uint32_t how_many,
1557 	string const & name_template,
1558 	bool strict_io,
1559 	ARDOUR::PresentationInfo::order_t order)
1560 {
1561 	list<boost::shared_ptr<AudioTrack> > tracks;
1562 	RouteList routes;
1563 
1564 	assert (_session);
1565 
1566 	try {
1567 		if (track) {
1568 			tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode);
1569 
1570 			if (tracks.size() != how_many) {
1571 				error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
1572 				      << endmsg;
1573 			}
1574 
1575 		} else {
1576 
1577 			routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order);
1578 
1579 			if (routes.size() != how_many) {
1580 				error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
1581 				      << endmsg;
1582 			}
1583 		}
1584 	}
1585 
1586 	catch (...) {
1587 		display_insufficient_ports_message ();
1588 		return;
1589 	}
1590 
1591 	if (strict_io) {
1592 		for (list<boost::shared_ptr<AudioTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
1593 			(*i)->set_strict_io (true);
1594 		}
1595 		for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
1596 			(*i)->set_strict_io (true);
1597 		}
1598 	}
1599 }
1600 
1601 void
session_add_foldback_bus(int32_t channels,uint32_t how_many,string const & name_template)1602 ARDOUR_UI::session_add_foldback_bus (int32_t channels, uint32_t how_many, string const & name_template)
1603 {
1604 	RouteList routes;
1605 
1606 	assert (_session);
1607 
1608 	try {
1609 		routes = _session->new_audio_route (channels, channels, 0, how_many, name_template, PresentationInfo::FoldbackBus, -1);
1610 
1611 		if (routes.size() != how_many) {
1612 			error << string_compose (P_("could not create %1 new foldback bus", "could not create %1 new foldback busses", how_many), how_many)
1613 			      << endmsg;
1614 		}
1615 	}
1616 
1617 	catch (...) {
1618 		display_insufficient_ports_message ();
1619 		return;
1620 	}
1621 }
1622 
1623 void
display_insufficient_ports_message()1624 ARDOUR_UI::display_insufficient_ports_message ()
1625 {
1626 	ArdourMessageDialog msg (_main_window,
1627 			string_compose (_("There are insufficient ports available\n\
1628 to create a new track or bus.\n\
1629 You should save %1, exit and\n\
1630 restart with more ports."), PROGRAM_NAME));
1631 	msg.run ();
1632 }
1633 
1634 void
transport_goto_start()1635 ARDOUR_UI::transport_goto_start ()
1636 {
1637 	if (_session) {
1638 		_session->goto_start ();
1639 
1640 		/* force displayed area in editor to start no matter
1641 		   what "follow playhead" setting is.
1642 		*/
1643 
1644 		if (editor) {
1645 			editor->center_screen (_session->current_start_sample ());
1646 		}
1647 	}
1648 }
1649 
1650 void
transport_goto_zero()1651 ARDOUR_UI::transport_goto_zero ()
1652 {
1653 	if (_session) {
1654 		_session->request_locate (0);
1655 
1656 		/* force displayed area in editor to start no matter
1657 		   what "follow playhead" setting is.
1658 		*/
1659 
1660 		if (editor) {
1661 			editor->reset_x_origin (0);
1662 		}
1663 	}
1664 }
1665 
1666 void
transport_goto_wallclock()1667 ARDOUR_UI::transport_goto_wallclock ()
1668 {
1669 	if (_session && editor) {
1670 
1671 		time_t now;
1672 		struct tm tmnow;
1673 		samplepos_t samples;
1674 
1675 		time (&now);
1676 		localtime_r (&now, &tmnow);
1677 
1678 		samplecnt_t sample_rate = _session->sample_rate();
1679 
1680 		if (sample_rate == 0) {
1681 			/* no frame rate available */
1682 			return;
1683 		}
1684 
1685 		samples = tmnow.tm_hour * (60 * 60 * sample_rate);
1686 		samples += tmnow.tm_min * (60 * sample_rate);
1687 		samples += tmnow.tm_sec * sample_rate;
1688 
1689 		_session->request_locate (samples);
1690 
1691 		/* force displayed area in editor to start no matter
1692 		   what "follow playhead" setting is.
1693 		*/
1694 
1695 		if (editor) {
1696 			editor->center_screen (samples);
1697 		}
1698 	}
1699 }
1700 
1701 void
transport_goto_end()1702 ARDOUR_UI::transport_goto_end ()
1703 {
1704 	if (_session) {
1705 		samplepos_t const sample = _session->current_end_sample();
1706 		_session->request_locate (sample);
1707 
1708 		/* force displayed area in editor to start no matter
1709 		   what "follow playhead" setting is.
1710 		*/
1711 
1712 		if (editor) {
1713 			editor->center_screen (sample);
1714 		}
1715 	}
1716 }
1717 
1718 void
transport_stop()1719 ARDOUR_UI::transport_stop ()
1720 {
1721 	if (!_session) {
1722 		return;
1723 	}
1724 
1725 	if (_session->is_auditioning()) {
1726 		_session->cancel_audition ();
1727 		return;
1728 	}
1729 
1730 	_session->request_stop (false, true);
1731 }
1732 
1733 /** Check if any tracks are record enabled. If none are, record enable all of them.
1734  * @return true if track record-enabled status was changed, false otherwise.
1735  */
1736 bool
trx_record_enable_all_tracks()1737 ARDOUR_UI::trx_record_enable_all_tracks ()
1738 {
1739 	if (!_session) {
1740 		return false;
1741 	}
1742 
1743 	boost::shared_ptr<RouteList> rl = _session->get_tracks ();
1744 	bool none_record_enabled = true;
1745 
1746 	for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
1747 		boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
1748 		assert (t);
1749 
1750 		if (t->rec_enable_control()->get_value()) {
1751 			none_record_enabled = false;
1752 			break;
1753 		}
1754 	}
1755 
1756 	if (none_record_enabled) {
1757 		_session->set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), 1.0, Controllable::NoGroup);
1758 	}
1759 
1760 	return none_record_enabled;
1761 }
1762 
1763 void
transport_record(bool roll)1764 ARDOUR_UI::transport_record (bool roll)
1765 {
1766 	if (_session) {
1767 		switch (_session->record_status()) {
1768 		case Session::Disabled:
1769 			if (_session->ntracks() == 0) {
1770 				ArdourMessageDialog 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."));
1771 				msg.run ();
1772 				return;
1773 			}
1774 			_session->maybe_enable_record ();
1775 			if (roll) {
1776 				transport_roll ();
1777 			}
1778 			break;
1779 		case Session::Recording:
1780 			if (roll) {
1781 				_session->request_stop();
1782 			} else {
1783 				_session->disable_record (false, true);
1784 			}
1785 			break;
1786 
1787 		case Session::Enabled:
1788 			if (roll) {
1789 				transport_roll();
1790 			} else {
1791 				_session->disable_record (false, true);
1792 			}
1793 		}
1794 	}
1795 }
1796 
1797 void
transport_roll()1798 ARDOUR_UI::transport_roll ()
1799 {
1800 	if (!_session) {
1801 		return;
1802 	}
1803 
1804 	if (_session->is_auditioning()) {
1805 		return;
1806 	}
1807 
1808 	if (_session->config.get_external_sync()) {
1809 		switch (TransportMasterManager::instance().current()->type()) {
1810 		case Engine:
1811 			break;
1812 		default:
1813 			/* transport controlled by the master */
1814 			return;
1815 		}
1816 	}
1817 
1818 	bool rolling = _session->transport_rolling();
1819 
1820 	if (_session->get_play_loop()) {
1821 
1822 		/* If loop playback is not a mode, then we should cancel
1823 		   it when this action is requested. If it is a mode
1824 		   we just leave it in place.
1825 		*/
1826 
1827 		if (!Config->get_loop_is_mode()) {
1828 			/* stop loop playback but keep transport state */
1829 			_session->request_play_loop (false, false);
1830 		}
1831 
1832 	} else if (_session->get_play_range () ) {
1833 		/* stop playing a range if we currently are */
1834 		_session->request_play_range (0, true);
1835 	}
1836 
1837 	if (!rolling) {
1838 		_session->request_roll ();
1839 	}
1840 }
1841 
1842 bool
get_smart_mode() const1843 ARDOUR_UI::get_smart_mode() const
1844 {
1845 	return ( editor->get_smart_mode() );
1846 }
1847 
1848 
1849 void
toggle_roll(bool with_abort,bool roll_out_of_bounded_mode)1850 ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
1851 {
1852 	if (!_session) {
1853 		return;
1854 	}
1855 
1856 	if (_session->is_auditioning()) {
1857 		_session->cancel_audition ();
1858 		return;
1859 	}
1860 
1861 	if (_session->config.get_external_sync()) {
1862 		switch (TransportMasterManager::instance().current()->type()) {
1863 		case Engine:
1864 			break;
1865 		default:
1866 			/* transport controlled by the master */
1867 			return;
1868 		}
1869 	}
1870 
1871 	bool rolling = _session->transport_rolling();
1872 
1873 	if (rolling) {
1874 
1875 		if (roll_out_of_bounded_mode) {
1876 			/* drop out of loop/range playback but leave transport rolling */
1877 
1878 			if (_session->get_play_loop()) {
1879 
1880 				if (_session->actively_recording()) {
1881 					/* actually stop transport because
1882 					   otherwise the captured data will make
1883 					   no sense.
1884 					*/
1885 					_session->request_play_loop (false, true);
1886 
1887 				} else {
1888 					_session->request_play_loop (false, false);
1889 				}
1890 
1891 			} else if (_session->get_play_range ()) {
1892 
1893 				_session->request_cancel_play_range ();
1894 			}
1895 
1896 		} else {
1897 			_session->request_stop (with_abort, true);
1898 		}
1899 
1900 	} else { /* not rolling */
1901 
1902 		if (with_abort) { /* with_abort == true means the command was intended to stop transport, not start. */
1903 			return;
1904 		}
1905 
1906 		if (_session->get_play_loop() && Config->get_loop_is_mode()) {
1907 			_session->request_locate (_session->locations()->auto_loop_location()->start(), MustRoll);
1908 		} else {
1909 			if (UIConfiguration::instance().get_follow_edits()) {
1910 				list<AudioRange>& range = editor->get_selection().time;
1911 				if (range.front().start == _session->transport_sample()) { // if playhead is exactly at the start of a range, we assume it was placed there by follow_edits
1912 					_session->request_play_range (&range, true);
1913 					_session->set_requested_return_sample (range.front().start);  //force an auto-return here
1914 				}
1915 			}
1916 			_session->request_roll ();
1917 		}
1918 	}
1919 }
1920 
1921 void
toggle_session_auto_loop()1922 ARDOUR_UI::toggle_session_auto_loop ()
1923 {
1924 	if (!_session) {
1925 		return;
1926 	}
1927 
1928 	Location * looploc = _session->locations()->auto_loop_location();
1929 
1930 	if (!looploc) {
1931 		return;
1932 	}
1933 
1934 	if (_session->get_play_loop()) {
1935 
1936 		/* looping enabled, our job is to disable it */
1937 
1938 		_session->request_play_loop (false);
1939 
1940 	} else {
1941 
1942 		/* looping not enabled, our job is to enable it.
1943 
1944 		   loop-is-NOT-mode: this action always starts the transport rolling.
1945 		   loop-IS-mode:     this action simply sets the loop play mechanism, but
1946 		                        does not start transport.
1947 		*/
1948 		if (Config->get_loop_is_mode()) {
1949 			_session->request_play_loop (true, false);
1950 		} else {
1951 			_session->request_play_loop (true, true);
1952 		}
1953 	}
1954 
1955 	//show the loop markers
1956 	looploc->set_hidden (false, this);
1957 }
1958 
1959 void
transport_play_selection()1960 ARDOUR_UI::transport_play_selection ()
1961 {
1962 	if (!_session) {
1963 		return;
1964 	}
1965 
1966 	editor->play_selection ();
1967 }
1968 
1969 void
transport_play_preroll()1970 ARDOUR_UI::transport_play_preroll ()
1971 {
1972 	if (!_session) {
1973 		return;
1974 	}
1975 	editor->play_with_preroll ();
1976 }
1977 
1978 void
transport_rec_preroll()1979 ARDOUR_UI::transport_rec_preroll ()
1980 {
1981 	if (!_session) {
1982 		return;
1983 	}
1984 	editor->rec_with_preroll ();
1985 }
1986 
1987 void
transport_rec_count_in()1988 ARDOUR_UI::transport_rec_count_in ()
1989 {
1990 	if (!_session) {
1991 		return;
1992 	}
1993 	editor->rec_with_count_in ();
1994 }
1995 
1996 void
transport_ffwd_rewind(bool fwd)1997 ARDOUR_UI::transport_ffwd_rewind (bool fwd)
1998 {
1999 	if (!_session) {
2000 		return;
2001 	}
2002 	// incrementally increase speed by semitones
2003 	// (keypress auto-repeat is 100ms)
2004 	const float maxspeed = Config->get_shuttle_max_speed();
2005 	float semitone_ratio = exp2f (1.0f/12.0f);
2006 	const float octave_down = powf (1.f / semitone_ratio, 12.f);
2007 	float transport_speed = _session->actual_speed();
2008 	float speed;
2009 
2010 	if (Config->get_rewind_ffwd_like_tape_decks()) {
2011 
2012 		if (fwd) {
2013 			if (transport_speed <= 0) {
2014 				_session->request_transport_speed (1.0, false);
2015 				_session->request_roll (TRS_UI);
2016 				return;
2017 			}
2018 		} else {
2019 			if (transport_speed >= 0) {
2020 				_session->request_transport_speed (-1.0, false);
2021 				_session->request_roll (TRS_UI);
2022 				return;
2023 			}
2024 		}
2025 
2026 
2027 	} else {
2028 
2029 		if (fabs (transport_speed) <= 0.1) {
2030 
2031 			/* close to zero, maybe flip direction */
2032 
2033 			if (fwd) {
2034 				if (transport_speed <= 0) {
2035 					_session->request_transport_speed (1.0, false);
2036 					_session->request_roll (TRS_UI);
2037 				}
2038 			} else {
2039 				if (transport_speed >= 0) {
2040 					_session->request_transport_speed (-1.0, false);
2041 					_session->request_roll (TRS_UI);
2042 				}
2043 			}
2044 
2045 			/* either we've just started, or we're moving as slowly as we
2046 			 * ever should
2047 			 */
2048 
2049 			return;
2050 		}
2051 
2052 		if (fwd) {
2053 			if (transport_speed < 0.f) {
2054 				if (fabs (transport_speed) < octave_down) {
2055 					/* we need to move the speed back towards zero */
2056 					semitone_ratio = powf (1.f / semitone_ratio, 4.f);
2057 				} else {
2058 					semitone_ratio = 1.f / semitone_ratio;
2059 				}
2060 			} else {
2061 				if (fabs (transport_speed) < octave_down) {
2062 					/* moving very slowly, use 4 semitone steps */
2063 					semitone_ratio = powf (semitone_ratio, 4.f);
2064 				}
2065 			}
2066 		} else {
2067 			if (transport_speed > 0.f) {
2068 				/* we need to move the speed back towards zero */
2069 
2070 				if (transport_speed < octave_down) {
2071 					semitone_ratio = powf (1.f / semitone_ratio, 4.f);
2072 				} else {
2073 					semitone_ratio = 1.f / semitone_ratio;
2074 				}
2075 			} else {
2076 				if (fabs (transport_speed) < octave_down) {
2077 					/* moving very slowly, use 4 semitone steps */
2078 					semitone_ratio = powf (semitone_ratio, 4.f);
2079 				}
2080 			}
2081 		}
2082 
2083 	}
2084 
2085 	speed = semitone_ratio * transport_speed;
2086 	speed = std::max (-maxspeed, std::min (maxspeed, speed));
2087 	_session->request_transport_speed (speed, false);
2088 	_session->request_roll (TRS_UI);
2089 
2090 }
2091 
2092 void
transport_rewind()2093 ARDOUR_UI::transport_rewind ()
2094 {
2095 	transport_ffwd_rewind (false);
2096 }
2097 
2098 void
transport_forward()2099 ARDOUR_UI::transport_forward ()
2100 {
2101 	transport_ffwd_rewind (true);
2102 }
2103 
2104 void
toggle_record_enable(uint16_t rid)2105 ARDOUR_UI::toggle_record_enable (uint16_t rid)
2106 {
2107 	if (!_session) {
2108 		return;
2109 	}
2110 
2111 	boost::shared_ptr<Route> r;
2112 
2113 	if ((r = _session->get_remote_nth_route (rid)) != 0) {
2114 
2115 		boost::shared_ptr<Track> t;
2116 
2117 		if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
2118 			t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup);
2119 		}
2120 	}
2121 }
2122 
2123 void
map_transport_state()2124 ARDOUR_UI::map_transport_state ()
2125 {
2126 	if (!_session) {
2127 		layered_button.set_sensitive (false);
2128 		if (UIConfiguration::instance().get_screen_saver_mode () == InhibitWhileRecording) {
2129 			inhibit_screensaver (false);
2130 		}
2131 		return;
2132 	}
2133 
2134 	shuttle_box.map_transport_state ();
2135 
2136 	float sp = _session->transport_speed();
2137 
2138 	if (sp != 0.0f) {
2139 		layered_button.set_sensitive (!_session->actively_recording ());
2140 	} else {
2141 		layered_button.set_sensitive (true);
2142 		update_disk_space ();
2143 	}
2144 	if (UIConfiguration::instance().get_screen_saver_mode () == InhibitWhileRecording) {
2145 		inhibit_screensaver (_session->actively_recording ());
2146 	}
2147 }
2148 
2149 void
blink_handler(bool blink_on)2150 ARDOUR_UI::blink_handler (bool blink_on)
2151 {
2152 	sync_blink (blink_on);
2153 
2154 	if (!UIConfiguration::instance().get_blink_alert_indicators()) {
2155 		blink_on = true;
2156 	}
2157 	error_blink (blink_on);
2158 	solo_blink (blink_on);
2159 	audition_blink (blink_on);
2160 	feedback_blink (blink_on);
2161 }
2162 
2163 void
update_clocks()2164 ARDOUR_UI::update_clocks ()
2165 {
2166 	if (!_session) return;
2167 
2168 	if (editor && !editor->dragging_playhead() && !editor->pending_locate_request()) {
2169 		Clock (_session->audible_sample()); /* EMIT_SIGNAL */
2170 	}
2171 }
2172 
2173 void
start_clocking()2174 ARDOUR_UI::start_clocking ()
2175 {
2176 	if (UIConfiguration::instance().get_super_rapid_clock_update()) {
2177 		clock_signal_connection = Timers::fps_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2178 	} else {
2179 		clock_signal_connection = Timers::rapid_connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
2180 	}
2181 }
2182 
2183 void
stop_clocking()2184 ARDOUR_UI::stop_clocking ()
2185 {
2186 	clock_signal_connection.disconnect ();
2187 }
2188 
2189 void
save_state(const string & name,bool switch_to_it)2190 ARDOUR_UI::save_state (const string & name, bool switch_to_it)
2191 {
2192 	if (!_session || _session->deletion_in_progress()) {
2193 		return;
2194 	}
2195 
2196 	if (_session->unnamed()) {
2197 		rename_session (true);
2198 	}
2199 
2200 	XMLNode* node = new XMLNode (X_("UI"));
2201 
2202 	WM::Manager::instance().add_state (*node);
2203 
2204 	node->add_child_nocopy (gui_object_state->get_state());
2205 
2206 	_session->add_extra_xml (*node);
2207 
2208 	if (export_video_dialog) {
2209 		_session->add_extra_xml (export_video_dialog->get_state());
2210 	}
2211 
2212 	save_state_canfail (name, switch_to_it);
2213 }
2214 
2215 int
save_state_canfail(string name,bool switch_to_it)2216 ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
2217 {
2218 	if (_session) {
2219 		int ret;
2220 
2221 		if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
2222 			return ret;
2223 		}
2224 	}
2225 
2226 	save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2227 	return 0;
2228 }
2229 
2230 void
primary_clock_value_changed()2231 ARDOUR_UI::primary_clock_value_changed ()
2232 {
2233 	if (_session) {
2234 		_session->request_locate (primary_clock->current_time ());
2235 	}
2236 }
2237 
2238 void
big_clock_value_changed()2239 ARDOUR_UI::big_clock_value_changed ()
2240 {
2241 	if (_session) {
2242 		_session->request_locate (big_clock->current_time ());
2243 	}
2244 }
2245 
2246 void
secondary_clock_value_changed()2247 ARDOUR_UI::secondary_clock_value_changed ()
2248 {
2249 	if (_session) {
2250 		_session->request_locate (secondary_clock->current_time ());
2251 	}
2252 }
2253 void
save_template_dialog_response(int response,SaveTemplateDialog * d)2254 ARDOUR_UI::save_template_dialog_response (int response, SaveTemplateDialog* d)
2255 {
2256 	if (response == RESPONSE_ACCEPT) {
2257 		const string name = d->get_template_name ();
2258 		const string desc = d->get_description ();
2259 
2260 		int failed = _session->save_template (name, desc);
2261 
2262 		if (failed == -2) { /* file already exists. */
2263 			bool overwrite = overwrite_file_dialog (*d,
2264 								_("Confirm Template Overwrite"),
2265 								_("A template already exists with that name. Do you want to overwrite it?"));
2266 
2267 			if (overwrite) {
2268 				_session->save_template (name, desc, true);
2269 			}
2270 			else {
2271 				d->show ();
2272 				return;
2273 			}
2274 		}
2275 	}
2276 	delete d;
2277 }
2278 
2279 void
save_template()2280 ARDOUR_UI::save_template ()
2281 {
2282 	const std::string desc = SessionMetadata::Metadata()->description ();
2283 	SaveTemplateDialog* d = new SaveTemplateDialog (_session->name (), desc);
2284 	d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::save_template_dialog_response), d));
2285 	d->show ();
2286 }
2287 
manage_templates()2288 void ARDOUR_UI::manage_templates ()
2289 {
2290 	TemplateDialog td;
2291 	td.run();
2292 }
2293 
2294 void
edit_metadata()2295 ARDOUR_UI::edit_metadata ()
2296 {
2297 	SessionMetadataEditor dialog;
2298 	dialog.set_session (_session);
2299 	dialog.grab_focus ();
2300 	dialog.run ();
2301 }
2302 
2303 void
import_metadata()2304 ARDOUR_UI::import_metadata ()
2305 {
2306 	SessionMetadataImporter dialog;
2307 	dialog.set_session (_session);
2308 	dialog.run ();
2309 }
2310 
_lua_print(std::string s)2311 static void _lua_print (std::string s) {
2312 #ifndef NDEBUG
2313 	std::cout << "LuaTemplate: " << s << "\n";
2314 #endif
2315 	PBD::info << "LuaTemplate: " << s << endmsg;
2316 }
2317 
2318 std::map<std::string, std::string>
route_setup_info(const std::string & script_path)2319 ARDOUR_UI::route_setup_info (const std::string& script_path)
2320 {
2321 	std::map<std::string, std::string> rv;
2322 
2323 	if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
2324 		return rv;
2325 	}
2326 
2327 	LuaState lua;
2328 	lua.Print.connect (&_lua_print);
2329 	lua.sandbox (true);
2330 
2331 	lua_State* L = lua.getState();
2332 	LuaInstance::register_classes (L);
2333 	LuaBindings::set_session (L, _session);
2334 	luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
2335 	lua_setglobal (L, "Editor");
2336 
2337 	lua.do_command ("function ardour () end");
2338 	lua.do_file (script_path);
2339 
2340 	try {
2341 		luabridge::LuaRef fn = luabridge::getGlobal (L, "route_setup");
2342 		if (!fn.isFunction ()) {
2343 			return rv;
2344 		}
2345 		luabridge::LuaRef rs = fn ();
2346 		if (!rs.isTable ()) {
2347 			return rv;
2348 		}
2349 		for (luabridge::Iterator i(rs); !i.isNil (); ++i) {
2350 			if (!i.key().isString()) {
2351 				continue;
2352 			}
2353 			std::string key = i.key().tostring();
2354 			if (i.value().isString() || i.value().isNumber() || i.value().isBoolean()) {
2355 				rv[key] = i.value().tostring();
2356 			}
2357 		}
2358 	} catch (luabridge::LuaException const& e) {
2359 #ifndef NDEBUG
2360 		cerr << "LuaException:" << e.what () << endl;
2361 #endif
2362 		PBD::warning << "LuaException: " << e.what () << endmsg;
2363 	} catch (...) { }
2364 	return rv;
2365 }
2366 
2367 void
meta_route_setup(const std::string & script_path)2368 ARDOUR_UI::meta_route_setup (const std::string& script_path)
2369 {
2370 	if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
2371 		return;
2372 	}
2373 	assert (add_route_dialog);
2374 
2375 	int count;
2376 	if ((count = add_route_dialog->count()) <= 0) {
2377 		return;
2378 	}
2379 
2380 	LuaState lua;
2381 	lua.Print.connect (&_lua_print);
2382 	lua.sandbox (true);
2383 
2384 	lua_State* L = lua.getState();
2385 	LuaInstance::register_classes (L);
2386 	LuaBindings::set_session (L, _session);
2387 	luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
2388 	lua_setglobal (L, "Editor");
2389 
2390 	lua.do_command ("function ardour () end");
2391 	lua.do_file (script_path);
2392 
2393 	luabridge::LuaRef args (luabridge::newTable (L));
2394 
2395 	args["name"]       = add_route_dialog->name_template ();
2396 	args["insert_at"]  = translate_order (add_route_dialog->insert_at());
2397 	args["group"]      = add_route_dialog->route_group ();
2398 	args["strict_io"]  = add_route_dialog->use_strict_io ();
2399 	args["instrument"] = add_route_dialog->requested_instrument ();
2400 	args["track_mode"] = add_route_dialog->mode ();
2401 	args["channels"]   = add_route_dialog->channel_count ();
2402 	args["how_many"]   = count;
2403 
2404 	try {
2405 		luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
2406 		if (fn.isFunction()) {
2407 			fn (args)();
2408 		}
2409 	} catch (luabridge::LuaException const& e) {
2410 #ifndef NDEBUG
2411 		cerr << "LuaException:" << e.what () << endl;
2412 #endif
2413 		PBD::warning << "LuaException: " << e.what () << endmsg;
2414 	} catch (...) {
2415 		display_insufficient_ports_message ();
2416 	}
2417 }
2418 
2419 void
meta_session_setup(const std::string & script_path)2420 ARDOUR_UI::meta_session_setup (const std::string& script_path)
2421 {
2422 	if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
2423 		return;
2424 	}
2425 
2426 	LuaState lua;
2427 	lua.Print.connect (&_lua_print);
2428 	lua.sandbox (true);
2429 
2430 	lua_State* L = lua.getState();
2431 	LuaInstance::register_classes (L);
2432 	LuaBindings::set_session (L, _session);
2433 	luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
2434 	lua_setglobal (L, "Editor");
2435 
2436 	lua.do_command ("function ardour () end");
2437 	lua.do_file (script_path);
2438 
2439 	try {
2440 		luabridge::LuaRef fn = luabridge::getGlobal (L, "factory");
2441 		if (fn.isFunction()) {
2442 			fn ()();
2443 		}
2444 	} catch (luabridge::LuaException const& e) {
2445 #ifndef NDEBUG
2446 		cerr << "LuaException:" << e.what () << endl;
2447 #endif
2448 		PBD::warning << "LuaException: " << e.what () << endmsg;
2449 	} catch (...) {
2450 		display_insufficient_ports_message ();
2451 	}
2452 }
2453 
2454 void
display_cleanup_results(ARDOUR::CleanupReport const & rep,const gchar * list_title,const bool msg_delete)2455 ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport const& rep, const gchar* list_title, const bool msg_delete)
2456 {
2457 	size_t removed;
2458 
2459 	removed = rep.paths.size();
2460 
2461 	if (removed == 0) {
2462 		ArdourMessageDialog msgd (_main_window,
2463 		                          _("No files were ready for clean-up"),
2464 		                          true,
2465 		                          Gtk::MESSAGE_INFO,
2466 		                          Gtk::BUTTONS_OK);
2467 		msgd.set_title (_("Clean-up"));
2468 		msgd.set_secondary_text (_("If this seems surprising, \n\
2469 check for any existing snapshots.\n\
2470 These may still include regions that\n\
2471 require some unused files to continue to exist."));
2472 
2473 		msgd.run ();
2474 		return;
2475 	}
2476 
2477 	ArdourDialog results (_("Clean-up"), true, false);
2478 
2479 	struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2480 		CleanupResultsModelColumns() {
2481 			add (visible_name);
2482 			add (fullpath);
2483 		}
2484 		Gtk::TreeModelColumn<std::string> visible_name;
2485 		Gtk::TreeModelColumn<std::string> fullpath;
2486 	};
2487 
2488 
2489 	CleanupResultsModelColumns results_columns;
2490 	Glib::RefPtr<Gtk::ListStore> results_model;
2491 	Gtk::TreeView results_display;
2492 
2493 	results_model = ListStore::create (results_columns);
2494 	results_display.set_model (results_model);
2495 	results_display.append_column (list_title, results_columns.visible_name);
2496 
2497 	results_display.set_name ("CleanupResultsList");
2498 	results_display.set_headers_visible (true);
2499 	results_display.set_headers_clickable (false);
2500 	results_display.set_reorderable (false);
2501 
2502 	Gtk::ScrolledWindow list_scroller;
2503 	Gtk::Label txt;
2504 	Gtk::VBox dvbox;
2505 	Gtk::HBox dhbox;  // the hbox for the image and text
2506 	Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2507 	Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2508 
2509 	dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2510 
2511 	const string dead_directory = _session->session_directory().dead_path();
2512 
2513 	/* subst:
2514 	   %1 - number of files removed
2515 	   %2 - location of "dead"
2516 	   %3 - size of files affected
2517 	   %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2518 	*/
2519 
2520 	const char* bprefix;
2521 	double space_adjusted = 0;
2522 
2523 	if (rep.space < 1000) {
2524 		bprefix = X_("");
2525 		space_adjusted = rep.space;
2526 	} else if (rep.space < 1000000) {
2527 		bprefix = _("kilo");
2528 		space_adjusted = floorf((float)rep.space / 1000.0);
2529 	} else if (rep.space < 1000000 * 1000) {
2530 		bprefix = _("mega");
2531 		space_adjusted = floorf((float)rep.space / (1000.0 * 1000.0));
2532 	} else {
2533 		bprefix = _("giga");
2534 		space_adjusted = floorf((float)rep.space / (1000.0 * 1000 * 1000.0));
2535 	}
2536 
2537 	if (msg_delete) {
2538 		txt.set_markup (string_compose (P_("\
2539 The following file was deleted from %2,\n\
2540 releasing %3 %4bytes of disk space", "\
2541 The following %1 files were deleted from %2,\n\
2542 releasing %3 %4bytes of disk space", removed),
2543 					removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
2544 	} else {
2545 		txt.set_markup (string_compose (P_("\
2546 The following file was not in use and \n\
2547 has been moved to: %2\n\n\
2548 After a restart of %5\n\n\
2549 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
2550 will release an additional %3 %4bytes of disk space.\n", "\
2551 The following %1 files were not in use and \n\
2552 have been moved to: %2\n\n\
2553 After a restart of %5\n\n\
2554 <span face=\"mono\">Session -> Clean-up -> Flush Wastebasket</span>\n\n\
2555 will release an additional %3 %4bytes of disk space.\n", removed),
2556 					removed, Gtkmm2ext::markup_escape_text (dead_directory), space_adjusted, bprefix, PROGRAM_NAME));
2557 	}
2558 
2559 	dhbox.pack_start (*dimage, true, false, 5);
2560 	dhbox.pack_start (txt, true, false, 5);
2561 
2562 	for (vector<string>::const_iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2563 		TreeModel::Row row = *(results_model->append());
2564 		row[results_columns.visible_name] = *i;
2565 		row[results_columns.fullpath] = *i;
2566 	}
2567 
2568 	list_scroller.add (results_display);
2569 	list_scroller.set_size_request (-1, 150);
2570 	list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2571 
2572 	dvbox.pack_start (dhbox, true, false, 5);
2573 	dvbox.pack_start (list_scroller, true, false, 5);
2574 	ddhbox.pack_start (dvbox, true, false, 5);
2575 
2576 	results.get_vbox()->pack_start (ddhbox, true, false, 5);
2577 	results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2578 	results.set_default_response (RESPONSE_CLOSE);
2579 	results.set_position (Gtk::WIN_POS_MOUSE);
2580 
2581 	results_display.show();
2582 	list_scroller.show();
2583 	txt.show();
2584 	dvbox.show();
2585 	dhbox.show();
2586 	ddhbox.show();
2587 	dimage->show();
2588 
2589 	//results.get_vbox()->show();
2590 	results.set_resizable (false);
2591 
2592 	results.run ();
2593 
2594 }
2595 
2596 void
cleanup()2597 ARDOUR_UI::cleanup ()
2598 {
2599 	if (_session == 0) {
2600 		/* shouldn't happen: menu item is insensitive */
2601 		return;
2602 	}
2603 
2604 
2605 	ArdourMessageDialog checker (_("Are you sure you want to clean-up?"),
2606 	                             true,
2607 	                             Gtk::MESSAGE_QUESTION,
2608 	                             Gtk::BUTTONS_NONE);
2609 
2610 	checker.set_title (_("Clean-up"));
2611 
2612 	checker.set_secondary_text(_("Clean-up is a destructive operation.\n\
2613 ALL undo/redo information will be lost if you clean-up.\n\
2614 Clean-up will move all unused files to a \"dead\" location."));
2615 
2616 	checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2617 	checker.add_button (_("Clean-up"), RESPONSE_ACCEPT);
2618 	checker.set_default_response (RESPONSE_CANCEL);
2619 
2620 	checker.set_name (_("CleanupDialog"));
2621 	checker.set_wmclass (X_("ardour_cleanup"), PROGRAM_NAME);
2622 	checker.set_position (Gtk::WIN_POS_MOUSE);
2623 
2624 	switch (checker.run()) {
2625 	case RESPONSE_ACCEPT:
2626 		break;
2627 	default:
2628 		return;
2629 	}
2630 	checker.hide();
2631 
2632 	ARDOUR::CleanupReport rep;
2633 
2634 	editor->prepare_for_cleanup ();
2635 
2636 	/* do not allow flush until a session is reloaded */
2637 	ActionManager::get_action (X_("Main"), X_("FlushWastebasket"))->set_sensitive (false);
2638 
2639 	if (_session->cleanup_sources (rep)) {
2640 		editor->finish_cleanup ();
2641 		return;
2642 	}
2643 
2644 	editor->finish_cleanup ();
2645 
2646 	display_cleanup_results (rep, _("Cleaned Files"), false);
2647 }
2648 
2649 void
flush_trash()2650 ARDOUR_UI::flush_trash ()
2651 {
2652 	if (_session == 0) {
2653 		/* shouldn't happen: menu item is insensitive */
2654 		return;
2655 	}
2656 
2657 	ARDOUR::CleanupReport rep;
2658 
2659 	if (_session->cleanup_trash_sources (rep)) {
2660 		return;
2661 	}
2662 
2663 	display_cleanup_results (rep, _("deleted file"), true);
2664 }
2665 
2666 void
cleanup_peakfiles()2667 ARDOUR_UI::cleanup_peakfiles ()
2668 {
2669 	if (_session == 0) {
2670 		/* shouldn't happen: menu item is insensitive */
2671 		return;
2672 	}
2673 
2674 	if (! _session->can_cleanup_peakfiles ()) {
2675 		return;
2676 	}
2677 
2678 	// get all region-views in this session
2679 	RegionSelection rs;
2680 	TrackViewList empty;
2681 	empty.clear();
2682 	editor->get_regions_after(rs, (samplepos_t) 0, empty);
2683 	std::list<RegionView*> views = rs.by_layer();
2684 
2685 	// remove displayed audio-region-views waveforms
2686 	for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
2687 		AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
2688 		if (!arv) { continue ; }
2689 		arv->delete_waves();
2690 	}
2691 
2692 	// cleanup peak files:
2693 	// - stop pending peakfile threads
2694 	// - close peakfiles if any
2695 	// - remove peak dir in session
2696 	// - setup peakfiles (background thread)
2697 	_session->cleanup_peakfiles ();
2698 
2699 	ArdourWaveView::WaveView::clear_cache ();
2700 
2701 	// re-add waves to ARV
2702 	for (list<RegionView*>::iterator i = views.begin(); i != views.end(); ++i) {
2703 		AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
2704 		if (!arv) { continue ; }
2705 		arv->create_waves();
2706 	}
2707 }
2708 
2709 PresentationInfo::order_t
translate_order(RouteDialogs::InsertAt place)2710 ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
2711 {
2712 	if (editor->get_selection().tracks.empty()) {
2713 		return place == RouteDialogs::First ? 0 : PresentationInfo::max_order;
2714 	}
2715 
2716 	PresentationInfo::order_t order_hint = PresentationInfo::max_order;
2717 
2718 	/*
2719 	  we want the new routes to have their order keys set starting from
2720 	  the highest order key in the selection + 1 (if available).
2721 	*/
2722 
2723 	if (place == RouteDialogs::AfterSelection) {
2724 		RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
2725 		if (rtav) {
2726 			order_hint = rtav->route()->presentation_info().order();
2727 			order_hint++;
2728 		}
2729 	} else if (place == RouteDialogs::BeforeSelection) {
2730 		RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
2731 		if (rtav) {
2732 			order_hint = rtav->route()->presentation_info().order();
2733 		}
2734 	} else if (place == RouteDialogs::First) {
2735 		order_hint = 0;
2736 	} else {
2737 		/* leave order_hint at max_order */
2738 	}
2739 
2740 	return order_hint;
2741 }
2742 
2743 void
start_duplicate_routes()2744 ARDOUR_UI::start_duplicate_routes ()
2745 {
2746 	if (!duplicate_routes_dialog) {
2747 		duplicate_routes_dialog = new DuplicateRouteDialog;
2748 	}
2749 
2750 	if (duplicate_routes_dialog->restart (_session)) {
2751 		return;
2752 	}
2753 
2754 	duplicate_routes_dialog->present ();
2755 }
2756 
2757 void
add_route()2758 ARDOUR_UI::add_route ()
2759 {
2760 	if (!_session || !_session->writable() || _session->actively_recording()) {
2761 		return;
2762 	}
2763 
2764 	if (!add_route_dialog.get (false)) {
2765 		add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
2766 	}
2767 
2768 	if (add_route_dialog->is_visible()) {
2769 		/* we're already doing this */
2770 		return;
2771 	}
2772 
2773 	add_route_dialog->set_position (WIN_POS_MOUSE);
2774 	add_route_dialog->present();
2775 }
2776 
2777 void
add_route_dialog_response(int r)2778 ARDOUR_UI::add_route_dialog_response (int r)
2779 {
2780 	if (!_session) {
2781 		warning << _("You cannot add tracks or busses without a session already loaded.") << endmsg;
2782 		return;
2783 	}
2784 
2785 	if (!AudioEngine::instance()->running ()) {
2786 		switch (r) {
2787 			case AddRouteDialog::Add:
2788 			case AddRouteDialog::AddAndClose:
2789 				break;
2790 			default:
2791 				return;
2792 		}
2793 		add_route_dialog->ArdourDialog::on_response (r);
2794 		ARDOUR_UI_UTILS::engine_is_running ();
2795 		return;
2796 	}
2797 
2798 	int count;
2799 
2800 	switch (r) {
2801 	case AddRouteDialog::Add:
2802 		add_route_dialog->reset_name_edited ();
2803 		break;
2804 	case AddRouteDialog::AddAndClose:
2805 		add_route_dialog->ArdourDialog::on_response (r);
2806 		break;
2807 	default:
2808 		add_route_dialog->ArdourDialog::on_response (r);
2809 		return;
2810 	}
2811 
2812 	std::string template_path = add_route_dialog->get_template_path();
2813 	if (!template_path.empty() && template_path.substr (0, 11) == "urn:ardour:") {
2814 		meta_route_setup (template_path.substr (11));
2815 		return;
2816 	}
2817 
2818 	if ((count = add_route_dialog->count()) <= 0) {
2819 		return;
2820 	}
2821 
2822 	PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
2823 	const string name_template = add_route_dialog->name_template ();
2824 	DisplaySuspender ds;
2825 
2826 	if (!template_path.empty ()) {
2827 		if (add_route_dialog->name_template_is_default ()) {
2828 			_session->new_route_from_template (count, order, template_path, string ());
2829 		} else {
2830 			_session->new_route_from_template (count, order, template_path, name_template);
2831 		}
2832 		return;
2833 	}
2834 
2835 	ChanCount input_chan= add_route_dialog->channels ();
2836 	ChanCount output_chan;
2837 	PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
2838 	RouteGroup* route_group = add_route_dialog->route_group ();
2839 	AutoConnectOption oac = Config->get_output_auto_connect();
2840 	bool strict_io = add_route_dialog->use_strict_io ();
2841 
2842 	if (oac & AutoConnectMaster) {
2843 		output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
2844 		output_chan.set (DataType::MIDI, 0);
2845 	} else {
2846 		output_chan = input_chan;
2847 	}
2848 
2849 	/* XXX do something with name template */
2850 
2851 	Session::ProcessorChangeBlocker pcb (_session);
2852 
2853 	switch (add_route_dialog->type_wanted()) {
2854 	case AddRouteDialog::AudioTrack:
2855 		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);
2856 		break;
2857 	case AddRouteDialog::AudioBus:
2858 		session_add_audio_route (false, input_chan.n_audio(), output_chan.n_audio(), ARDOUR::Normal, route_group, count, name_template, strict_io, order);
2859 		break;
2860 	case AddRouteDialog::MidiTrack:
2861 		session_add_midi_route (true, route_group, count, name_template, strict_io, instrument, 0, order);
2862 		break;
2863 	case AddRouteDialog::MidiBus:
2864 		session_add_midi_route (false, route_group, count, name_template, strict_io, instrument, 0, order);
2865 		break;
2866 	case AddRouteDialog::VCAMaster:
2867 		_session->vca_manager().create_vca (count, name_template);
2868 		break;
2869 	case AddRouteDialog::FoldbackBus:
2870 		session_add_foldback_bus (input_chan.n_audio(), count, name_template);
2871 		ActionManager::get_toggle_action (X_("Mixer"), X_("ToggleFoldbackStrip"))->set_active (true);
2872 		break;
2873 	}
2874 }
2875 
2876 void
disk_overrun_handler()2877 ARDOUR_UI::disk_overrun_handler ()
2878 {
2879 	ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_overrun_handler)
2880 
2881 	if (!have_disk_speed_dialog_displayed) {
2882 		have_disk_speed_dialog_displayed = true;
2883 		ArdourMessageDialog* msg = new ArdourMessageDialog (_main_window, string_compose (_("\
2884 The disk system on your computer\n\
2885 was not able to keep up with %1.\n\
2886 \n\
2887 Specifically, it failed to write data to disk\n\
2888 quickly enough to keep up with recording.\n"), PROGRAM_NAME));
2889 		msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2890 		msg->show ();
2891 	}
2892 }
2893 
2894 void
gui_idle_handler()2895 ARDOUR_UI::gui_idle_handler ()
2896 {
2897 	int timeout = 30;
2898 	/* due to idle calls, gtk_events_pending() may always return true */
2899 	while (gtk_events_pending() && --timeout) {
2900 		gtk_main_iteration ();
2901 	}
2902 }
2903 
2904 void
disk_underrun_handler()2905 ARDOUR_UI::disk_underrun_handler ()
2906 {
2907 	ENSURE_GUI_THREAD (*this, &ARDOUR_UI::disk_underrun_handler)
2908 
2909 	if (!have_disk_speed_dialog_displayed) {
2910 		have_disk_speed_dialog_displayed = true;
2911 		ArdourMessageDialog* msg = new ArdourMessageDialog (
2912 			_main_window, string_compose (_("The disk system on your computer\n\
2913 was not able to keep up with %1.\n\
2914 \n\
2915 Specifically, it failed to read data from disk\n\
2916 quickly enough to keep up with playback.\n"), PROGRAM_NAME));
2917 		msg->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2918 		msg->show ();
2919 	}
2920 }
2921 
2922 void
disk_speed_dialog_gone(int,MessageDialog * msg)2923 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
2924 {
2925 	have_disk_speed_dialog_displayed = false;
2926 	delete msg;
2927 }
2928 
2929 void
session_dialog(std::string msg)2930 ARDOUR_UI::session_dialog (std::string msg)
2931 {
2932 	ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
2933 	ArdourMessageDialog d (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
2934 	d.run ();
2935 }
2936 
2937 int
pending_state_dialog()2938 ARDOUR_UI::pending_state_dialog ()
2939 {
2940 	HBox* hbox = manage (new HBox());
2941 	Image* image = manage (new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG));
2942 	ArdourDialog dialog (_("Crash Recovery"), true);
2943 	Label  message (string_compose (_("\
2944 This session appears to have been modified\n\
2945 without save, or in middle of recording when\n\
2946 %1 or the computer was shutdown.\n\
2947 \n\
2948 %1 can recover any changes for\n\
2949 you, or it can ignore it. Please decide\n\
2950 what you would like to do.\n"), PROGRAM_NAME));
2951 	image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
2952 	hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
2953 	hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
2954 	dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
2955 	dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2956 	dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2957 	dialog.set_default_response (RESPONSE_ACCEPT);
2958 	dialog.set_position (WIN_POS_CENTER);
2959 	message.show();
2960 	image->show();
2961 	hbox->show();
2962 
2963 	Splash::instance()->hide ();
2964 
2965 	switch (dialog.run ()) {
2966 	case RESPONSE_ACCEPT:
2967 		return 1;
2968 	default:
2969 		return 0;
2970 	}
2971 }
2972 
2973 void
store_clock_modes()2974 ARDOUR_UI::store_clock_modes ()
2975 {
2976 	if (session_load_in_progress) {
2977 		/* Do not overwrite clock modes while loading them (with a session) */
2978 		return;
2979 	}
2980 
2981 	XMLNode* node = new XMLNode(X_("ClockModes"));
2982 
2983 	for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2984 		XMLNode* child = new XMLNode (X_("Clock"));
2985 
2986 		child->set_property (X_("name"), (*x)->name());
2987 		child->set_property (X_("mode"), (*x)->mode());
2988 		child->set_property (X_("on"), (*x)->on());
2989 
2990 		node->add_child_nocopy (*child);
2991 	}
2992 
2993 	_session->add_extra_xml (*node);
2994 	_session->set_dirty ();
2995 }
2996 
2997 /** Allocate our thread-local buffers */
2998 void
get_process_buffers()2999 ARDOUR_UI::get_process_buffers ()
3000 {
3001 	_process_thread->get_buffers ();
3002 }
3003 
3004 /** Drop our thread-local buffers */
3005 void
drop_process_buffers()3006 ARDOUR_UI::drop_process_buffers ()
3007 {
3008 	_process_thread->drop_buffers ();
3009 }
3010 
3011 void
feedback_detected()3012 ARDOUR_UI::feedback_detected ()
3013 {
3014 	_feedback_exists = true;
3015 }
3016 
3017 void
successful_graph_sort()3018 ARDOUR_UI::successful_graph_sort ()
3019 {
3020 	_feedback_exists = false;
3021 }
3022 
3023 void
midi_panic()3024 ARDOUR_UI::midi_panic ()
3025 {
3026 	if (_session) {
3027 		_session->midi_panic();
3028 	}
3029 }
3030 
3031 void
reset_peak_display()3032 ARDOUR_UI::reset_peak_display ()
3033 {
3034 	if (!_session || !_session->master_out() || !editor_meter) return;
3035 	_clear_editor_meter = true;
3036 }
3037 
3038 void
reset_group_peak_display(RouteGroup * group)3039 ARDOUR_UI::reset_group_peak_display (RouteGroup* group)
3040 {
3041 	if (!_session || !_session->master_out()) return;
3042 	if (group == _session->master_out()->route_group()) {
3043 		reset_peak_display ();
3044 	}
3045 }
3046 
3047 void
reset_route_peak_display(Route * route)3048 ARDOUR_UI::reset_route_peak_display (Route* route)
3049 {
3050 	if (!_session || !_session->master_out()) return;
3051 	if (_session->master_out().get() == route) {
3052 		reset_peak_display ();
3053 	}
3054 }
3055 
3056 void
hide_application()3057 ARDOUR_UI::hide_application ()
3058 {
3059 	Application::instance ()-> hide ();
3060 }
3061 
3062 void
setup_toplevel_window(Gtk::Window & window,const string & name,void * owner)3063 ARDOUR_UI::setup_toplevel_window (Gtk::Window& window, const string& name, void* owner)
3064 {
3065 	/* icons, titles, WM stuff */
3066 
3067 	static list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
3068 
3069 	if (window_icons.empty()) {
3070 		Glib::RefPtr<Gdk::Pixbuf> icon;
3071 		if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
3072 			window_icons.push_back (icon);
3073 		}
3074 		if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
3075 			window_icons.push_back (icon);
3076 		}
3077 		if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
3078 			window_icons.push_back (icon);
3079 		}
3080 		if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
3081 			window_icons.push_back (icon);
3082 		}
3083 	}
3084 
3085 	if (!window_icons.empty()) {
3086 		window.set_default_icon_list (window_icons);
3087 	}
3088 
3089 	Gtkmm2ext::WindowTitle title (Glib::get_application_name());
3090 
3091 	if (!name.empty()) {
3092 		title += name;
3093 	}
3094 
3095 	window.set_title (title.get_string());
3096 	window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
3097 
3098 	window.set_flags (CAN_FOCUS);
3099 	window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
3100 
3101 	/* This is a hack to ensure that GTK-accelerators continue to
3102 	 * work. Once we switch over to entirely native bindings, this will be
3103 	 * unnecessary and should be removed
3104 	 */
3105 	window.add_accel_group (ActionManager::ui_manager->get_accel_group());
3106 
3107 	window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
3108 	window.signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::tabbed_window_state_event_handler), owner));
3109 	window.signal_key_press_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
3110 	window.signal_key_release_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::key_event_handler), &window), false);
3111 }
3112