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>
32 #ifdef WINDOWS_VST_SUPPORT
37 #include "ardour/linux_vst_support.h"
40 #ifdef AUDIOUNIT_SUPPORT
41 #include "ardour/audio_unit.h"
45 #include <xmmintrin.h>
48 #include <glibmm/fileutils.h>
49 #include <glibmm/miscutils.h>
53 #include "pbd/error.h"
55 #include "pbd/strsplit.h"
57 #include "pbd/file_utils.h"
58 #include "pbd/enumwriter.h"
60 #include "midi++/port.h"
61 #include "midi++/manager.h"
62 #include "midi++/mmc.h"
64 #include "ardour/analyser.h"
65 #include "ardour/audio_library.h"
66 #include "ardour/audioengine.h"
67 #include "ardour/audioplaylist.h"
68 #include "ardour/audioregion.h"
69 #include "ardour/buffer_manager.h"
70 #include "ardour/control_protocol_manager.h"
71 #include "ardour/filesystem_paths.h"
72 #include "ardour/midi_region.h"
73 #include "ardour/mix.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/rc_configuration.h"
79 #include "ardour/region.h"
80 #include "ardour/route_group.h"
81 #include "ardour/runtime_functions.h"
82 #include "ardour/session_event.h"
83 #include "ardour/source_factory.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;
110 extern void 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)
174 SInt32 sysVersion = 0;
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_windows_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 ARDOUR::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_windows_vst (use_windows_vst);
294 Config->set_use_lxvst(true);
297 Profile = new RuntimeProfile;
300 #ifdef WINDOWS_VST_SUPPORT
301 if (Config->get_use_windows_vst() && fst_init (0)) {
307 if (Config->get_use_lxvst() && vstfx_init (0)) {
312 #ifdef AUDIOUNIT_SUPPORT
313 AUPluginInfo::load_cached_info ();
316 setup_hardware_optimization (try_optimization);
318 SourceFactory::init ();
321 /* singleton - first object is "it" */
322 (void) PluginManager::instance();
324 ProcessThread::init ();
325 BufferManager::init (10); // XX should be num_processors_for_dsp + 1 for the GUI thread
327 PannerManager::instance().discover_panners();
329 // Initialize parameter metadata
330 EventTypeMap::instance().new_parameter(NullAutomation);
331 EventTypeMap::instance().new_parameter(GainAutomation);
332 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
333 EventTypeMap::instance().new_parameter(PanElevationAutomation);
334 EventTypeMap::instance().new_parameter(PanWidthAutomation);
335 EventTypeMap::instance().new_parameter(PluginAutomation);
336 EventTypeMap::instance().new_parameter(SoloAutomation);
337 EventTypeMap::instance().new_parameter(MuteAutomation);
338 EventTypeMap::instance().new_parameter(MidiCCAutomation);
339 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
340 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
341 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
342 EventTypeMap::instance().new_parameter(FadeInAutomation);
343 EventTypeMap::instance().new_parameter(FadeOutAutomation);
344 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
345 EventTypeMap::instance().new_parameter(MidiCCAutomation);
351 ARDOUR::init_post_engine ()
353 /* the MIDI Manager is needed by the ControlProtocolManager */
354 MIDI::Manager::create (AudioEngine::instance()->jack());
356 ControlProtocolManager::instance().discover_control_protocols ();
359 if ((node = Config->control_protocol_state()) != 0) {
360 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
365 ARDOUR::PluginManager::instance().refresh ();
373 delete &ControlProtocolManager::instance();
374 #ifdef WINDOWS_VST_SUPPORT
381 EnumWriter::destroy ();
386 ARDOUR::find_bindings_files (map<string,string>& files)
388 vector<sys::path> found;
389 SearchPath spath = ardour_config_search_path();
391 if (getenv ("ARDOUR_SAE")) {
392 Glib::PatternSpec pattern("*SAE-*.bindings");
393 find_matching_files_in_search_path (spath, pattern, found);
395 Glib::PatternSpec pattern("*.bindings");
396 find_matching_files_in_search_path (spath, pattern, found);
403 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
405 pair<string,string> namepath;
406 namepath.second = path.to_string();
407 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
408 files.insert (namepath);
413 ARDOUR::no_auto_connect()
415 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
422 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
423 // valgrind doesn't understand this assembler stuff
424 // September 10th, 2007
428 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
433 /* XXX use real code to determine if the processor supports
434 DenormalsAreZero and FlushToZero
437 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
441 MXCSR = _mm_getcsr();
443 #ifdef DEBUG_DENORMAL_EXCEPTION
444 /* This will raise a FP exception if a denormal is detected */
445 MXCSR &= ~_MM_MASK_DENORM;
448 switch (Config->get_denormal_model()) {
450 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
454 if (fpu.has_flush_to_zero()) {
455 MXCSR |= _MM_FLUSH_ZERO_ON;
460 MXCSR &= ~_MM_FLUSH_ZERO_ON;
461 if (fpu.has_denormals_are_zero()) {
467 if (fpu.has_flush_to_zero()) {
468 if (fpu.has_denormals_are_zero()) {
469 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
471 MXCSR |= _MM_FLUSH_ZERO_ON;
483 ARDOUR::translation_kill_path ()
485 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
489 ARDOUR::translations_are_disabled ()
491 /* if file does not exist, we don't translate (bundled ardour only) */
492 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;