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::get_ardour_revision ()
365 ARDOUR::find_bindings_files (map<string,string>& files)
367 vector<sys::path> found;
368 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
370 if (getenv ("ARDOUR_SAE")) {
371 Glib::PatternSpec pattern("*SAE-*.bindings");
372 find_matching_files_in_search_path (spath, pattern, found);
374 Glib::PatternSpec pattern("*.bindings");
375 find_matching_files_in_search_path (spath, pattern, found);
382 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
384 pair<string,string> namepath;
385 namepath.second = path.to_string();
386 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
387 files.insert (namepath);
392 ARDOUR::no_auto_connect()
394 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
401 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
402 // valgrind doesn't understand this assembler stuff
403 // September 10th, 2007
407 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
412 /* XXX use real code to determine if the processor supports
413 DenormalsAreZero and FlushToZero
416 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
420 MXCSR = _mm_getcsr();
422 switch (Config->get_denormal_model()) {
424 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
428 if (fpu.has_flush_to_zero()) {
429 MXCSR |= _MM_FLUSH_ZERO_ON;
434 MXCSR &= ~_MM_FLUSH_ZERO_ON;
435 if (fpu.has_denormals_are_zero()) {
441 if (fpu.has_flush_to_zero()) {
442 if (fpu.has_denormals_are_zero()) {
443 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
445 MXCSR |= _MM_FLUSH_ZERO_ON;
457 ARDOUR::coverage (framepos_t sa, framepos_t ea,
458 framepos_t sb, framepos_t eb)
460 /* OverlapType returned reflects how the second (B)
461 range overlaps the first (A).
463 The diagrams show various relative placements
464 of A and B for each OverlapType.
467 Internal: the start points cannot coincide
468 External: the start and end points can coincide
469 Start: end points can coincide
470 End: start points can coincide
472 XXX Logically, Internal should disallow end
477 |--------------------| A
479 |-----------------| B
486 if ((sb > sa) && (eb <= ea)) {
487 return OverlapInternal;
491 |--------------------| A
493 -----------------------| B
496 "B overlaps the start of A"
500 if ((eb >= sa) && (eb <= ea)) {
504 |---------------------| A
506 |----------------------- B
509 "B overlaps the end of A"
512 if ((sb > sa) && (sb <= ea)) {
516 |--------------------| A
517 -------------------------- B
518 |----------------------- B
519 ----------------------| B
520 |--------------------| B
523 "B overlaps all of A"
525 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
526 return OverlapExternal;
533 ARDOUR::translation_kill_path ()
535 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
539 ARDOUR::translations_are_disabled ()
541 /* if file does not exist, we don't translate (bundled ardour only) */
542 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;