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_no_gain = x86_sse_mix_buffers_no_gain;
167 generic_mix_functions = false;
171 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
174 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
177 if (sysVersion >= 0x00001040) { // Tiger at least
178 compute_peak = veclib_compute_peak;
179 find_peaks = veclib_find_peaks;
180 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
181 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
182 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
184 generic_mix_functions = false;
186 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
190 /* consider FPU denormal handling to be "h/w optimization" */
195 if (generic_mix_functions) {
197 compute_peak = default_compute_peak;
198 find_peaks = default_find_peaks;
199 apply_gain_to_buffer = default_apply_gain_to_buffer;
200 mix_buffers_with_gain = default_mix_buffers_with_gain;
201 mix_buffers_no_gain = default_mix_buffers_no_gain;
203 info << "No H/W specific optimizations in use" << endmsg;
206 AudioGrapher::Routines::override_compute_peak (compute_peak);
207 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
211 lotsa_files_please ()
215 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
217 rl.rlim_cur = rl.rlim_max;
219 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
220 if (rl.rlim_cur == RLIM_INFINITY) {
221 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
223 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
226 if (rl.rlim_cur == RLIM_INFINITY) {
227 info << _("Removed open file count limit. Excellent!") << endmsg;
229 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
233 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
238 ARDOUR::init (bool use_vst, bool try_optimization)
240 if (!Glib::thread_supported()) {
244 (void) bindtextdomain(PACKAGE, LOCALEDIR);
247 SessionEvent::init_event_pool ();
249 make_property_quarks ();
250 SessionObject::make_property_quarks ();
251 Region::make_property_quarks ();
252 MidiRegion::make_property_quarks ();
253 AudioRegion::make_property_quarks ();
254 RouteGroup::make_property_quarks ();
255 Playlist::make_property_quarks ();
256 AudioPlaylist::make_property_quarks ();
258 /* this is a useful ready to use PropertyChange that many
259 things need to check. This avoids having to compose
260 it every time we want to check for any of the relevant
264 bounds_change.add (ARDOUR::Properties::start);
265 bounds_change.add (ARDOUR::Properties::position);
266 bounds_change.add (ARDOUR::Properties::length);
268 /* provide a state version for the few cases that need it and are not
269 driven by reading state from disk (e.g. undo/redo)
272 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
274 setup_enum_writer ();
276 // allow ardour the absolute maximum number of open files
277 lotsa_files_please ();
280 Library = new AudioLibrary;
282 BootMessage (_("Loading configuration"));
284 Config = new RCConfiguration;
286 if (Config->load_state ()) {
290 Config->set_use_vst (use_vst);
292 Profile = new RuntimeProfile;
296 if (Config->get_use_vst() && fst_init (0)) {
301 #ifdef HAVE_AUDIOUNITS
302 AUPluginInfo::load_cached_info ();
305 /* Make VAMP look in our library ahead of anything else */
307 char *p = getenv ("VAMP_PATH");
308 string vamppath = VAMP_DIR;
313 setenv ("VAMP_PATH", vamppath.c_str(), 1);
316 setup_hardware_optimization (try_optimization);
318 SourceFactory::init ();
321 /* singleton - first object is "it" */
322 new PluginManager ();
324 ProcessThread::init ();
325 BufferManager::init (10); // XX should be num_processors_for_dsp
327 PannerManager::instance().discover_panners();
333 ARDOUR::init_post_engine ()
335 /* the MIDI Manager is needed by the ControlProtocolManager */
336 MIDI::Manager::create (AudioEngine::instance()->jack());
338 ControlProtocolManager::instance().discover_control_protocols ();
341 if ((node = Config->control_protocol_state()) != 0) {
342 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
351 delete &ControlProtocolManager::instance();
359 ARDOUR::find_bindings_files (map<string,string>& files)
361 vector<sys::path> found;
362 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
364 if (getenv ("ARDOUR_SAE")) {
365 Glib::PatternSpec pattern("*SAE-*.bindings");
366 find_matching_files_in_search_path (spath, pattern, found);
368 Glib::PatternSpec pattern("*.bindings");
369 find_matching_files_in_search_path (spath, pattern, found);
376 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
378 pair<string,string> namepath;
379 namepath.second = path.to_string();
380 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
381 files.insert (namepath);
386 ARDOUR::no_auto_connect()
388 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
395 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
396 // valgrind doesn't understand this assembler stuff
397 // September 10th, 2007
401 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
406 /* XXX use real code to determine if the processor supports
407 DenormalsAreZero and FlushToZero
410 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
414 MXCSR = _mm_getcsr();
416 switch (Config->get_denormal_model()) {
418 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
422 if (fpu.has_flush_to_zero()) {
423 MXCSR |= _MM_FLUSH_ZERO_ON;
428 MXCSR &= ~_MM_FLUSH_ZERO_ON;
429 if (fpu.has_denormals_are_zero()) {
435 if (fpu.has_flush_to_zero()) {
436 if (fpu.has_denormals_are_zero()) {
437 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
439 MXCSR |= _MM_FLUSH_ZERO_ON;
451 ARDOUR::coverage (framepos_t sa, framepos_t ea,
452 framepos_t sb, framepos_t eb)
454 /* OverlapType returned reflects how the second (B)
455 range overlaps the first (A).
457 The diagrams show various relative placements
458 of A and B for each OverlapType.
461 Internal: the start points cannot coincide
462 External: the start and end points can coincide
463 Start: end points can coincide
464 End: start points can coincide
466 XXX Logically, Internal should disallow end
471 |--------------------| A
473 |-----------------| B
480 if ((sb > sa) && (eb <= ea)) {
481 return OverlapInternal;
485 |--------------------| A
487 -----------------------| B
490 "B overlaps the start of A"
494 if ((eb >= sa) && (eb <= ea)) {
498 |---------------------| A
500 |----------------------- B
503 "B overlaps the end of A"
506 if ((sb > sa) && (sb <= ea)) {
510 |--------------------| A
511 -------------------------- B
512 |----------------------- B
513 ----------------------| B
514 |--------------------| B
517 "B overlaps all of A"
519 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
520 return OverlapExternal;
527 ARDOUR::translation_kill_path ()
529 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
533 ARDOUR::translations_are_disabled ()
535 /* if file does not exist, we don't translate (bundled ardour only) */
536 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;