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>
49 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
54 #include <glibmm/fileutils.h>
55 #include <glibmm/miscutils.h>
60 #include "pbd/error.h"
62 #include "pbd/strsplit.h"
64 #include "pbd/file_utils.h"
65 #include "pbd/enumwriter.h"
66 #include "pbd/basename.h"
68 #include "midi++/port.h"
69 #include "midi++/manager.h"
70 #include "midi++/mmc.h"
72 #include "ardour/analyser.h"
73 #include "ardour/audio_library.h"
74 #include "ardour/audioengine.h"
75 #include "ardour/audioplaylist.h"
76 #include "ardour/audioregion.h"
77 #include "ardour/buffer_manager.h"
78 #include "ardour/control_protocol_manager.h"
79 #include "ardour/filesystem_paths.h"
80 #include "ardour/midi_region.h"
81 #include "ardour/mix.h"
82 #include "ardour/panner_manager.h"
83 #include "ardour/plugin_manager.h"
84 #include "ardour/process_thread.h"
85 #include "ardour/profile.h"
86 #include "ardour/rc_configuration.h"
87 #include "ardour/region.h"
88 #include "ardour/route_group.h"
89 #include "ardour/runtime_functions.h"
90 #include "ardour/session_event.h"
91 #include "ardour/source_factory.h"
93 #include "audiographer/routines.h"
95 #if defined (__APPLE__)
96 #include <Carbon/Carbon.h> // For Gestalt
101 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
102 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
103 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
105 using namespace ARDOUR;
109 compute_peak_t ARDOUR::compute_peak = 0;
110 find_peaks_t ARDOUR::find_peaks = 0;
111 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
112 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
113 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
115 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
118 extern void setup_enum_writer ();
121 /* this is useful for quite a few things that want to check
122 if any bounds-related property has changed
124 PBD::PropertyChange ARDOUR::bounds_change;
127 setup_hardware_optimization (bool try_optimization)
129 bool generic_mix_functions = true;
131 if (try_optimization) {
135 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
139 info << "Using SSE optimized routines" << endmsg;
142 compute_peak = x86_sse_compute_peak;
143 find_peaks = x86_sse_find_peaks;
144 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
145 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
146 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
148 generic_mix_functions = false;
152 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
153 SInt32 sysVersion = 0;
155 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
158 if (sysVersion >= 0x00001040) { // Tiger at least
159 compute_peak = veclib_compute_peak;
160 find_peaks = veclib_find_peaks;
161 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
162 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
163 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
165 generic_mix_functions = false;
167 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
171 /* consider FPU denormal handling to be "h/w optimization" */
176 if (generic_mix_functions) {
178 compute_peak = default_compute_peak;
179 find_peaks = default_find_peaks;
180 apply_gain_to_buffer = default_apply_gain_to_buffer;
181 mix_buffers_with_gain = default_mix_buffers_with_gain;
182 mix_buffers_no_gain = default_mix_buffers_no_gain;
184 info << "No H/W specific optimizations in use" << endmsg;
187 AudioGrapher::Routines::override_compute_peak (compute_peak);
188 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
192 lotsa_files_please ()
196 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
198 rl.rlim_cur = rl.rlim_max;
200 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
201 if (rl.rlim_cur == RLIM_INFINITY) {
202 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
204 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
207 if (rl.rlim_cur == RLIM_INFINITY) {
208 info << _("Removed open file count limit. Excellent!") << endmsg;
210 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
214 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
219 ARDOUR::init (bool use_windows_vst, bool try_optimization)
221 if (!Glib::thread_supported()) {
225 // this really should be in PBD::init..if there was one
228 (void) bindtextdomain(PACKAGE, LOCALEDIR);
231 SessionEvent::init_event_pool ();
233 SessionObject::make_property_quarks ();
234 Region::make_property_quarks ();
235 MidiRegion::make_property_quarks ();
236 AudioRegion::make_property_quarks ();
237 RouteGroup::make_property_quarks ();
238 Playlist::make_property_quarks ();
239 AudioPlaylist::make_property_quarks ();
241 /* this is a useful ready to use PropertyChange that many
242 things need to check. This avoids having to compose
243 it every time we want to check for any of the relevant
247 bounds_change.add (ARDOUR::Properties::start);
248 bounds_change.add (ARDOUR::Properties::position);
249 bounds_change.add (ARDOUR::Properties::length);
251 /* provide a state version for the few cases that need it and are not
252 driven by reading state from disk (e.g. undo/redo)
255 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
257 ARDOUR::setup_enum_writer ();
259 // allow ardour the absolute maximum number of open files
260 lotsa_files_please ();
263 Library = new AudioLibrary;
265 BootMessage (_("Loading configuration"));
267 Config = new RCConfiguration;
269 if (Config->load_state ()) {
273 Config->set_use_windows_vst (use_windows_vst);
275 Config->set_use_lxvst(true);
278 Profile = new RuntimeProfile;
281 #ifdef WINDOWS_VST_SUPPORT
282 if (Config->get_use_windows_vst() && fst_init (0)) {
288 if (Config->get_use_lxvst() && vstfx_init (0)) {
293 #ifdef AUDIOUNIT_SUPPORT
294 AUPluginInfo::load_cached_info ();
297 setup_hardware_optimization (try_optimization);
299 SourceFactory::init ();
302 /* singleton - first object is "it" */
303 (void) PluginManager::instance();
305 ProcessThread::init ();
306 /* the + 4 is a bit of a handwave. i don't actually know
307 how many more per-thread buffer sets we need above
308 the h/w concurrency, but its definitely > 1 more.
310 BufferManager::init (hardware_concurrency() + 4);
312 PannerManager::instance().discover_panners();
314 // Initialize parameter metadata
315 EventTypeMap::instance().new_parameter(NullAutomation);
316 EventTypeMap::instance().new_parameter(GainAutomation);
317 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
318 EventTypeMap::instance().new_parameter(PanElevationAutomation);
319 EventTypeMap::instance().new_parameter(PanWidthAutomation);
320 EventTypeMap::instance().new_parameter(PluginAutomation);
321 EventTypeMap::instance().new_parameter(SoloAutomation);
322 EventTypeMap::instance().new_parameter(MuteAutomation);
323 EventTypeMap::instance().new_parameter(MidiCCAutomation);
324 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
325 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
326 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
327 EventTypeMap::instance().new_parameter(FadeInAutomation);
328 EventTypeMap::instance().new_parameter(FadeOutAutomation);
329 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
330 EventTypeMap::instance().new_parameter(MidiCCAutomation);
336 ARDOUR::init_post_engine ()
338 /* the MIDI Manager is needed by the ControlProtocolManager */
339 MIDI::Manager::create (AudioEngine::instance()->jack());
341 ControlProtocolManager::instance().discover_control_protocols ();
344 if ((node = Config->control_protocol_state()) != 0) {
345 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
350 ARDOUR::PluginManager::instance().refresh ();
358 delete &ControlProtocolManager::instance();
359 #ifdef WINDOWS_VST_SUPPORT
366 EnumWriter::destroy ();
371 ARDOUR::find_bindings_files (map<string,string>& files)
373 vector<std::string> found;
374 SearchPath spath = ardour_config_search_path();
376 if (getenv ("ARDOUR_SAE")) {
377 Glib::PatternSpec pattern("*SAE-*.bindings");
378 find_matching_files_in_search_path (spath, pattern, found);
380 Glib::PatternSpec pattern("*.bindings");
381 find_matching_files_in_search_path (spath, pattern, found);
388 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
389 std::string path(*x);
390 pair<string,string> namepath;
391 namepath.second = path;
392 namepath.first = PBD::basename_nosuffix (path);
393 files.insert (namepath);
398 ARDOUR::no_auto_connect()
400 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
407 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
408 // valgrind doesn't understand this assembler stuff
409 // September 10th, 2007
413 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
418 /* XXX use real code to determine if the processor supports
419 DenormalsAreZero and FlushToZero
422 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
426 MXCSR = _mm_getcsr();
428 #ifdef DEBUG_DENORMAL_EXCEPTION
429 /* This will raise a FP exception if a denormal is detected */
430 MXCSR &= ~_MM_MASK_DENORM;
433 switch (Config->get_denormal_model()) {
435 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
439 if (fpu.has_flush_to_zero()) {
440 MXCSR |= _MM_FLUSH_ZERO_ON;
445 MXCSR &= ~_MM_FLUSH_ZERO_ON;
446 if (fpu.has_denormals_are_zero()) {
452 if (fpu.has_flush_to_zero()) {
453 if (fpu.has_denormals_are_zero()) {
454 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
456 MXCSR |= _MM_FLUSH_ZERO_ON;
468 ARDOUR::translation_kill_path ()
470 return Glib::build_filename (user_config_directory(), ".love_is_the_language_of_audio");
474 ARDOUR::translations_are_disabled ()
476 /* if file does not exist, we don't translate (bundled ardour only) */
477 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;