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
385 ARDOUR::find_bindings_files (map<string,string>& files)
387 vector<sys::path> found;
388 SearchPath spath = ardour_config_search_path();
390 if (getenv ("ARDOUR_SAE")) {
391 Glib::PatternSpec pattern("*SAE-*.bindings");
392 find_matching_files_in_search_path (spath, pattern, found);
394 Glib::PatternSpec pattern("*.bindings");
395 find_matching_files_in_search_path (spath, pattern, found);
402 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
404 pair<string,string> namepath;
405 namepath.second = path.to_string();
406 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
407 files.insert (namepath);
412 ARDOUR::no_auto_connect()
414 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
421 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
422 // valgrind doesn't understand this assembler stuff
423 // September 10th, 2007
427 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
432 /* XXX use real code to determine if the processor supports
433 DenormalsAreZero and FlushToZero
436 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
440 MXCSR = _mm_getcsr();
442 #ifdef DEBUG_DENORMAL_EXCEPTION
443 /* This will raise a FP exception if a denormal is detected */
444 MXCSR &= ~_MM_MASK_DENORM;
447 switch (Config->get_denormal_model()) {
449 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
453 if (fpu.has_flush_to_zero()) {
454 MXCSR |= _MM_FLUSH_ZERO_ON;
459 MXCSR &= ~_MM_FLUSH_ZERO_ON;
460 if (fpu.has_denormals_are_zero()) {
466 if (fpu.has_flush_to_zero()) {
467 if (fpu.has_denormals_are_zero()) {
468 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
470 MXCSR |= _MM_FLUSH_ZERO_ON;
482 ARDOUR::translation_kill_path ()
484 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
488 ARDOUR::translations_are_disabled ()
490 /* if file does not exist, we don't translate (bundled ardour only) */
491 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;