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/dB.h"
69 #include "ardour/debug.h"
70 #include "ardour/filesystem_paths.h"
71 #include "ardour/midi_region.h"
72 #include "ardour/mix.h"
73 #include "ardour/audioplaylist.h"
74 #include "ardour/panner_manager.h"
75 #include "ardour/plugin_manager.h"
76 #include "ardour/process_thread.h"
77 #include "ardour/profile.h"
78 #include "ardour/region.h"
79 #include "ardour/rc_configuration.h"
80 #include "ardour/route_group.h"
81 #include "ardour/runtime_functions.h"
82 #include "ardour/session.h"
83 #include "ardour/session_event.h"
84 #include "ardour/source_factory.h"
85 #include "ardour/utils.h"
87 #include "audiographer/routines.h"
89 #if defined (__APPLE__)
90 #include <Carbon/Carbon.h> // For Gestalt
95 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
96 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
97 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
99 using namespace ARDOUR;
103 compute_peak_t ARDOUR::compute_peak = 0;
104 find_peaks_t ARDOUR::find_peaks = 0;
105 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
106 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
107 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
109 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
111 void ARDOUR::setup_enum_writer ();
113 /* this is useful for quite a few things that want to check
114 if any bounds-related property has changed
116 PBD::PropertyChange ARDOUR::bounds_change;
119 namespace Properties {
121 /* the envelope and fades are not scalar items and so
122 currently (2010/02) are not stored using Property.
123 However, these descriptors enable us to notify
124 about changes to them via PropertyChange.
126 Declared in ardour/audioregion.h ...
129 PBD::PropertyDescriptor<bool> fade_in;
130 PBD::PropertyDescriptor<bool> fade_out;
131 PBD::PropertyDescriptor<bool> envelope;
136 ARDOUR::make_property_quarks ()
138 Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
139 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in.property_id));
140 Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
141 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out.property_id));
142 Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
143 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id));
147 setup_hardware_optimization (bool try_optimization)
149 bool generic_mix_functions = true;
151 if (try_optimization) {
155 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
159 info << "Using SSE optimized routines" << endmsg;
162 compute_peak = x86_sse_compute_peak;
163 find_peaks = x86_sse_find_peaks;
164 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
165 // mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
166 mix_buffers_with_gain = default_mix_buffers_with_gain;
167 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
169 generic_mix_functions = false;
173 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
176 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
179 if (sysVersion >= 0x00001040) { // Tiger at least
180 compute_peak = veclib_compute_peak;
181 find_peaks = veclib_find_peaks;
182 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
183 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
184 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
186 generic_mix_functions = false;
188 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
192 /* consider FPU denormal handling to be "h/w optimization" */
197 if (generic_mix_functions) {
199 compute_peak = default_compute_peak;
200 find_peaks = default_find_peaks;
201 apply_gain_to_buffer = default_apply_gain_to_buffer;
202 mix_buffers_with_gain = default_mix_buffers_with_gain;
203 mix_buffers_no_gain = default_mix_buffers_no_gain;
205 info << "No H/W specific optimizations in use" << endmsg;
208 AudioGrapher::Routines::override_compute_peak (compute_peak);
209 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
213 lotsa_files_please ()
217 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
219 rl.rlim_cur = rl.rlim_max;
221 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
222 if (rl.rlim_cur == RLIM_INFINITY) {
223 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
225 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
228 if (rl.rlim_cur == RLIM_INFINITY) {
229 info << _("Removed open file count limit. Excellent!") << endmsg;
231 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
235 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
240 ARDOUR::init (bool use_vst, bool try_optimization)
242 if (!Glib::thread_supported()) {
246 (void) bindtextdomain(PACKAGE, LOCALEDIR);
249 SessionEvent::init_event_pool ();
251 make_property_quarks ();
252 SessionObject::make_property_quarks ();
253 Region::make_property_quarks ();
254 MidiRegion::make_property_quarks ();
255 AudioRegion::make_property_quarks ();
256 RouteGroup::make_property_quarks ();
257 Playlist::make_property_quarks ();
258 AudioPlaylist::make_property_quarks ();
260 /* this is a useful ready to use PropertyChange that many
261 things need to check. This avoids having to compose
262 it every time we want to check for any of the relevant
266 bounds_change.add (ARDOUR::Properties::start);
267 bounds_change.add (ARDOUR::Properties::position);
268 bounds_change.add (ARDOUR::Properties::length);
270 /* provide a state version for the few cases that need it and are not
271 driven by reading state from disk (e.g. undo/redo)
274 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
276 setup_enum_writer ();
278 // allow ardour the absolute maximum number of open files
279 lotsa_files_please ();
282 Library = new AudioLibrary;
284 BootMessage (_("Loading configuration"));
286 Config = new RCConfiguration;
288 if (Config->load_state ()) {
292 Config->set_use_vst (use_vst);
294 Profile = new RuntimeProfile;
298 if (Config->get_use_vst() && fst_init (0)) {
303 #ifdef HAVE_AUDIOUNITS
304 AUPluginInfo::load_cached_info ();
307 /* Make VAMP look in our library ahead of anything else */
309 char *p = getenv ("VAMP_PATH");
310 string vamppath = VAMP_DIR;
315 setenv ("VAMP_PATH", vamppath.c_str(), 1);
318 setup_hardware_optimization (try_optimization);
320 SourceFactory::init ();
323 /* singleton - first object is "it" */
324 new PluginManager ();
326 ProcessThread::init ();
327 BufferManager::init (10); // XX should be num_processors_for_dsp
329 PannerManager::instance().discover_panners();
335 ARDOUR::init_post_engine ()
337 /* the MIDI Manager is needed by the ControlProtocolManager */
338 MIDI::Manager::create (AudioEngine::instance()->jack());
340 ControlProtocolManager::instance().discover_control_protocols ();
343 if ((node = Config->control_protocol_state()) != 0) {
344 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
353 delete &ControlProtocolManager::instance();
361 ARDOUR::find_bindings_files (map<string,string>& files)
363 vector<sys::path> found;
364 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
366 if (getenv ("ARDOUR_SAE")) {
367 Glib::PatternSpec pattern("*SAE-*.bindings");
368 find_matching_files_in_search_path (spath, pattern, found);
370 Glib::PatternSpec pattern("*.bindings");
371 find_matching_files_in_search_path (spath, pattern, found);
378 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
380 pair<string,string> namepath;
381 namepath.second = path.to_string();
382 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
383 files.insert (namepath);
388 ARDOUR::no_auto_connect()
390 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
397 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
398 // valgrind doesn't understand this assembler stuff
399 // September 10th, 2007
403 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
408 /* XXX use real code to determine if the processor supports
409 DenormalsAreZero and FlushToZero
412 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
416 MXCSR = _mm_getcsr();
418 switch (Config->get_denormal_model()) {
420 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
424 if (fpu.has_flush_to_zero()) {
425 MXCSR |= _MM_FLUSH_ZERO_ON;
430 MXCSR &= ~_MM_FLUSH_ZERO_ON;
431 if (fpu.has_denormals_are_zero()) {
437 if (fpu.has_flush_to_zero()) {
438 if (fpu.has_denormals_are_zero()) {
439 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
441 MXCSR |= _MM_FLUSH_ZERO_ON;
453 ARDOUR::coverage (framepos_t sa, framepos_t ea,
454 framepos_t sb, framepos_t eb)
456 /* OverlapType returned reflects how the second (B)
457 range overlaps the first (A).
459 The diagrams show various relative placements
460 of A and B for each OverlapType.
463 Internal: the start points cannot coincide
464 External: the start and end points can coincide
465 Start: end points can coincide
466 End: start points can coincide
468 XXX Logically, Internal should disallow end
473 |--------------------| A
475 |-----------------| B
482 if ((sb > sa) && (eb <= ea)) {
483 return OverlapInternal;
487 |--------------------| A
489 -----------------------| B
492 "B overlaps the start of A"
496 if ((eb >= sa) && (eb <= ea)) {
500 |---------------------| A
502 |----------------------- B
505 "B overlaps the end of A"
508 if ((sb > sa) && (sb <= ea)) {
512 |--------------------| A
513 -------------------------- B
514 |----------------------- B
515 ----------------------| B
516 |--------------------| B
519 "B overlaps all of A"
521 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
522 return OverlapExternal;
529 ARDOUR::translation_kill_path ()
531 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
535 ARDOUR::translations_are_disabled ()
537 /* if file does not exist, we don't translate (bundled ardour only) */
538 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;