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"
59 #include "pbd/basename.h"
61 #include "midi++/port.h"
62 #include "midi++/manager.h"
63 #include "midi++/mmc.h"
65 #include "ardour/analyser.h"
66 #include "ardour/audio_library.h"
67 #include "ardour/audioengine.h"
68 #include "ardour/audioplaylist.h"
69 #include "ardour/audioregion.h"
70 #include "ardour/buffer_manager.h"
71 #include "ardour/control_protocol_manager.h"
72 #include "ardour/filesystem_paths.h"
73 #include "ardour/midi_region.h"
74 #include "ardour/mix.h"
75 #include "ardour/panner_manager.h"
76 #include "ardour/plugin_manager.h"
77 #include "ardour/process_thread.h"
78 #include "ardour/profile.h"
79 #include "ardour/rc_configuration.h"
80 #include "ardour/region.h"
81 #include "ardour/route_group.h"
82 #include "ardour/runtime_functions.h"
83 #include "ardour/session_event.h"
84 #include "ardour/source_factory.h"
86 #include "audiographer/routines.h"
88 #if defined (__APPLE__)
89 #include <Carbon/Carbon.h> // For Gestalt
94 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
95 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
96 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
98 using namespace ARDOUR;
102 compute_peak_t ARDOUR::compute_peak = 0;
103 find_peaks_t ARDOUR::find_peaks = 0;
104 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
105 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
106 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
108 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
111 extern void setup_enum_writer ();
114 /* this is useful for quite a few things that want to check
115 if any bounds-related property has changed
117 PBD::PropertyChange ARDOUR::bounds_change;
120 setup_hardware_optimization (bool try_optimization)
122 bool generic_mix_functions = true;
124 if (try_optimization) {
128 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
132 info << "Using SSE optimized routines" << endmsg;
135 compute_peak = x86_sse_compute_peak;
136 find_peaks = x86_sse_find_peaks;
137 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
138 // mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
139 mix_buffers_with_gain = default_mix_buffers_with_gain;
140 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
142 generic_mix_functions = false;
146 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
147 SInt32 sysVersion = 0;
149 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
152 if (sysVersion >= 0x00001040) { // Tiger at least
153 compute_peak = veclib_compute_peak;
154 find_peaks = veclib_find_peaks;
155 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
156 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
157 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
159 generic_mix_functions = false;
161 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
165 /* consider FPU denormal handling to be "h/w optimization" */
170 if (generic_mix_functions) {
172 compute_peak = default_compute_peak;
173 find_peaks = default_find_peaks;
174 apply_gain_to_buffer = default_apply_gain_to_buffer;
175 mix_buffers_with_gain = default_mix_buffers_with_gain;
176 mix_buffers_no_gain = default_mix_buffers_no_gain;
178 info << "No H/W specific optimizations in use" << endmsg;
181 AudioGrapher::Routines::override_compute_peak (compute_peak);
182 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
186 lotsa_files_please ()
190 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
192 rl.rlim_cur = rl.rlim_max;
194 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
195 if (rl.rlim_cur == RLIM_INFINITY) {
196 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
198 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
201 if (rl.rlim_cur == RLIM_INFINITY) {
202 info << _("Removed open file count limit. Excellent!") << endmsg;
204 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
208 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
213 ARDOUR::init (bool use_windows_vst, bool try_optimization)
215 if (!Glib::thread_supported()) {
219 (void) bindtextdomain(PACKAGE, LOCALEDIR);
222 SessionEvent::init_event_pool ();
224 SessionObject::make_property_quarks ();
225 Region::make_property_quarks ();
226 MidiRegion::make_property_quarks ();
227 AudioRegion::make_property_quarks ();
228 RouteGroup::make_property_quarks ();
229 Playlist::make_property_quarks ();
230 AudioPlaylist::make_property_quarks ();
232 /* this is a useful ready to use PropertyChange that many
233 things need to check. This avoids having to compose
234 it every time we want to check for any of the relevant
238 bounds_change.add (ARDOUR::Properties::start);
239 bounds_change.add (ARDOUR::Properties::position);
240 bounds_change.add (ARDOUR::Properties::length);
242 /* provide a state version for the few cases that need it and are not
243 driven by reading state from disk (e.g. undo/redo)
246 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
248 ARDOUR::setup_enum_writer ();
250 // allow ardour the absolute maximum number of open files
251 lotsa_files_please ();
254 Library = new AudioLibrary;
256 BootMessage (_("Loading configuration"));
258 Config = new RCConfiguration;
260 if (Config->load_state ()) {
264 Config->set_use_windows_vst (use_windows_vst);
266 Config->set_use_lxvst(true);
269 Profile = new RuntimeProfile;
272 #ifdef WINDOWS_VST_SUPPORT
273 if (Config->get_use_windows_vst() && fst_init (0)) {
279 if (Config->get_use_lxvst() && vstfx_init (0)) {
284 #ifdef AUDIOUNIT_SUPPORT
285 AUPluginInfo::load_cached_info ();
288 setup_hardware_optimization (try_optimization);
290 SourceFactory::init ();
293 /* singleton - first object is "it" */
294 (void) PluginManager::instance();
296 ProcessThread::init ();
297 BufferManager::init (10); // XX should be num_processors_for_dsp + 1 for the GUI thread
299 PannerManager::instance().discover_panners();
301 // Initialize parameter metadata
302 EventTypeMap::instance().new_parameter(NullAutomation);
303 EventTypeMap::instance().new_parameter(GainAutomation);
304 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
305 EventTypeMap::instance().new_parameter(PanElevationAutomation);
306 EventTypeMap::instance().new_parameter(PanWidthAutomation);
307 EventTypeMap::instance().new_parameter(PluginAutomation);
308 EventTypeMap::instance().new_parameter(SoloAutomation);
309 EventTypeMap::instance().new_parameter(MuteAutomation);
310 EventTypeMap::instance().new_parameter(MidiCCAutomation);
311 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
312 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
313 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
314 EventTypeMap::instance().new_parameter(FadeInAutomation);
315 EventTypeMap::instance().new_parameter(FadeOutAutomation);
316 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
317 EventTypeMap::instance().new_parameter(MidiCCAutomation);
323 ARDOUR::init_post_engine ()
325 /* the MIDI Manager is needed by the ControlProtocolManager */
326 MIDI::Manager::create (AudioEngine::instance()->jack());
328 ControlProtocolManager::instance().discover_control_protocols ();
331 if ((node = Config->control_protocol_state()) != 0) {
332 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
337 ARDOUR::PluginManager::instance().refresh ();
345 delete &ControlProtocolManager::instance();
346 #ifdef WINDOWS_VST_SUPPORT
353 EnumWriter::destroy ();
358 ARDOUR::find_bindings_files (map<string,string>& files)
360 vector<std::string> found;
361 SearchPath spath = ardour_config_search_path();
363 if (getenv ("ARDOUR_SAE")) {
364 Glib::PatternSpec pattern("*SAE-*.bindings");
365 find_matching_files_in_search_path (spath, pattern, found);
367 Glib::PatternSpec pattern("*.bindings");
368 find_matching_files_in_search_path (spath, pattern, found);
375 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
376 std::string path(*x);
377 pair<string,string> namepath;
378 namepath.second = path;
379 namepath.first = PBD::basename_nosuffix (path);
380 files.insert (namepath);
385 ARDOUR::no_auto_connect()
387 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
394 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
395 // valgrind doesn't understand this assembler stuff
396 // September 10th, 2007
400 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
405 /* XXX use real code to determine if the processor supports
406 DenormalsAreZero and FlushToZero
409 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
413 MXCSR = _mm_getcsr();
415 #ifdef DEBUG_DENORMAL_EXCEPTION
416 /* This will raise a FP exception if a denormal is detected */
417 MXCSR &= ~_MM_MASK_DENORM;
420 switch (Config->get_denormal_model()) {
422 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
426 if (fpu.has_flush_to_zero()) {
427 MXCSR |= _MM_FLUSH_ZERO_ON;
432 MXCSR &= ~_MM_FLUSH_ZERO_ON;
433 if (fpu.has_denormals_are_zero()) {
439 if (fpu.has_flush_to_zero()) {
440 if (fpu.has_denormals_are_zero()) {
441 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
443 MXCSR |= _MM_FLUSH_ZERO_ON;
455 ARDOUR::translation_kill_path ()
457 return Glib::build_filename (user_config_directory(), ".love_is_the_language_of_audio");
461 ARDOUR::translations_are_disabled ()
463 /* if file does not exist, we don't translate (bundled ardour only) */
464 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;