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();
331 // Initialize parameter metadata
332 EventTypeMap::instance().new_parameter(NullAutomation);
333 EventTypeMap::instance().new_parameter(GainAutomation);
334 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
335 EventTypeMap::instance().new_parameter(PanElevationAutomation);
336 EventTypeMap::instance().new_parameter(PanWidthAutomation);
337 EventTypeMap::instance().new_parameter(PluginAutomation);
338 EventTypeMap::instance().new_parameter(SoloAutomation);
339 EventTypeMap::instance().new_parameter(MuteAutomation);
340 EventTypeMap::instance().new_parameter(MidiCCAutomation);
341 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
342 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
343 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
344 EventTypeMap::instance().new_parameter(FadeInAutomation);
345 EventTypeMap::instance().new_parameter(FadeOutAutomation);
346 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
347 EventTypeMap::instance().new_parameter(MidiCCAutomation);
353 ARDOUR::init_post_engine ()
355 /* the MIDI Manager is needed by the ControlProtocolManager */
356 MIDI::Manager::create (AudioEngine::instance()->jack());
358 ControlProtocolManager::instance().discover_control_protocols ();
361 if ((node = Config->control_protocol_state()) != 0) {
362 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
371 delete &ControlProtocolManager::instance();
379 ARDOUR::find_bindings_files (map<string,string>& files)
381 vector<sys::path> found;
382 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
384 if (getenv ("ARDOUR_SAE")) {
385 Glib::PatternSpec pattern("*SAE-*.bindings");
386 find_matching_files_in_search_path (spath, pattern, found);
388 Glib::PatternSpec pattern("*.bindings");
389 find_matching_files_in_search_path (spath, pattern, found);
396 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
398 pair<string,string> namepath;
399 namepath.second = path.to_string();
400 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
401 files.insert (namepath);
406 ARDOUR::no_auto_connect()
408 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
415 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
416 // valgrind doesn't understand this assembler stuff
417 // September 10th, 2007
421 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
426 /* XXX use real code to determine if the processor supports
427 DenormalsAreZero and FlushToZero
430 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
434 MXCSR = _mm_getcsr();
436 switch (Config->get_denormal_model()) {
438 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
442 if (fpu.has_flush_to_zero()) {
443 MXCSR |= _MM_FLUSH_ZERO_ON;
448 MXCSR &= ~_MM_FLUSH_ZERO_ON;
449 if (fpu.has_denormals_are_zero()) {
455 if (fpu.has_flush_to_zero()) {
456 if (fpu.has_denormals_are_zero()) {
457 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
459 MXCSR |= _MM_FLUSH_ZERO_ON;
471 ARDOUR::coverage (framepos_t sa, framepos_t ea,
472 framepos_t sb, framepos_t eb)
474 /* OverlapType returned reflects how the second (B)
475 range overlaps the first (A).
477 The diagrams show various relative placements
478 of A and B for each OverlapType.
481 Internal: the start points cannot coincide
482 External: the start and end points can coincide
483 Start: end points can coincide
484 End: start points can coincide
486 XXX Logically, Internal should disallow end
491 |--------------------| A
493 |-----------------| B
500 if ((sb > sa) && (eb <= ea)) {
501 return OverlapInternal;
505 |--------------------| A
507 -----------------------| B
510 "B overlaps the start of A"
514 if ((eb >= sa) && (eb <= ea)) {
518 |---------------------| A
520 |----------------------- B
523 "B overlaps the end of A"
526 if ((sb > sa) && (sb <= ea)) {
530 |--------------------| A
531 -------------------------- B
532 |----------------------- B
533 ----------------------| B
534 |--------------------| B
537 "B overlaps all of A"
539 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
540 return OverlapExternal;
547 ARDOUR::translation_kill_path ()
549 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
553 ARDOUR::translations_are_disabled ()
555 /* if file does not exist, we don't translate (bundled ardour only) */
556 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;