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/plugin_manager.h"
74 #include "ardour/process_thread.h"
75 #include "ardour/profile.h"
76 #include "ardour/region.h"
77 #include "ardour/rc_configuration.h"
78 #include "ardour/route_group.h"
79 #include "ardour/runtime_functions.h"
80 #include "ardour/session.h"
81 #include "ardour/session_event.h"
82 #include "ardour/source_factory.h"
83 #include "ardour/utils.h"
85 #include "audiographer/routines.h"
87 #if defined (__APPLE__)
88 #include <Carbon/Carbon.h> // For Gestalt
93 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
94 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
95 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
97 using namespace ARDOUR;
101 compute_peak_t ARDOUR::compute_peak = 0;
102 find_peaks_t ARDOUR::find_peaks = 0;
103 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
104 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
105 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
107 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
109 void ARDOUR::setup_enum_writer ();
111 /* this is useful for quite a few things that want to check
112 if any bounds-related property has changed
114 PBD::PropertyChange ARDOUR::bounds_change;
117 namespace Properties {
119 /* the envelope and fades are not scalar items and so
120 currently (2010/02) are not stored using Property.
121 However, these descriptors enable us to notify
122 about changes to them via PropertyChange.
124 Declared in ardour/audioregion.h ...
127 PBD::PropertyDescriptor<bool> fade_in;
128 PBD::PropertyDescriptor<bool> fade_out;
129 PBD::PropertyDescriptor<bool> envelope;
134 ARDOUR::make_property_quarks ()
136 Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
137 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in.property_id));
138 Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
139 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out.property_id));
140 Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
141 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id));
145 setup_hardware_optimization (bool try_optimization)
147 bool generic_mix_functions = true;
149 if (try_optimization) {
153 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
157 info << "Using SSE optimized routines" << endmsg;
160 compute_peak = x86_sse_compute_peak;
161 find_peaks = x86_sse_find_peaks;
162 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
163 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
164 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
166 generic_mix_functions = false;
170 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
173 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
176 if (sysVersion >= 0x00001040) { // Tiger at least
177 compute_peak = veclib_compute_peak;
178 find_peaks = veclib_find_peaks;
179 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
180 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
181 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
183 generic_mix_functions = false;
185 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
189 /* consider FPU denormal handling to be "h/w optimization" */
194 if (generic_mix_functions) {
196 compute_peak = default_compute_peak;
197 find_peaks = default_find_peaks;
198 apply_gain_to_buffer = default_apply_gain_to_buffer;
199 mix_buffers_with_gain = default_mix_buffers_with_gain;
200 mix_buffers_no_gain = default_mix_buffers_no_gain;
202 info << "No H/W specific optimizations in use" << endmsg;
205 AudioGrapher::Routines::override_compute_peak (compute_peak);
206 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
210 lotsa_files_please ()
214 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
216 rl.rlim_cur = rl.rlim_max;
218 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
219 if (rl.rlim_cur == RLIM_INFINITY) {
220 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
222 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
225 if (rl.rlim_cur == RLIM_INFINITY) {
226 info << _("Removed open file count limit. Excellent!") << endmsg;
228 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
232 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
237 ARDOUR::init (bool use_vst, bool try_optimization)
239 if (!Glib::thread_supported()) {
243 (void) bindtextdomain(PACKAGE, LOCALEDIR);
246 SessionEvent::init_event_pool ();
248 make_property_quarks ();
249 SessionObject::make_property_quarks ();
250 Region::make_property_quarks ();
251 MidiRegion::make_property_quarks ();
252 AudioRegion::make_property_quarks ();
253 RouteGroup::make_property_quarks ();
254 Playlist::make_property_quarks ();
255 AudioPlaylist::make_property_quarks ();
257 /* this is a useful ready to use PropertyChange that many
258 things need to check. This avoids having to compose
259 it every time we want to check for any of the relevant
263 bounds_change.add (ARDOUR::Properties::start);
264 bounds_change.add (ARDOUR::Properties::position);
265 bounds_change.add (ARDOUR::Properties::length);
267 /* provide a state version for the few cases that need it and are not
268 driven by reading state from disk (e.g. undo/redo)
271 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
273 setup_enum_writer ();
275 // allow ardour the absolute maximum number of open files
276 lotsa_files_please ();
279 Library = new AudioLibrary;
281 BootMessage (_("Loading configuration"));
283 Config = new RCConfiguration;
285 if (Config->load_state ()) {
289 Config->set_use_vst (use_vst);
291 Profile = new RuntimeProfile;
295 if (Config->get_use_vst() && fst_init (0)) {
300 #ifdef HAVE_AUDIOUNITS
301 AUPluginInfo::load_cached_info ();
304 /* Make VAMP look in our library ahead of anything else */
306 char *p = getenv ("VAMP_PATH");
307 string vamppath = VAMP_DIR;
312 setenv ("VAMP_PATH", vamppath.c_str(), 1);
315 setup_hardware_optimization (try_optimization);
317 SourceFactory::init ();
320 /* singleton - first object is "it" */
321 new PluginManager ();
323 ProcessThread::init ();
324 BufferManager::init (10); // XX should be num_processors_for_dsp
330 ARDOUR::init_post_engine ()
332 /* the MIDI Manager is needed by the ControlProtocolManager */
333 MIDI::Manager::create (AudioEngine::instance()->jack());
335 ControlProtocolManager::instance().discover_control_protocols ();
338 if ((node = Config->control_protocol_state()) != 0) {
339 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
342 MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
350 delete &ControlProtocolManager::instance();
358 ARDOUR::get_ardour_revision ()
364 ARDOUR::find_bindings_files (map<string,string>& files)
366 vector<sys::path> found;
367 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
369 if (getenv ("ARDOUR_SAE")) {
370 Glib::PatternSpec pattern("*SAE-*.bindings");
371 find_matching_files_in_search_path (spath, pattern, found);
373 Glib::PatternSpec pattern("*.bindings");
374 find_matching_files_in_search_path (spath, pattern, found);
381 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
383 pair<string,string> namepath;
384 namepath.second = path.to_string();
385 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
386 files.insert (namepath);
391 ARDOUR::no_auto_connect()
393 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
400 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
401 // valgrind doesn't understand this assembler stuff
402 // September 10th, 2007
406 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
411 /* XXX use real code to determine if the processor supports
412 DenormalsAreZero and FlushToZero
415 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
419 MXCSR = _mm_getcsr();
421 switch (Config->get_denormal_model()) {
423 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
427 if (fpu.has_flush_to_zero()) {
428 MXCSR |= _MM_FLUSH_ZERO_ON;
433 MXCSR &= ~_MM_FLUSH_ZERO_ON;
434 if (fpu.has_denormals_are_zero()) {
440 if (fpu.has_flush_to_zero()) {
441 if (fpu.has_denormals_are_zero()) {
442 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
444 MXCSR |= _MM_FLUSH_ZERO_ON;
456 ARDOUR::coverage (framepos_t sa, framepos_t ea,
457 framepos_t sb, framepos_t eb)
459 /* OverlapType returned reflects how the second (B)
460 range overlaps the first (A).
462 The diagrams show various relative placements
463 of A and B for each OverlapType.
466 Internal: the start points cannot coincide
467 External: the start and end points can coincide
468 Start: end points can coincide
469 End: start points can coincide
471 XXX Logically, Internal should disallow end
476 |--------------------| A
478 |-----------------| B
485 if ((sb > sa) && (eb <= ea)) {
486 return OverlapInternal;
490 |--------------------| A
492 -----------------------| B
495 "B overlaps the start of A"
499 if ((eb >= sa) && (eb <= ea)) {
503 |---------------------| A
505 |----------------------- B
508 "B overlaps the end of A"
511 if ((sb > sa) && (sb <= ea)) {
515 |--------------------| A
516 -------------------------- B
517 |----------------------- B
518 ----------------------| B
519 |--------------------| B
522 "B overlaps all of A"
524 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
525 return OverlapExternal;
532 ARDOUR::translation_kill_path ()
534 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
538 ARDOUR::translations_are_disabled ()
540 /* if file does not exist, we don't translate (bundled ardour only) */
541 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;