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"
27 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
30 #include <sys/types.h>
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
39 #ifdef WINDOWS_VST_SUPPORT
44 #include "ardour/linux_vst_support.h"
47 #ifdef AUDIOUNIT_SUPPORT
48 #include "ardour/audio_unit.h"
51 #if defined(__SSE__) || defined(USE_XMMINTRIN)
52 #include <xmmintrin.h>
56 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
59 #include <glibmm/fileutils.h>
60 #include <glibmm/miscutils.h>
67 #include "pbd/error.h"
70 #include "pbd/strsplit.h"
72 #include "pbd/file_utils.h"
73 #include "pbd/enumwriter.h"
74 #include "pbd/basename.h"
76 #include "midi++/port.h"
77 #include "midi++/manager.h"
78 #include "midi++/mmc.h"
80 #include "ardour/analyser.h"
81 #include "ardour/audio_library.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audioplaylist.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/buffer_manager.h"
86 #include "ardour/control_protocol_manager.h"
87 #include "ardour/filesystem_paths.h"
88 #include "ardour/midi_region.h"
89 #include "ardour/mix.h"
90 #include "ardour/panner_manager.h"
91 #include "ardour/plugin_manager.h"
92 #include "ardour/process_thread.h"
93 #include "ardour/profile.h"
94 #include "ardour/rc_configuration.h"
95 #include "ardour/region.h"
96 #include "ardour/route_group.h"
97 #include "ardour/runtime_functions.h"
98 #include "ardour/session_event.h"
99 #include "ardour/source_factory.h"
101 #include "audiographer/routines.h"
103 #if defined (__APPLE__)
104 #include <Carbon/Carbon.h> // For Gestalt
109 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
110 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
111 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
113 using namespace ARDOUR;
117 bool libardour_initialized = false;
119 compute_peak_t ARDOUR::compute_peak = 0;
120 find_peaks_t ARDOUR::find_peaks = 0;
121 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
122 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
123 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
125 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
126 PBD::Signal0<void> ARDOUR::GUIIdle;
129 extern void setup_enum_writer ();
132 /* this is useful for quite a few things that want to check
133 if any bounds-related property has changed
135 PBD::PropertyChange ARDOUR::bounds_change;
138 setup_hardware_optimization (bool try_optimization)
140 bool generic_mix_functions = true;
142 if (try_optimization) {
146 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
150 info << "Using SSE optimized routines" << endmsg;
153 compute_peak = x86_sse_compute_peak;
154 find_peaks = x86_sse_find_peaks;
155 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
156 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
157 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
159 generic_mix_functions = false;
163 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
164 SInt32 sysVersion = 0;
166 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
169 if (sysVersion >= 0x00001040) { // Tiger at least
170 compute_peak = veclib_compute_peak;
171 find_peaks = veclib_find_peaks;
172 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
173 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
174 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
176 generic_mix_functions = false;
178 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
182 /* consider FPU denormal handling to be "h/w optimization" */
187 if (generic_mix_functions) {
189 compute_peak = default_compute_peak;
190 find_peaks = default_find_peaks;
191 apply_gain_to_buffer = default_apply_gain_to_buffer;
192 mix_buffers_with_gain = default_mix_buffers_with_gain;
193 mix_buffers_no_gain = default_mix_buffers_no_gain;
195 info << "No H/W specific optimizations in use" << endmsg;
198 AudioGrapher::Routines::override_compute_peak (compute_peak);
199 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
203 lotsa_files_please ()
205 #ifndef PLATFORM_WINDOWS
208 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
210 rl.rlim_cur = rl.rlim_max;
212 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
213 if (rl.rlim_cur == RLIM_INFINITY) {
214 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
216 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
219 if (rl.rlim_cur != RLIM_INFINITY) {
220 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
224 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
230 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
232 if (libardour_initialized) {
236 if (!PBD::init()) return false;
239 (void) bindtextdomain(PACKAGE, localedir);
242 SessionEvent::init_event_pool ();
244 SessionObject::make_property_quarks ();
245 Region::make_property_quarks ();
246 MidiRegion::make_property_quarks ();
247 AudioRegion::make_property_quarks ();
248 RouteGroup::make_property_quarks ();
249 Playlist::make_property_quarks ();
250 AudioPlaylist::make_property_quarks ();
252 /* this is a useful ready to use PropertyChange that many
253 things need to check. This avoids having to compose
254 it every time we want to check for any of the relevant
258 bounds_change.add (ARDOUR::Properties::start);
259 bounds_change.add (ARDOUR::Properties::position);
260 bounds_change.add (ARDOUR::Properties::length);
262 /* provide a state version for the few cases that need it and are not
263 driven by reading state from disk (e.g. undo/redo)
266 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
268 ARDOUR::setup_enum_writer ();
270 // allow ardour the absolute maximum number of open files
271 lotsa_files_please ();
276 Library = new AudioLibrary;
278 BootMessage (_("Loading configuration"));
280 Config = new RCConfiguration;
282 if (Config->load_state ()) {
286 Config->set_use_windows_vst (use_windows_vst);
288 Config->set_use_lxvst(true);
291 Profile = new RuntimeProfile;
294 #ifdef WINDOWS_VST_SUPPORT
295 if (Config->get_use_windows_vst() && fst_init (0)) {
301 if (Config->get_use_lxvst() && vstfx_init (0)) {
306 #ifdef AUDIOUNIT_SUPPORT
307 AUPluginInfo::load_cached_info ();
310 setup_hardware_optimization (try_optimization);
312 SourceFactory::init ();
315 /* singleton - first object is "it" */
316 (void) PluginManager::instance();
318 ProcessThread::init ();
319 /* the + 4 is a bit of a handwave. i don't actually know
320 how many more per-thread buffer sets we need above
321 the h/w concurrency, but its definitely > 1 more.
323 BufferManager::init (hardware_concurrency() + 4);
325 PannerManager::instance().discover_panners();
327 // Initialize parameter metadata
328 EventTypeMap::instance().new_parameter(NullAutomation);
329 EventTypeMap::instance().new_parameter(GainAutomation);
330 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
331 EventTypeMap::instance().new_parameter(PanElevationAutomation);
332 EventTypeMap::instance().new_parameter(PanWidthAutomation);
333 EventTypeMap::instance().new_parameter(PluginAutomation);
334 EventTypeMap::instance().new_parameter(SoloAutomation);
335 EventTypeMap::instance().new_parameter(MuteAutomation);
336 EventTypeMap::instance().new_parameter(MidiCCAutomation);
337 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
338 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
339 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
340 EventTypeMap::instance().new_parameter(FadeInAutomation);
341 EventTypeMap::instance().new_parameter(FadeOutAutomation);
342 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
343 EventTypeMap::instance().new_parameter(MidiCCAutomation);
345 libardour_initialized = true;
351 ARDOUR::init_post_engine ()
353 /* the MIDI Manager is needed by the ControlProtocolManager */
354 MIDI::Manager::create (AudioEngine::instance()->jack());
356 ControlProtocolManager::instance().discover_control_protocols ();
359 if ((node = Config->control_protocol_state()) != 0) {
360 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
365 ARDOUR::PluginManager::instance().refresh ();
375 delete &ControlProtocolManager::instance();
376 #ifdef WINDOWS_VST_SUPPORT
388 ARDOUR::find_bindings_files (map<string,string>& files)
390 vector<std::string> found;
391 SearchPath spath = ardour_config_search_path();
393 if (getenv ("ARDOUR_SAE")) {
394 Glib::PatternSpec pattern("*SAE-*.bindings");
395 find_matching_files_in_search_path (spath, pattern, found);
397 Glib::PatternSpec pattern("*.bindings");
398 find_matching_files_in_search_path (spath, pattern, found);
405 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
406 std::string path(*x);
407 pair<string,string> namepath;
408 namepath.second = path;
409 namepath.first = PBD::basename_nosuffix (path);
410 files.insert (namepath);
415 ARDOUR::no_auto_connect()
417 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
424 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
425 // valgrind doesn't understand this assembler stuff
426 // September 10th, 2007
430 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
435 /* XXX use real code to determine if the processor supports
436 DenormalsAreZero and FlushToZero
439 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
443 MXCSR = _mm_getcsr();
445 #ifdef DEBUG_DENORMAL_EXCEPTION
446 /* This will raise a FP exception if a denormal is detected */
447 MXCSR &= ~_MM_MASK_DENORM;
450 switch (Config->get_denormal_model()) {
452 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
456 if (fpu.has_flush_to_zero()) {
457 MXCSR |= _MM_FLUSH_ZERO_ON;
462 MXCSR &= ~_MM_FLUSH_ZERO_ON;
463 if (fpu.has_denormals_are_zero()) {
469 if (fpu.has_flush_to_zero()) {
470 if (fpu.has_denormals_are_zero()) {
471 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
473 MXCSR |= _MM_FLUSH_ZERO_ON;
484 /* this can be changed to modify the translation behaviour for
485 cases where the user has never expressed a preference.
487 static const bool translate_by_default = true;
490 ARDOUR::translation_enable_path ()
492 return Glib::build_filename (user_config_directory(), ".translate");
496 ARDOUR::translations_are_enabled ()
498 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
501 return translate_by_default;
507 if (::read (fd, &c, 1) == 1 && c == '1') {
517 ARDOUR::set_translations_enabled (bool yn)
519 string i18n_enabler = ARDOUR::translation_enable_path();
520 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
542 ARDOUR::get_available_sync_options ()
544 vector<SyncSource> ret;
546 ret.push_back (JACK);
548 ret.push_back (MIDIClock);