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>
55 #include "pbd/error.h"
57 #include "pbd/strsplit.h"
59 #include "pbd/file_utils.h"
60 #include "pbd/enumwriter.h"
61 #include "pbd/basename.h"
63 #include "midi++/port.h"
64 #include "midi++/manager.h"
65 #include "midi++/mmc.h"
67 #include "ardour/analyser.h"
68 #include "ardour/audio_library.h"
69 #include "ardour/audioengine.h"
70 #include "ardour/audioplaylist.h"
71 #include "ardour/audioregion.h"
72 #include "ardour/buffer_manager.h"
73 #include "ardour/control_protocol_manager.h"
74 #include "ardour/filesystem_paths.h"
75 #include "ardour/midi_region.h"
76 #include "ardour/mix.h"
77 #include "ardour/panner_manager.h"
78 #include "ardour/plugin_manager.h"
79 #include "ardour/process_thread.h"
80 #include "ardour/profile.h"
81 #include "ardour/rc_configuration.h"
82 #include "ardour/region.h"
83 #include "ardour/route_group.h"
84 #include "ardour/runtime_functions.h"
85 #include "ardour/session_event.h"
86 #include "ardour/source_factory.h"
88 #include "audiographer/routines.h"
90 #if defined (__APPLE__)
91 #include <Carbon/Carbon.h> // For Gestalt
96 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
97 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
98 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
100 using namespace ARDOUR;
104 compute_peak_t ARDOUR::compute_peak = 0;
105 find_peaks_t ARDOUR::find_peaks = 0;
106 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
107 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
108 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
110 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
113 extern void setup_enum_writer ();
116 /* this is useful for quite a few things that want to check
117 if any bounds-related property has changed
119 PBD::PropertyChange ARDOUR::bounds_change;
122 setup_hardware_optimization (bool try_optimization)
124 bool generic_mix_functions = true;
126 if (try_optimization) {
130 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
134 info << "Using SSE optimized routines" << endmsg;
137 compute_peak = x86_sse_compute_peak;
138 find_peaks = x86_sse_find_peaks;
139 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
140 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
141 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
143 generic_mix_functions = false;
147 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
148 SInt32 sysVersion = 0;
150 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
153 if (sysVersion >= 0x00001040) { // Tiger at least
154 compute_peak = veclib_compute_peak;
155 find_peaks = veclib_find_peaks;
156 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
157 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
158 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
160 generic_mix_functions = false;
162 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
166 /* consider FPU denormal handling to be "h/w optimization" */
171 if (generic_mix_functions) {
173 compute_peak = default_compute_peak;
174 find_peaks = default_find_peaks;
175 apply_gain_to_buffer = default_apply_gain_to_buffer;
176 mix_buffers_with_gain = default_mix_buffers_with_gain;
177 mix_buffers_no_gain = default_mix_buffers_no_gain;
179 info << "No H/W specific optimizations in use" << endmsg;
182 AudioGrapher::Routines::override_compute_peak (compute_peak);
183 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
187 lotsa_files_please ()
191 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
193 rl.rlim_cur = rl.rlim_max;
195 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
196 if (rl.rlim_cur == RLIM_INFINITY) {
197 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
199 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
202 if (rl.rlim_cur == RLIM_INFINITY) {
203 info << _("Removed open file count limit. Excellent!") << endmsg;
205 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
209 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
214 ARDOUR::init (bool use_windows_vst, bool try_optimization)
216 if (!Glib::thread_supported()) {
220 // this really should be in PBD::init..if there was one
223 (void) bindtextdomain(PACKAGE, LOCALEDIR);
226 SessionEvent::init_event_pool ();
228 SessionObject::make_property_quarks ();
229 Region::make_property_quarks ();
230 MidiRegion::make_property_quarks ();
231 AudioRegion::make_property_quarks ();
232 RouteGroup::make_property_quarks ();
233 Playlist::make_property_quarks ();
234 AudioPlaylist::make_property_quarks ();
236 /* this is a useful ready to use PropertyChange that many
237 things need to check. This avoids having to compose
238 it every time we want to check for any of the relevant
242 bounds_change.add (ARDOUR::Properties::start);
243 bounds_change.add (ARDOUR::Properties::position);
244 bounds_change.add (ARDOUR::Properties::length);
246 /* provide a state version for the few cases that need it and are not
247 driven by reading state from disk (e.g. undo/redo)
250 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
252 ARDOUR::setup_enum_writer ();
254 // allow ardour the absolute maximum number of open files
255 lotsa_files_please ();
258 Library = new AudioLibrary;
260 BootMessage (_("Loading configuration"));
262 Config = new RCConfiguration;
264 if (Config->load_state ()) {
268 Config->set_use_windows_vst (use_windows_vst);
270 Config->set_use_lxvst(true);
273 Profile = new RuntimeProfile;
276 #ifdef WINDOWS_VST_SUPPORT
277 if (Config->get_use_windows_vst() && fst_init (0)) {
283 if (Config->get_use_lxvst() && vstfx_init (0)) {
288 #ifdef AUDIOUNIT_SUPPORT
289 AUPluginInfo::load_cached_info ();
292 setup_hardware_optimization (try_optimization);
294 SourceFactory::init ();
297 /* singleton - first object is "it" */
298 (void) PluginManager::instance();
300 ProcessThread::init ();
301 BufferManager::init (10); // XX should be num_processors_for_dsp + 1 for the GUI thread
303 PannerManager::instance().discover_panners();
305 // Initialize parameter metadata
306 EventTypeMap::instance().new_parameter(NullAutomation);
307 EventTypeMap::instance().new_parameter(GainAutomation);
308 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
309 EventTypeMap::instance().new_parameter(PanElevationAutomation);
310 EventTypeMap::instance().new_parameter(PanWidthAutomation);
311 EventTypeMap::instance().new_parameter(PluginAutomation);
312 EventTypeMap::instance().new_parameter(SoloAutomation);
313 EventTypeMap::instance().new_parameter(MuteAutomation);
314 EventTypeMap::instance().new_parameter(MidiCCAutomation);
315 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
316 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
317 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
318 EventTypeMap::instance().new_parameter(FadeInAutomation);
319 EventTypeMap::instance().new_parameter(FadeOutAutomation);
320 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
321 EventTypeMap::instance().new_parameter(MidiCCAutomation);
327 ARDOUR::init_post_engine ()
329 /* the MIDI Manager is needed by the ControlProtocolManager */
330 MIDI::Manager::create (AudioEngine::instance()->jack());
332 ControlProtocolManager::instance().discover_control_protocols ();
335 if ((node = Config->control_protocol_state()) != 0) {
336 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
341 ARDOUR::PluginManager::instance().refresh ();
349 delete &ControlProtocolManager::instance();
350 #ifdef WINDOWS_VST_SUPPORT
357 EnumWriter::destroy ();
362 ARDOUR::find_bindings_files (map<string,string>& files)
364 vector<std::string> found;
365 SearchPath spath = ardour_config_search_path();
367 if (getenv ("ARDOUR_SAE")) {
368 Glib::PatternSpec pattern("*SAE-*.bindings");
369 find_matching_files_in_search_path (spath, pattern, found);
371 Glib::PatternSpec pattern("*.bindings");
372 find_matching_files_in_search_path (spath, pattern, found);
379 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
380 std::string path(*x);
381 pair<string,string> namepath;
382 namepath.second = path;
383 namepath.first = PBD::basename_nosuffix (path);
384 files.insert (namepath);
389 ARDOUR::no_auto_connect()
391 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
398 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
399 // valgrind doesn't understand this assembler stuff
400 // September 10th, 2007
404 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
409 /* XXX use real code to determine if the processor supports
410 DenormalsAreZero and FlushToZero
413 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
417 MXCSR = _mm_getcsr();
419 #ifdef DEBUG_DENORMAL_EXCEPTION
420 /* This will raise a FP exception if a denormal is detected */
421 MXCSR &= ~_MM_MASK_DENORM;
424 switch (Config->get_denormal_model()) {
426 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
430 if (fpu.has_flush_to_zero()) {
431 MXCSR |= _MM_FLUSH_ZERO_ON;
436 MXCSR &= ~_MM_FLUSH_ZERO_ON;
437 if (fpu.has_denormals_are_zero()) {
443 if (fpu.has_flush_to_zero()) {
444 if (fpu.has_denormals_are_zero()) {
445 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
447 MXCSR |= _MM_FLUSH_ZERO_ON;
459 ARDOUR::translation_kill_path ()
461 return Glib::build_filename (user_config_directory(), ".love_is_the_language_of_audio");
465 ARDOUR::translations_are_disabled ()
467 /* if file does not exist, we don't translate (bundled ardour only) */
468 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;