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>
36 #ifdef HAVE_AUDIOUNITS
37 #include "ardour/audio_unit.h"
41 #include <xmmintrin.h>
44 #include <glibmm/fileutils.h>
45 #include <glibmm/miscutils.h>
49 #include "pbd/error.h"
51 #include "pbd/strsplit.h"
53 #include "pbd/file_utils.h"
54 #include "pbd/enumwriter.h"
56 #include "midi++/port.h"
57 #include "midi++/manager.h"
58 #include "midi++/mmc.h"
60 #include "ardour/analyser.h"
61 #include "ardour/ardour.h"
62 #include "ardour/audio_library.h"
63 #include "ardour/audioengine.h"
64 #include "ardour/audioregion.h"
65 #include "ardour/audiosource.h"
66 #include "ardour/buffer_manager.h"
67 #include "ardour/control_protocol_manager.h"
68 #include "ardour/debug.h"
69 #include "ardour/filesystem_paths.h"
70 #include "ardour/midi_region.h"
71 #include "ardour/mix.h"
72 #include "ardour/audioplaylist.h"
73 #include "ardour/panner_manager.h"
74 #include "ardour/plugin_manager.h"
75 #include "ardour/process_thread.h"
76 #include "ardour/profile.h"
77 #include "ardour/region.h"
78 #include "ardour/rc_configuration.h"
79 #include "ardour/route_group.h"
80 #include "ardour/runtime_functions.h"
81 #include "ardour/session.h"
82 #include "ardour/session_event.h"
83 #include "ardour/source_factory.h"
84 #include "ardour/utils.h"
86 #include "audiographer/routines.h"
88 #if defined (__APPLE__)
89 #include <Carbon/Carbon.h> // For Gestalt
94 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
95 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
96 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
98 using namespace ARDOUR;
102 compute_peak_t ARDOUR::compute_peak = 0;
103 find_peaks_t ARDOUR::find_peaks = 0;
104 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
105 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
106 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
108 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
110 void ARDOUR::setup_enum_writer ();
112 /* this is useful for quite a few things that want to check
113 if any bounds-related property has changed
115 PBD::PropertyChange ARDOUR::bounds_change;
118 namespace Properties {
120 /* the envelope and fades are not scalar items and so
121 currently (2010/02) are not stored using Property.
122 However, these descriptors enable us to notify
123 about changes to them via PropertyChange.
125 Declared in ardour/audioregion.h ...
128 PBD::PropertyDescriptor<bool> fade_in;
129 PBD::PropertyDescriptor<bool> fade_out;
130 PBD::PropertyDescriptor<bool> envelope;
135 ARDOUR::make_property_quarks ()
137 Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
138 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in.property_id));
139 Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
140 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out.property_id));
141 Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
142 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id));
146 setup_hardware_optimization (bool try_optimization)
148 bool generic_mix_functions = true;
150 if (try_optimization) {
154 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
158 info << "Using SSE optimized routines" << endmsg;
161 compute_peak = x86_sse_compute_peak;
162 find_peaks = x86_sse_find_peaks;
163 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
164 // mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
165 mix_buffers_with_gain = default_mix_buffers_with_gain;
166 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
168 generic_mix_functions = false;
172 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
175 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
178 if (sysVersion >= 0x00001040) { // Tiger at least
179 compute_peak = veclib_compute_peak;
180 find_peaks = veclib_find_peaks;
181 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
182 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
183 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
185 generic_mix_functions = false;
187 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
191 /* consider FPU denormal handling to be "h/w optimization" */
196 if (generic_mix_functions) {
198 compute_peak = default_compute_peak;
199 find_peaks = default_find_peaks;
200 apply_gain_to_buffer = default_apply_gain_to_buffer;
201 mix_buffers_with_gain = default_mix_buffers_with_gain;
202 mix_buffers_no_gain = default_mix_buffers_no_gain;
204 info << "No H/W specific optimizations in use" << endmsg;
207 AudioGrapher::Routines::override_compute_peak (compute_peak);
208 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
212 lotsa_files_please ()
216 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
218 rl.rlim_cur = rl.rlim_max;
220 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
221 if (rl.rlim_cur == RLIM_INFINITY) {
222 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
224 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
227 if (rl.rlim_cur == RLIM_INFINITY) {
228 info << _("Removed open file count limit. Excellent!") << endmsg;
230 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
234 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
239 ARDOUR::init (bool use_vst, bool try_optimization)
241 if (!Glib::thread_supported()) {
245 (void) bindtextdomain(PACKAGE, LOCALEDIR);
248 SessionEvent::init_event_pool ();
250 make_property_quarks ();
251 SessionObject::make_property_quarks ();
252 Region::make_property_quarks ();
253 MidiRegion::make_property_quarks ();
254 AudioRegion::make_property_quarks ();
255 RouteGroup::make_property_quarks ();
256 Playlist::make_property_quarks ();
257 AudioPlaylist::make_property_quarks ();
259 /* this is a useful ready to use PropertyChange that many
260 things need to check. This avoids having to compose
261 it every time we want to check for any of the relevant
265 bounds_change.add (ARDOUR::Properties::start);
266 bounds_change.add (ARDOUR::Properties::position);
267 bounds_change.add (ARDOUR::Properties::length);
269 /* provide a state version for the few cases that need it and are not
270 driven by reading state from disk (e.g. undo/redo)
273 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
275 setup_enum_writer ();
277 // allow ardour the absolute maximum number of open files
278 lotsa_files_please ();
281 Library = new AudioLibrary;
283 BootMessage (_("Loading configuration"));
285 Config = new RCConfiguration;
287 if (Config->load_state ()) {
291 Config->set_use_vst (use_vst);
293 Profile = new RuntimeProfile;
297 if (Config->get_use_vst() && fst_init (0)) {
302 #ifdef HAVE_AUDIOUNITS
303 AUPluginInfo::load_cached_info ();
306 /* Make VAMP look in our library ahead of anything else */
308 char *p = getenv ("VAMP_PATH");
309 string vamppath = VAMP_DIR;
314 setenv ("VAMP_PATH", vamppath.c_str(), 1);
317 setup_hardware_optimization (try_optimization);
319 SourceFactory::init ();
322 /* singleton - first object is "it" */
323 new PluginManager ();
325 ProcessThread::init ();
326 BufferManager::init (10); // XX should be num_processors_for_dsp
328 PannerManager::instance().discover_panners();
334 ARDOUR::init_post_engine ()
336 /* the MIDI Manager is needed by the ControlProtocolManager */
337 MIDI::Manager::create (AudioEngine::instance()->jack());
339 ControlProtocolManager::instance().discover_control_protocols ();
342 if ((node = Config->control_protocol_state()) != 0) {
343 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
352 delete &ControlProtocolManager::instance();
360 ARDOUR::find_bindings_files (map<string,string>& files)
362 vector<sys::path> found;
363 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
365 if (getenv ("ARDOUR_SAE")) {
366 Glib::PatternSpec pattern("*SAE-*.bindings");
367 find_matching_files_in_search_path (spath, pattern, found);
369 Glib::PatternSpec pattern("*.bindings");
370 find_matching_files_in_search_path (spath, pattern, found);
377 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
379 pair<string,string> namepath;
380 namepath.second = path.to_string();
381 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
382 files.insert (namepath);
387 ARDOUR::no_auto_connect()
389 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
396 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
397 // valgrind doesn't understand this assembler stuff
398 // September 10th, 2007
402 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
407 /* XXX use real code to determine if the processor supports
408 DenormalsAreZero and FlushToZero
411 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
415 MXCSR = _mm_getcsr();
417 switch (Config->get_denormal_model()) {
419 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
423 if (fpu.has_flush_to_zero()) {
424 MXCSR |= _MM_FLUSH_ZERO_ON;
429 MXCSR &= ~_MM_FLUSH_ZERO_ON;
430 if (fpu.has_denormals_are_zero()) {
436 if (fpu.has_flush_to_zero()) {
437 if (fpu.has_denormals_are_zero()) {
438 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
440 MXCSR |= _MM_FLUSH_ZERO_ON;
452 ARDOUR::coverage (framepos_t sa, framepos_t ea,
453 framepos_t sb, framepos_t eb)
455 /* OverlapType returned reflects how the second (B)
456 range overlaps the first (A).
458 The diagrams show various relative placements
459 of A and B for each OverlapType.
462 Internal: the start points cannot coincide
463 External: the start and end points can coincide
464 Start: end points can coincide
465 End: start points can coincide
467 XXX Logically, Internal should disallow end
472 |--------------------| A
474 |-----------------| B
481 if ((sb > sa) && (eb <= ea)) {
482 return OverlapInternal;
486 |--------------------| A
488 -----------------------| B
491 "B overlaps the start of A"
495 if ((eb >= sa) && (eb <= ea)) {
499 |---------------------| A
501 |----------------------- B
504 "B overlaps the end of A"
507 if ((sb > sa) && (sb <= ea)) {
511 |--------------------| A
512 -------------------------- B
513 |----------------------- B
514 ----------------------| B
515 |--------------------| B
518 "B overlaps all of A"
520 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
521 return OverlapExternal;
528 ARDOUR::translation_kill_path ()
530 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
534 ARDOUR::translations_are_disabled ()
536 /* if file does not exist, we don't translate (bundled ardour only) */
537 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;