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/operations.h"
93 #include "ardour/panner_manager.h"
94 #include "ardour/plugin_manager.h"
95 #include "ardour/process_thread.h"
96 #include "ardour/profile.h"
97 #include "ardour/rc_configuration.h"
98 #include "ardour/region.h"
99 #include "ardour/route_group.h"
100 #include "ardour/runtime_functions.h"
101 #include "ardour/session_event.h"
102 #include "ardour/source_factory.h"
104 #include "audiographer/routines.h"
106 #if defined (__APPLE__)
107 #include <Carbon/Carbon.h> // For Gestalt
112 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
113 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
114 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
116 using namespace ARDOUR;
120 bool libardour_initialized = false;
122 compute_peak_t ARDOUR::compute_peak = 0;
123 find_peaks_t ARDOUR::find_peaks = 0;
124 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
125 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
126 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
128 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
129 PBD::Signal3<void,std::string,std::string,bool> ARDOUR::PluginScanMessage;
130 PBD::Signal1<void,int> ARDOUR::PluginScanTimeout;
131 PBD::Signal0<void> ARDOUR::GUIIdle;
134 extern void setup_enum_writer ();
137 /* this is useful for quite a few things that want to check
138 if any bounds-related property has changed
140 PBD::PropertyChange ARDOUR::bounds_change;
143 setup_hardware_optimization (bool try_optimization)
145 bool generic_mix_functions = true;
147 if (try_optimization) {
151 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
155 info << "Using SSE optimized routines" << endmsg;
158 compute_peak = x86_sse_compute_peak;
159 find_peaks = x86_sse_find_peaks;
160 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
161 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
162 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
164 generic_mix_functions = false;
168 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
169 SInt32 sysVersion = 0;
171 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
174 if (sysVersion >= 0x00001040) { // Tiger at least
175 compute_peak = veclib_compute_peak;
176 find_peaks = veclib_find_peaks;
177 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
178 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
179 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
181 generic_mix_functions = false;
183 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
187 /* consider FPU denormal handling to be "h/w optimization" */
192 if (generic_mix_functions) {
194 compute_peak = default_compute_peak;
195 find_peaks = default_find_peaks;
196 apply_gain_to_buffer = default_apply_gain_to_buffer;
197 mix_buffers_with_gain = default_mix_buffers_with_gain;
198 mix_buffers_no_gain = default_mix_buffers_no_gain;
200 info << "No H/W specific optimizations in use" << endmsg;
203 AudioGrapher::Routines::override_compute_peak (compute_peak);
204 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
208 lotsa_files_please ()
210 #ifndef PLATFORM_WINDOWS
213 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
215 rl.rlim_cur = rl.rlim_max;
217 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
218 if (rl.rlim_cur == RLIM_INFINITY) {
219 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
221 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
224 if (rl.rlim_cur != RLIM_INFINITY) {
225 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
229 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
235 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
237 if (libardour_initialized) {
241 if (!PBD::init()) return false;
244 (void) bindtextdomain(PACKAGE, localedir);
245 (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
248 SessionEvent::init_event_pool ();
250 Operations::make_operations_quarks ();
251 SessionObject::make_property_quarks ();
252 Region::make_property_quarks ();
253 MidiRegion::make_property_quarks ();
254 AudioRegion::make_property_quarks ();
255 RouteGroup::make_property_quarks ();
256 Playlist::make_property_quarks ();
257 AudioPlaylist::make_property_quarks ();
259 /* this is a useful ready to use PropertyChange that many
260 things need to check. This avoids having to compose
261 it every time we want to check for any of the relevant
265 bounds_change.add (ARDOUR::Properties::start);
266 bounds_change.add (ARDOUR::Properties::position);
267 bounds_change.add (ARDOUR::Properties::length);
269 /* provide a state version for the few cases that need it and are not
270 driven by reading state from disk (e.g. undo/redo)
273 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
275 ARDOUR::setup_enum_writer ();
277 // allow ardour the absolute maximum number of open files
278 lotsa_files_please ();
283 Library = new AudioLibrary;
285 BootMessage (_("Loading configuration"));
287 Config = new RCConfiguration;
289 if (Config->load_state ()) {
293 Config->set_use_windows_vst (use_windows_vst);
295 Config->set_use_lxvst(true);
298 Profile = new RuntimeProfile;
301 #ifdef WINDOWS_VST_SUPPORT
302 if (Config->get_use_windows_vst() && fst_init (0)) {
308 if (Config->get_use_lxvst() && vstfx_init (0)) {
313 #ifdef AUDIOUNIT_SUPPORT
314 AUPluginInfo::load_cached_info ();
317 setup_hardware_optimization (try_optimization);
319 SourceFactory::init ();
322 /* singleton - first object is "it" */
323 (void) PluginManager::instance();
325 ProcessThread::init ();
326 /* the + 4 is a bit of a handwave. i don't actually know
327 how many more per-thread buffer sets we need above
328 the h/w concurrency, but its definitely > 1 more.
330 BufferManager::init (hardware_concurrency() + 4);
332 PannerManager::instance().discover_panners();
334 // Initialize parameter metadata
335 EventTypeMap::instance().new_parameter(NullAutomation);
336 EventTypeMap::instance().new_parameter(GainAutomation);
337 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
338 EventTypeMap::instance().new_parameter(PanElevationAutomation);
339 EventTypeMap::instance().new_parameter(PanWidthAutomation);
340 EventTypeMap::instance().new_parameter(PluginAutomation);
341 EventTypeMap::instance().new_parameter(SoloAutomation);
342 EventTypeMap::instance().new_parameter(MuteAutomation);
343 EventTypeMap::instance().new_parameter(MidiCCAutomation);
344 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
345 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
346 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
347 EventTypeMap::instance().new_parameter(FadeInAutomation);
348 EventTypeMap::instance().new_parameter(FadeOutAutomation);
349 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
350 EventTypeMap::instance().new_parameter(MidiCCAutomation);
352 ARDOUR::AudioEngine::create ();
354 libardour_initialized = true;
360 ARDOUR::init_post_engine ()
362 ControlProtocolManager::instance().discover_control_protocols ();
365 if ((node = Config->control_protocol_state()) != 0) {
366 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
371 ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
377 if (!libardour_initialized) {
381 ARDOUR::AudioEngine::destroy ();
387 delete &ControlProtocolManager::instance();
388 #ifdef WINDOWS_VST_SUPPORT
395 delete &PluginManager::instance();
403 ARDOUR::find_bindings_files (map<string,string>& files)
405 vector<std::string> found;
406 Searchpath spath = ardour_config_search_path();
408 if (getenv ("ARDOUR_SAE")) {
409 find_files_matching_pattern (found, spath, "*SAE-*.bindings");
411 find_files_matching_pattern (found, spath, "*.bindings");
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);