2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "libardour-config.h"
23 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
25 #include <sys/types.h>
27 #include <sys/resource.h>
37 #include "ardour/vstfx.h"
40 #ifdef AUDIOUNIT_SUPPORT
41 #include "ardour/audio_unit.h"
45 #include <xmmintrin.h>
48 #include <glibmm/fileutils.h>
49 #include <glibmm/miscutils.h>
53 #include "pbd/error.h"
55 #include "pbd/strsplit.h"
57 #include "pbd/file_utils.h"
58 #include "pbd/enumwriter.h"
60 #include "midi++/port.h"
61 #include "midi++/manager.h"
62 #include "midi++/mmc.h"
64 #include "ardour/analyser.h"
65 #include "ardour/ardour.h"
66 #include "ardour/audio_library.h"
67 #include "ardour/audioengine.h"
68 #include "ardour/audioregion.h"
69 #include "ardour/audiosource.h"
70 #include "ardour/buffer_manager.h"
71 #include "ardour/control_protocol_manager.h"
72 #include "ardour/dB.h"
73 #include "ardour/debug.h"
74 #include "ardour/filesystem_paths.h"
75 #include "ardour/midi_region.h"
76 #include "ardour/mix.h"
77 #include "ardour/audioplaylist.h"
78 #include "ardour/panner_manager.h"
79 #include "ardour/plugin_manager.h"
80 #include "ardour/process_thread.h"
81 #include "ardour/profile.h"
82 #include "ardour/region.h"
83 #include "ardour/rc_configuration.h"
84 #include "ardour/route_group.h"
85 #include "ardour/runtime_functions.h"
86 #include "ardour/session.h"
87 #include "ardour/session_event.h"
88 #include "ardour/source_factory.h"
89 #include "ardour/utils.h"
91 #include "audiographer/routines.h"
93 #if defined (__APPLE__)
94 #include <Carbon/Carbon.h> // For Gestalt
99 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
100 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
101 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
103 using namespace ARDOUR;
107 compute_peak_t ARDOUR::compute_peak = 0;
108 find_peaks_t ARDOUR::find_peaks = 0;
109 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
110 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
111 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
113 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
115 void ARDOUR::setup_enum_writer ();
117 /* this is useful for quite a few things that want to check
118 if any bounds-related property has changed
120 PBD::PropertyChange ARDOUR::bounds_change;
123 namespace Properties {
125 /* the envelope and fades are not scalar items and so
126 currently (2010/02) are not stored using Property.
127 However, these descriptors enable us to notify
128 about changes to them via PropertyChange.
130 Declared in ardour/audioregion.h ...
133 PBD::PropertyDescriptor<bool> fade_in;
134 PBD::PropertyDescriptor<bool> fade_out;
135 PBD::PropertyDescriptor<bool> envelope;
140 ARDOUR::make_property_quarks ()
142 Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
143 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in.property_id));
144 Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
145 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out.property_id));
146 Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
147 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id));
151 setup_hardware_optimization (bool try_optimization)
153 bool generic_mix_functions = true;
155 if (try_optimization) {
159 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
163 info << "Using SSE optimized routines" << endmsg;
166 compute_peak = x86_sse_compute_peak;
167 find_peaks = x86_sse_find_peaks;
168 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
169 // mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
170 mix_buffers_with_gain = default_mix_buffers_with_gain;
171 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
173 generic_mix_functions = false;
177 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
180 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
183 if (sysVersion >= 0x00001040) { // Tiger at least
184 compute_peak = veclib_compute_peak;
185 find_peaks = veclib_find_peaks;
186 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
187 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
188 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
190 generic_mix_functions = false;
192 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
196 /* consider FPU denormal handling to be "h/w optimization" */
201 if (generic_mix_functions) {
203 compute_peak = default_compute_peak;
204 find_peaks = default_find_peaks;
205 apply_gain_to_buffer = default_apply_gain_to_buffer;
206 mix_buffers_with_gain = default_mix_buffers_with_gain;
207 mix_buffers_no_gain = default_mix_buffers_no_gain;
209 info << "No H/W specific optimizations in use" << endmsg;
212 AudioGrapher::Routines::override_compute_peak (compute_peak);
213 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
217 lotsa_files_please ()
221 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
223 rl.rlim_cur = rl.rlim_max;
225 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
226 if (rl.rlim_cur == RLIM_INFINITY) {
227 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
229 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
232 if (rl.rlim_cur == RLIM_INFINITY) {
233 info << _("Removed open file count limit. Excellent!") << endmsg;
235 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
239 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
244 ARDOUR::init (bool use_vst, bool try_optimization)
246 if (!Glib::thread_supported()) {
250 (void) bindtextdomain(PACKAGE, LOCALEDIR);
253 SessionEvent::init_event_pool ();
255 make_property_quarks ();
256 SessionObject::make_property_quarks ();
257 Region::make_property_quarks ();
258 MidiRegion::make_property_quarks ();
259 AudioRegion::make_property_quarks ();
260 RouteGroup::make_property_quarks ();
261 Playlist::make_property_quarks ();
262 AudioPlaylist::make_property_quarks ();
264 /* this is a useful ready to use PropertyChange that many
265 things need to check. This avoids having to compose
266 it every time we want to check for any of the relevant
270 bounds_change.add (ARDOUR::Properties::start);
271 bounds_change.add (ARDOUR::Properties::position);
272 bounds_change.add (ARDOUR::Properties::length);
274 /* provide a state version for the few cases that need it and are not
275 driven by reading state from disk (e.g. undo/redo)
278 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
280 setup_enum_writer ();
282 // allow ardour the absolute maximum number of open files
283 lotsa_files_please ();
286 Library = new AudioLibrary;
288 BootMessage (_("Loading configuration"));
290 Config = new RCConfiguration;
292 if (Config->load_state ()) {
296 Config->set_use_vst (use_vst);
298 Config->set_use_lxvst(true);
301 Profile = new RuntimeProfile;
305 if (Config->get_use_vst() && fst_init (0)) {
311 if (Config->get_use_lxvst() && vstfx_init (0)) {
316 #ifdef AUDIOUNIT_SUPPORT
317 AUPluginInfo::load_cached_info ();
320 /* Make VAMP look in our library ahead of anything else */
322 char *p = getenv ("VAMP_PATH");
323 string vamppath = VAMP_DIR;
328 setenv ("VAMP_PATH", vamppath.c_str(), 1);
331 setup_hardware_optimization (try_optimization);
333 SourceFactory::init ();
336 /* singleton - first object is "it" */
337 new PluginManager ();
339 ProcessThread::init ();
340 BufferManager::init (10); // XX should be num_processors_for_dsp
342 PannerManager::instance().discover_panners();
344 // Initialize parameter metadata
345 EventTypeMap::instance().new_parameter(NullAutomation);
346 EventTypeMap::instance().new_parameter(GainAutomation);
347 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
348 EventTypeMap::instance().new_parameter(PanElevationAutomation);
349 EventTypeMap::instance().new_parameter(PanWidthAutomation);
350 EventTypeMap::instance().new_parameter(PluginAutomation);
351 EventTypeMap::instance().new_parameter(SoloAutomation);
352 EventTypeMap::instance().new_parameter(MuteAutomation);
353 EventTypeMap::instance().new_parameter(MidiCCAutomation);
354 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
355 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
356 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
357 EventTypeMap::instance().new_parameter(FadeInAutomation);
358 EventTypeMap::instance().new_parameter(FadeOutAutomation);
359 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
360 EventTypeMap::instance().new_parameter(MidiCCAutomation);
366 ARDOUR::init_post_engine ()
368 /* the MIDI Manager is needed by the ControlProtocolManager */
369 MIDI::Manager::create (AudioEngine::instance()->jack());
371 ControlProtocolManager::instance().discover_control_protocols ();
374 if ((node = Config->control_protocol_state()) != 0) {
375 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
384 delete &ControlProtocolManager::instance();
396 ARDOUR::find_bindings_files (map<string,string>& files)
398 vector<sys::path> found;
399 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
401 if (getenv ("ARDOUR_SAE")) {
402 Glib::PatternSpec pattern("*SAE-*.bindings");
403 find_matching_files_in_search_path (spath, pattern, found);
405 Glib::PatternSpec pattern("*.bindings");
406 find_matching_files_in_search_path (spath, pattern, found);
413 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
415 pair<string,string> namepath;
416 namepath.second = path.to_string();
417 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
418 files.insert (namepath);
423 ARDOUR::no_auto_connect()
425 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
432 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
433 // valgrind doesn't understand this assembler stuff
434 // September 10th, 2007
438 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
443 /* XXX use real code to determine if the processor supports
444 DenormalsAreZero and FlushToZero
447 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
451 MXCSR = _mm_getcsr();
453 switch (Config->get_denormal_model()) {
455 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
459 if (fpu.has_flush_to_zero()) {
460 MXCSR |= _MM_FLUSH_ZERO_ON;
465 MXCSR &= ~_MM_FLUSH_ZERO_ON;
466 if (fpu.has_denormals_are_zero()) {
472 if (fpu.has_flush_to_zero()) {
473 if (fpu.has_denormals_are_zero()) {
474 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
476 MXCSR |= _MM_FLUSH_ZERO_ON;
488 ARDOUR::coverage (framepos_t sa, framepos_t ea,
489 framepos_t sb, framepos_t eb)
491 /* OverlapType returned reflects how the second (B)
492 range overlaps the first (A).
494 The diagrams show various relative placements
495 of A and B for each OverlapType.
498 Internal: the start points cannot coincide
499 External: the start and end points can coincide
500 Start: end points can coincide
501 End: start points can coincide
503 XXX Logically, Internal should disallow end
508 |--------------------| A
510 |-----------------| B
517 if ((sb > sa) && (eb <= ea)) {
518 return OverlapInternal;
522 |--------------------| A
524 -----------------------| B
527 "B overlaps the start of A"
531 if ((eb >= sa) && (eb <= ea)) {
535 |---------------------| A
537 |----------------------- B
540 "B overlaps the end of A"
543 if ((sb > sa) && (sb <= ea)) {
547 |--------------------| A
548 -------------------------- B
549 |----------------------- B
550 ----------------------| B
551 |--------------------| B
554 "B overlaps all of A"
556 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
557 return OverlapExternal;
564 ARDOUR::translation_kill_path ()
566 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
570 ARDOUR::translations_are_disabled ()
572 /* if file does not exist, we don't translate (bundled ardour only) */
573 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;