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>
50 #include <glibmm/fileutils.h>
51 #include <glibmm/miscutils.h>
56 #include "pbd/error.h"
58 #include "pbd/strsplit.h"
60 #include "pbd/file_utils.h"
61 #include "pbd/enumwriter.h"
62 #include "pbd/basename.h"
64 #include "midi++/port.h"
65 #include "midi++/manager.h"
66 #include "midi++/mmc.h"
68 #include "ardour/analyser.h"
69 #include "ardour/audio_library.h"
70 #include "ardour/audioengine.h"
71 #include "ardour/audioplaylist.h"
72 #include "ardour/audioregion.h"
73 #include "ardour/buffer_manager.h"
74 #include "ardour/control_protocol_manager.h"
75 #include "ardour/filesystem_paths.h"
76 #include "ardour/midi_region.h"
77 #include "ardour/mix.h"
78 #include "ardour/panner_manager.h"
79 #include "ardour/plugin_manager.h"
80 #include "ardour/process_thread.h"
81 #include "ardour/profile.h"
82 #include "ardour/rc_configuration.h"
83 #include "ardour/region.h"
84 #include "ardour/route_group.h"
85 #include "ardour/runtime_functions.h"
86 #include "ardour/session_event.h"
87 #include "ardour/source_factory.h"
89 #include "audiographer/routines.h"
91 #if defined (__APPLE__)
92 #include <Carbon/Carbon.h> // For Gestalt
97 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
98 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
99 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
101 using namespace ARDOUR;
105 compute_peak_t ARDOUR::compute_peak = 0;
106 find_peaks_t ARDOUR::find_peaks = 0;
107 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
108 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
109 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
111 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
114 extern void setup_enum_writer ();
117 /* this is useful for quite a few things that want to check
118 if any bounds-related property has changed
120 PBD::PropertyChange ARDOUR::bounds_change;
123 setup_hardware_optimization (bool try_optimization)
125 bool generic_mix_functions = true;
127 if (try_optimization) {
131 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
135 info << "Using SSE optimized routines" << endmsg;
138 compute_peak = x86_sse_compute_peak;
139 find_peaks = x86_sse_find_peaks;
140 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
141 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
142 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
144 generic_mix_functions = false;
148 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
149 SInt32 sysVersion = 0;
151 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
154 if (sysVersion >= 0x00001040) { // Tiger at least
155 compute_peak = veclib_compute_peak;
156 find_peaks = veclib_find_peaks;
157 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
158 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
159 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
161 generic_mix_functions = false;
163 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
167 /* consider FPU denormal handling to be "h/w optimization" */
172 if (generic_mix_functions) {
174 compute_peak = default_compute_peak;
175 find_peaks = default_find_peaks;
176 apply_gain_to_buffer = default_apply_gain_to_buffer;
177 mix_buffers_with_gain = default_mix_buffers_with_gain;
178 mix_buffers_no_gain = default_mix_buffers_no_gain;
180 info << "No H/W specific optimizations in use" << endmsg;
183 AudioGrapher::Routines::override_compute_peak (compute_peak);
184 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
188 lotsa_files_please ()
192 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
194 rl.rlim_cur = rl.rlim_max;
196 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
197 if (rl.rlim_cur == RLIM_INFINITY) {
198 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
200 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
203 if (rl.rlim_cur == RLIM_INFINITY) {
204 info << _("Removed open file count limit. Excellent!") << endmsg;
206 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
210 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
215 ARDOUR::init (bool use_windows_vst, bool try_optimization)
217 if (!Glib::thread_supported()) {
221 // this really should be in PBD::init..if there was one
224 (void) bindtextdomain(PACKAGE, LOCALEDIR);
227 SessionEvent::init_event_pool ();
229 SessionObject::make_property_quarks ();
230 Region::make_property_quarks ();
231 MidiRegion::make_property_quarks ();
232 AudioRegion::make_property_quarks ();
233 RouteGroup::make_property_quarks ();
234 Playlist::make_property_quarks ();
235 AudioPlaylist::make_property_quarks ();
237 /* this is a useful ready to use PropertyChange that many
238 things need to check. This avoids having to compose
239 it every time we want to check for any of the relevant
243 bounds_change.add (ARDOUR::Properties::start);
244 bounds_change.add (ARDOUR::Properties::position);
245 bounds_change.add (ARDOUR::Properties::length);
247 /* provide a state version for the few cases that need it and are not
248 driven by reading state from disk (e.g. undo/redo)
251 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
253 ARDOUR::setup_enum_writer ();
255 // allow ardour the absolute maximum number of open files
256 lotsa_files_please ();
259 Library = new AudioLibrary;
261 BootMessage (_("Loading configuration"));
263 Config = new RCConfiguration;
265 if (Config->load_state ()) {
269 Config->set_use_windows_vst (use_windows_vst);
271 Config->set_use_lxvst(true);
274 Profile = new RuntimeProfile;
277 #ifdef WINDOWS_VST_SUPPORT
278 if (Config->get_use_windows_vst() && fst_init (0)) {
284 if (Config->get_use_lxvst() && vstfx_init (0)) {
289 #ifdef AUDIOUNIT_SUPPORT
290 AUPluginInfo::load_cached_info ();
293 setup_hardware_optimization (try_optimization);
295 SourceFactory::init ();
298 /* singleton - first object is "it" */
299 (void) PluginManager::instance();
301 ProcessThread::init ();
302 /* the + 4 is a bit of a handwave. i don't actually know
303 how many more per-thread buffer sets we need above
304 the h/w concurrency, but its definitely > 1 more.
306 BufferManager::init (hardware_concurrency() + 4);
308 PannerManager::instance().discover_panners();
310 // Initialize parameter metadata
311 EventTypeMap::instance().new_parameter(NullAutomation);
312 EventTypeMap::instance().new_parameter(GainAutomation);
313 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
314 EventTypeMap::instance().new_parameter(PanElevationAutomation);
315 EventTypeMap::instance().new_parameter(PanWidthAutomation);
316 EventTypeMap::instance().new_parameter(PluginAutomation);
317 EventTypeMap::instance().new_parameter(SoloAutomation);
318 EventTypeMap::instance().new_parameter(MuteAutomation);
319 EventTypeMap::instance().new_parameter(MidiCCAutomation);
320 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
321 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
322 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
323 EventTypeMap::instance().new_parameter(FadeInAutomation);
324 EventTypeMap::instance().new_parameter(FadeOutAutomation);
325 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
326 EventTypeMap::instance().new_parameter(MidiCCAutomation);
332 ARDOUR::init_post_engine ()
334 /* the MIDI Manager is needed by the ControlProtocolManager */
335 MIDI::Manager::create (AudioEngine::instance()->jack());
337 ControlProtocolManager::instance().discover_control_protocols ();
340 if ((node = Config->control_protocol_state()) != 0) {
341 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
346 ARDOUR::PluginManager::instance().refresh ();
354 delete &ControlProtocolManager::instance();
355 #ifdef WINDOWS_VST_SUPPORT
362 EnumWriter::destroy ();
367 ARDOUR::find_bindings_files (map<string,string>& files)
369 vector<std::string> found;
370 SearchPath spath = ardour_config_search_path();
372 if (getenv ("ARDOUR_SAE")) {
373 Glib::PatternSpec pattern("*SAE-*.bindings");
374 find_matching_files_in_search_path (spath, pattern, found);
376 Glib::PatternSpec pattern("*.bindings");
377 find_matching_files_in_search_path (spath, pattern, found);
384 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
385 std::string path(*x);
386 pair<string,string> namepath;
387 namepath.second = path;
388 namepath.first = PBD::basename_nosuffix (path);
389 files.insert (namepath);
394 ARDOUR::no_auto_connect()
396 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
403 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
404 // valgrind doesn't understand this assembler stuff
405 // September 10th, 2007
409 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
414 /* XXX use real code to determine if the processor supports
415 DenormalsAreZero and FlushToZero
418 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
422 MXCSR = _mm_getcsr();
424 #ifdef DEBUG_DENORMAL_EXCEPTION
425 /* This will raise a FP exception if a denormal is detected */
426 MXCSR &= ~_MM_MASK_DENORM;
429 switch (Config->get_denormal_model()) {
431 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
435 if (fpu.has_flush_to_zero()) {
436 MXCSR |= _MM_FLUSH_ZERO_ON;
441 MXCSR &= ~_MM_FLUSH_ZERO_ON;
442 if (fpu.has_denormals_are_zero()) {
448 if (fpu.has_flush_to_zero()) {
449 if (fpu.has_denormals_are_zero()) {
450 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
452 MXCSR |= _MM_FLUSH_ZERO_ON;
464 ARDOUR::translation_kill_path ()
466 return Glib::build_filename (user_config_directory(), ".love_is_the_language_of_audio");
470 ARDOUR::translations_are_disabled ()
472 /* if file does not exist, we don't translate (bundled ardour only) */
473 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;