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>
40 #ifdef WINDOWS_VST_SUPPORT
45 #include "ardour/linux_vst_support.h"
48 #ifdef AUDIOUNIT_SUPPORT
49 #include "ardour/audio_unit.h"
52 #if defined(__SSE__) || defined(USE_XMMINTRIN)
53 #include <xmmintrin.h>
57 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
60 #include <glibmm/fileutils.h>
61 #include <glibmm/miscutils.h>
68 #include "pbd/error.h"
71 #include "pbd/strsplit.h"
73 #include "pbd/file_utils.h"
74 #include "pbd/enumwriter.h"
75 #include "pbd/basename.h"
77 #include "midi++/port.h"
78 #include "midi++/mmc.h"
80 #include "ardour/analyser.h"
81 #include "ardour/audio_library.h"
82 #include "ardour/audio_backend.h"
83 #include "ardour/audioengine.h"
84 #include "ardour/audioplaylist.h"
85 #include "ardour/audioregion.h"
86 #include "ardour/buffer_manager.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/filesystem_paths.h"
89 #include "ardour/midi_region.h"
90 #include "ardour/midiport_manager.h"
91 #include "ardour/mix.h"
92 #include "ardour/panner_manager.h"
93 #include "ardour/plugin_manager.h"
94 #include "ardour/process_thread.h"
95 #include "ardour/profile.h"
96 #include "ardour/rc_configuration.h"
97 #include "ardour/region.h"
98 #include "ardour/route_group.h"
99 #include "ardour/runtime_functions.h"
100 #include "ardour/session_event.h"
101 #include "ardour/source_factory.h"
103 #include "audiographer/routines.h"
105 #if defined (__APPLE__)
106 #include <Carbon/Carbon.h> // For Gestalt
111 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
112 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
113 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
115 using namespace ARDOUR;
119 bool libardour_initialized = false;
121 compute_peak_t ARDOUR::compute_peak = 0;
122 find_peaks_t ARDOUR::find_peaks = 0;
123 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
124 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
125 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
127 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
128 PBD::Signal3<void,std::string,std::string,bool> ARDOUR::PluginScanMessage;
129 PBD::Signal1<void,int> ARDOUR::PluginScanTimeout;
130 PBD::Signal0<void> ARDOUR::GUIIdle;
133 extern void setup_enum_writer ();
136 /* this is useful for quite a few things that want to check
137 if any bounds-related property has changed
139 PBD::PropertyChange ARDOUR::bounds_change;
142 setup_hardware_optimization (bool try_optimization)
144 bool generic_mix_functions = true;
146 if (try_optimization) {
150 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
154 info << "Using SSE optimized routines" << endmsg;
157 compute_peak = x86_sse_compute_peak;
158 find_peaks = x86_sse_find_peaks;
159 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
160 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
161 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
163 generic_mix_functions = false;
167 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
168 SInt32 sysVersion = 0;
170 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
173 if (sysVersion >= 0x00001040) { // Tiger at least
174 compute_peak = veclib_compute_peak;
175 find_peaks = veclib_find_peaks;
176 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
177 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
178 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
180 generic_mix_functions = false;
182 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
186 /* consider FPU denormal handling to be "h/w optimization" */
191 if (generic_mix_functions) {
193 compute_peak = default_compute_peak;
194 find_peaks = default_find_peaks;
195 apply_gain_to_buffer = default_apply_gain_to_buffer;
196 mix_buffers_with_gain = default_mix_buffers_with_gain;
197 mix_buffers_no_gain = default_mix_buffers_no_gain;
199 info << "No H/W specific optimizations in use" << endmsg;
202 AudioGrapher::Routines::override_compute_peak (compute_peak);
203 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
207 lotsa_files_please ()
209 #ifndef PLATFORM_WINDOWS
212 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
214 rl.rlim_cur = rl.rlim_max;
216 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
217 if (rl.rlim_cur == RLIM_INFINITY) {
218 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
220 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
223 if (rl.rlim_cur != RLIM_INFINITY) {
224 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
228 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
234 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
236 if (libardour_initialized) {
240 if (!PBD::init()) return false;
243 (void) bindtextdomain(PACKAGE, localedir);
244 (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
247 SessionEvent::init_event_pool ();
249 SessionObject::make_property_quarks ();
250 Region::make_property_quarks ();
251 MidiRegion::make_property_quarks ();
252 AudioRegion::make_property_quarks ();
253 RouteGroup::make_property_quarks ();
254 Playlist::make_property_quarks ();
255 AudioPlaylist::make_property_quarks ();
257 /* this is a useful ready to use PropertyChange that many
258 things need to check. This avoids having to compose
259 it every time we want to check for any of the relevant
263 bounds_change.add (ARDOUR::Properties::start);
264 bounds_change.add (ARDOUR::Properties::position);
265 bounds_change.add (ARDOUR::Properties::length);
267 /* provide a state version for the few cases that need it and are not
268 driven by reading state from disk (e.g. undo/redo)
271 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
273 ARDOUR::setup_enum_writer ();
275 // allow ardour the absolute maximum number of open files
276 lotsa_files_please ();
281 Library = new AudioLibrary;
283 BootMessage (_("Loading configuration"));
285 Config = new RCConfiguration;
287 if (Config->load_state ()) {
291 Config->set_use_windows_vst (use_windows_vst);
293 Config->set_use_lxvst(true);
296 Profile = new RuntimeProfile;
299 #ifdef WINDOWS_VST_SUPPORT
300 if (Config->get_use_windows_vst() && fst_init (0)) {
306 if (Config->get_use_lxvst() && vstfx_init (0)) {
311 #ifdef AUDIOUNIT_SUPPORT
312 AUPluginInfo::load_cached_info ();
315 setup_hardware_optimization (try_optimization);
317 SourceFactory::init ();
320 /* singleton - first object is "it" */
321 (void) PluginManager::instance();
323 ProcessThread::init ();
324 /* the + 4 is a bit of a handwave. i don't actually know
325 how many more per-thread buffer sets we need above
326 the h/w concurrency, but its definitely > 1 more.
328 BufferManager::init (hardware_concurrency() + 4);
330 PannerManager::instance().discover_panners();
332 // Initialize parameter metadata
333 EventTypeMap::instance().new_parameter(NullAutomation);
334 EventTypeMap::instance().new_parameter(GainAutomation);
335 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
336 EventTypeMap::instance().new_parameter(PanElevationAutomation);
337 EventTypeMap::instance().new_parameter(PanWidthAutomation);
338 EventTypeMap::instance().new_parameter(PluginAutomation);
339 EventTypeMap::instance().new_parameter(SoloAutomation);
340 EventTypeMap::instance().new_parameter(MuteAutomation);
341 EventTypeMap::instance().new_parameter(MidiCCAutomation);
342 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
343 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
344 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
345 EventTypeMap::instance().new_parameter(FadeInAutomation);
346 EventTypeMap::instance().new_parameter(FadeOutAutomation);
347 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
348 EventTypeMap::instance().new_parameter(MidiCCAutomation);
350 ARDOUR::AudioEngine::create ();
352 libardour_initialized = true;
358 ARDOUR::init_post_engine ()
360 ControlProtocolManager::instance().discover_control_protocols ();
363 if ((node = Config->control_protocol_state()) != 0) {
364 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
369 ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
375 if (!libardour_initialized) {
379 ARDOUR::AudioEngine::destroy ();
385 delete &ControlProtocolManager::instance();
386 #ifdef WINDOWS_VST_SUPPORT
393 delete &PluginManager::instance();
401 ARDOUR::find_bindings_files (map<string,string>& files)
403 vector<std::string> found;
404 Searchpath spath = ardour_config_search_path();
406 if (getenv ("ARDOUR_SAE")) {
407 Glib::PatternSpec pattern("*SAE-*.bindings");
408 find_matching_files_in_search_path (spath, pattern, found);
410 Glib::PatternSpec pattern("*.bindings");
411 find_matching_files_in_search_path (spath, pattern, found);
418 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
419 std::string path(*x);
420 pair<string,string> namepath;
421 namepath.second = path;
422 namepath.first = PBD::basename_nosuffix (path);
423 files.insert (namepath);
428 ARDOUR::no_auto_connect()
430 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
437 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
438 // valgrind doesn't understand this assembler stuff
439 // September 10th, 2007
443 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
448 /* XXX use real code to determine if the processor supports
449 DenormalsAreZero and FlushToZero
452 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
456 MXCSR = _mm_getcsr();
458 #ifdef DEBUG_DENORMAL_EXCEPTION
459 /* This will raise a FP exception if a denormal is detected */
460 MXCSR &= ~_MM_MASK_DENORM;
463 switch (Config->get_denormal_model()) {
465 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
469 if (fpu.has_flush_to_zero()) {
470 MXCSR |= _MM_FLUSH_ZERO_ON;
475 MXCSR &= ~_MM_FLUSH_ZERO_ON;
476 if (fpu.has_denormals_are_zero()) {
482 if (fpu.has_flush_to_zero()) {
483 if (fpu.has_denormals_are_zero()) {
484 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
486 MXCSR |= _MM_FLUSH_ZERO_ON;
497 /* this can be changed to modify the translation behaviour for
498 cases where the user has never expressed a preference.
500 static const bool translate_by_default = true;
503 ARDOUR::translation_enable_path ()
505 return Glib::build_filename (user_config_directory(), ".translate");
509 ARDOUR::translations_are_enabled ()
511 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
514 return translate_by_default;
520 if (::read (fd, &c, 1) == 1 && c == '1') {
530 ARDOUR::set_translations_enabled (bool yn)
532 string i18n_enabler = ARDOUR::translation_enable_path();
533 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
547 (void) ::write (fd, &c, 1);
555 ARDOUR::get_available_sync_options ()
557 vector<SyncSource> ret;
559 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
560 if (backend && backend->name() == "JACK") {
561 ret.push_back (Engine);
565 ret.push_back (MIDIClock);
571 /** Return a monotonic value for the number of microseconds that have elapsed
572 * since an arbitrary zero origin.
576 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
578 #include <mach/mach_time.h>
579 #define CLOCK_REALTIME 0
580 #define CLOCK_MONOTONIC 0
582 clock_gettime (int /*clk_id*/, struct timespec *t)
584 static bool initialized = false;
585 static mach_timebase_info_data_t timebase;
587 mach_timebase_info(&timebase);
591 time = mach_absolute_time();
592 double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
593 double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
595 t->tv_nsec = nseconds;
601 ARDOUR::get_microseconds ()
603 #ifdef PLATFORM_WINDOWS
604 microseconds_t ret = 0;
605 LARGE_INTEGER freq, time;
607 if (QueryPerformanceFrequency(&freq))
608 if (QueryPerformanceCounter(&time))
609 ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
614 if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
618 return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);