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 setup_hardware_optimization (bool try_optimization)
121 bool generic_mix_functions = true;
123 if (try_optimization) {
127 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
131 info << "Using SSE optimized routines" << endmsg;
134 compute_peak = x86_sse_compute_peak;
135 find_peaks = x86_sse_find_peaks;
136 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
137 // mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
138 mix_buffers_with_gain = default_mix_buffers_with_gain;
139 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
141 generic_mix_functions = false;
145 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
146 SInt32 sysVersion = 0;
148 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
151 if (sysVersion >= 0x00001040) { // Tiger at least
152 compute_peak = veclib_compute_peak;
153 find_peaks = veclib_find_peaks;
154 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
155 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
156 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
158 generic_mix_functions = false;
160 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
164 /* consider FPU denormal handling to be "h/w optimization" */
169 if (generic_mix_functions) {
171 compute_peak = default_compute_peak;
172 find_peaks = default_find_peaks;
173 apply_gain_to_buffer = default_apply_gain_to_buffer;
174 mix_buffers_with_gain = default_mix_buffers_with_gain;
175 mix_buffers_no_gain = default_mix_buffers_no_gain;
177 info << "No H/W specific optimizations in use" << endmsg;
180 AudioGrapher::Routines::override_compute_peak (compute_peak);
181 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
185 lotsa_files_please ()
189 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
191 rl.rlim_cur = rl.rlim_max;
193 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
194 if (rl.rlim_cur == RLIM_INFINITY) {
195 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
197 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
200 if (rl.rlim_cur == RLIM_INFINITY) {
201 info << _("Removed open file count limit. Excellent!") << endmsg;
203 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
207 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
212 ARDOUR::init (bool use_windows_vst, bool try_optimization)
214 if (!Glib::thread_supported()) {
218 (void) bindtextdomain(PACKAGE, LOCALEDIR);
221 SessionEvent::init_event_pool ();
223 SessionObject::make_property_quarks ();
224 Region::make_property_quarks ();
225 MidiRegion::make_property_quarks ();
226 AudioRegion::make_property_quarks ();
227 RouteGroup::make_property_quarks ();
228 Playlist::make_property_quarks ();
229 AudioPlaylist::make_property_quarks ();
231 /* this is a useful ready to use PropertyChange that many
232 things need to check. This avoids having to compose
233 it every time we want to check for any of the relevant
237 bounds_change.add (ARDOUR::Properties::start);
238 bounds_change.add (ARDOUR::Properties::position);
239 bounds_change.add (ARDOUR::Properties::length);
241 /* provide a state version for the few cases that need it and are not
242 driven by reading state from disk (e.g. undo/redo)
245 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
247 ARDOUR::setup_enum_writer ();
249 // allow ardour the absolute maximum number of open files
250 lotsa_files_please ();
253 Library = new AudioLibrary;
255 BootMessage (_("Loading configuration"));
257 Config = new RCConfiguration;
259 if (Config->load_state ()) {
263 Config->set_use_windows_vst (use_windows_vst);
265 Config->set_use_lxvst(true);
268 Profile = new RuntimeProfile;
271 #ifdef WINDOWS_VST_SUPPORT
272 if (Config->get_use_windows_vst() && fst_init (0)) {
278 if (Config->get_use_lxvst() && vstfx_init (0)) {
283 #ifdef AUDIOUNIT_SUPPORT
284 AUPluginInfo::load_cached_info ();
287 setup_hardware_optimization (try_optimization);
289 SourceFactory::init ();
292 /* singleton - first object is "it" */
293 (void) PluginManager::instance();
295 ProcessThread::init ();
296 BufferManager::init (10); // XX should be num_processors_for_dsp + 1 for the GUI thread
298 PannerManager::instance().discover_panners();
300 // Initialize parameter metadata
301 EventTypeMap::instance().new_parameter(NullAutomation);
302 EventTypeMap::instance().new_parameter(GainAutomation);
303 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
304 EventTypeMap::instance().new_parameter(PanElevationAutomation);
305 EventTypeMap::instance().new_parameter(PanWidthAutomation);
306 EventTypeMap::instance().new_parameter(PluginAutomation);
307 EventTypeMap::instance().new_parameter(SoloAutomation);
308 EventTypeMap::instance().new_parameter(MuteAutomation);
309 EventTypeMap::instance().new_parameter(MidiCCAutomation);
310 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
311 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
312 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
313 EventTypeMap::instance().new_parameter(FadeInAutomation);
314 EventTypeMap::instance().new_parameter(FadeOutAutomation);
315 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
316 EventTypeMap::instance().new_parameter(MidiCCAutomation);
322 ARDOUR::init_post_engine ()
324 /* the MIDI Manager is needed by the ControlProtocolManager */
325 MIDI::Manager::create (AudioEngine::instance()->jack());
327 ControlProtocolManager::instance().discover_control_protocols ();
330 if ((node = Config->control_protocol_state()) != 0) {
331 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
336 ARDOUR::PluginManager::instance().refresh ();
344 delete &ControlProtocolManager::instance();
345 #ifdef WINDOWS_VST_SUPPORT
352 EnumWriter::destroy ();
357 ARDOUR::find_bindings_files (map<string,string>& files)
359 vector<sys::path> found;
360 SearchPath spath = ardour_config_search_path();
362 if (getenv ("ARDOUR_SAE")) {
363 Glib::PatternSpec pattern("*SAE-*.bindings");
364 find_matching_files_in_search_path (spath, pattern, found);
366 Glib::PatternSpec pattern("*.bindings");
367 find_matching_files_in_search_path (spath, pattern, found);
374 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
376 pair<string,string> namepath;
377 namepath.second = path.to_string();
378 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
379 files.insert (namepath);
384 ARDOUR::no_auto_connect()
386 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
393 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
394 // valgrind doesn't understand this assembler stuff
395 // September 10th, 2007
399 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
404 /* XXX use real code to determine if the processor supports
405 DenormalsAreZero and FlushToZero
408 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
412 MXCSR = _mm_getcsr();
414 #ifdef DEBUG_DENORMAL_EXCEPTION
415 /* This will raise a FP exception if a denormal is detected */
416 MXCSR &= ~_MM_MASK_DENORM;
419 switch (Config->get_denormal_model()) {
421 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
425 if (fpu.has_flush_to_zero()) {
426 MXCSR |= _MM_FLUSH_ZERO_ON;
431 MXCSR &= ~_MM_FLUSH_ZERO_ON;
432 if (fpu.has_denormals_are_zero()) {
438 if (fpu.has_flush_to_zero()) {
439 if (fpu.has_denormals_are_zero()) {
440 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
442 MXCSR |= _MM_FLUSH_ZERO_ON;
454 ARDOUR::translation_kill_path ()
456 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
460 ARDOUR::translations_are_disabled ()
462 /* if file does not exist, we don't translate (bundled ardour only) */
463 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;