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/event_type_map.h"
89 #include "ardour/filesystem_paths.h"
90 #include "ardour/midi_region.h"
91 #include "ardour/midiport_manager.h"
92 #include "ardour/mix.h"
93 #include "ardour/operations.h"
94 #include "ardour/panner_manager.h"
95 #include "ardour/plugin_manager.h"
96 #include "ardour/process_thread.h"
97 #include "ardour/profile.h"
98 #include "ardour/rc_configuration.h"
99 #include "ardour/region.h"
100 #include "ardour/route_group.h"
101 #include "ardour/runtime_functions.h"
102 #include "ardour/session_event.h"
103 #include "ardour/source_factory.h"
104 #include "ardour/uri_map.h"
106 #include "audiographer/routines.h"
108 #if defined (__APPLE__)
109 #include <Carbon/Carbon.h> // For Gestalt
114 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
115 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
116 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
118 using namespace ARDOUR;
122 bool libardour_initialized = false;
124 compute_peak_t ARDOUR::compute_peak = 0;
125 find_peaks_t ARDOUR::find_peaks = 0;
126 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
127 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
128 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
130 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
131 PBD::Signal3<void,std::string,std::string,bool> ARDOUR::PluginScanMessage;
132 PBD::Signal1<void,int> ARDOUR::PluginScanTimeout;
133 PBD::Signal0<void> ARDOUR::GUIIdle;
136 extern void setup_enum_writer ();
139 /* this is useful for quite a few things that want to check
140 if any bounds-related property has changed
142 PBD::PropertyChange ARDOUR::bounds_change;
145 setup_hardware_optimization (bool try_optimization)
147 bool generic_mix_functions = true;
149 if (try_optimization) {
153 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
157 info << "Using SSE optimized routines" << endmsg;
160 compute_peak = x86_sse_compute_peak;
161 find_peaks = x86_sse_find_peaks;
162 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
163 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
164 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
166 generic_mix_functions = false;
170 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
171 SInt32 sysVersion = 0;
173 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
176 if (sysVersion >= 0x00001040) { // Tiger at least
177 compute_peak = veclib_compute_peak;
178 find_peaks = veclib_find_peaks;
179 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
180 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
181 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
183 generic_mix_functions = false;
185 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
189 /* consider FPU denormal handling to be "h/w optimization" */
194 if (generic_mix_functions) {
196 compute_peak = default_compute_peak;
197 find_peaks = default_find_peaks;
198 apply_gain_to_buffer = default_apply_gain_to_buffer;
199 mix_buffers_with_gain = default_mix_buffers_with_gain;
200 mix_buffers_no_gain = default_mix_buffers_no_gain;
202 info << "No H/W specific optimizations in use" << endmsg;
205 AudioGrapher::Routines::override_compute_peak (compute_peak);
206 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
210 lotsa_files_please ()
212 #ifndef PLATFORM_WINDOWS
215 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
218 /* See the COMPATIBILITY note on the Apple setrlimit() man page */
219 rl.rlim_cur = min ((rlim_t) OPEN_MAX, rl.rlim_max);
221 rl.rlim_cur = rl.rlim_max;
224 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
225 if (rl.rlim_cur == RLIM_INFINITY) {
226 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
228 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
231 if (rl.rlim_cur != RLIM_INFINITY) {
232 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
236 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
242 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
244 if (libardour_initialized) {
248 if (!PBD::init()) return false;
251 (void) bindtextdomain(PACKAGE, localedir);
252 (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
255 SessionEvent::init_event_pool ();
257 Operations::make_operations_quarks ();
258 SessionObject::make_property_quarks ();
259 Region::make_property_quarks ();
260 MidiRegion::make_property_quarks ();
261 AudioRegion::make_property_quarks ();
262 RouteGroup::make_property_quarks ();
263 Playlist::make_property_quarks ();
264 AudioPlaylist::make_property_quarks ();
266 /* this is a useful ready to use PropertyChange that many
267 things need to check. This avoids having to compose
268 it every time we want to check for any of the relevant
272 bounds_change.add (ARDOUR::Properties::start);
273 bounds_change.add (ARDOUR::Properties::position);
274 bounds_change.add (ARDOUR::Properties::length);
276 /* provide a state version for the few cases that need it and are not
277 driven by reading state from disk (e.g. undo/redo)
280 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
282 ARDOUR::setup_enum_writer ();
284 // allow ardour the absolute maximum number of open files
285 lotsa_files_please ();
290 Library = new AudioLibrary;
292 BootMessage (_("Loading configuration"));
294 Config = new RCConfiguration;
296 if (Config->load_state ()) {
300 Config->set_use_windows_vst (use_windows_vst);
302 Config->set_use_lxvst(true);
305 Profile = new RuntimeProfile;
308 #ifdef WINDOWS_VST_SUPPORT
309 if (Config->get_use_windows_vst() && fst_init (0)) {
315 if (Config->get_use_lxvst() && vstfx_init (0)) {
320 #ifdef AUDIOUNIT_SUPPORT
321 AUPluginInfo::load_cached_info ();
324 setup_hardware_optimization (try_optimization);
326 SourceFactory::init ();
329 /* singletons - first object is "it" */
330 (void) PluginManager::instance();
332 (void) URIMap::instance();
334 (void) EventTypeMap::instance();
336 ProcessThread::init ();
337 /* the + 4 is a bit of a handwave. i don't actually know
338 how many more per-thread buffer sets we need above
339 the h/w concurrency, but its definitely > 1 more.
341 BufferManager::init (hardware_concurrency() + 4);
343 PannerManager::instance().discover_panners();
345 ARDOUR::AudioEngine::create ();
347 libardour_initialized = true;
353 ARDOUR::init_post_engine ()
355 ControlProtocolManager::instance().discover_control_protocols ();
358 if ((node = Config->control_protocol_state()) != 0) {
359 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
364 ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
370 if (!libardour_initialized) {
374 ARDOUR::AudioEngine::destroy ();
380 delete &ControlProtocolManager::instance();
381 #ifdef WINDOWS_VST_SUPPORT
388 delete &PluginManager::instance();
396 ARDOUR::find_bindings_files (map<string,string>& files)
398 vector<std::string> found;
399 Searchpath spath = ardour_config_search_path();
401 if (getenv ("ARDOUR_SAE")) {
402 find_files_matching_pattern (found, spath, "*SAE-*.bindings");
404 find_files_matching_pattern (found, spath, "*.bindings");
411 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
412 std::string path(*x);
413 pair<string,string> namepath;
414 namepath.second = path;
415 namepath.first = PBD::basename_nosuffix (path);
416 files.insert (namepath);
421 ARDOUR::no_auto_connect()
423 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
430 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
431 // valgrind doesn't understand this assembler stuff
432 // September 10th, 2007
436 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
441 /* XXX use real code to determine if the processor supports
442 DenormalsAreZero and FlushToZero
445 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
449 MXCSR = _mm_getcsr();
451 #ifdef DEBUG_DENORMAL_EXCEPTION
452 /* This will raise a FP exception if a denormal is detected */
453 MXCSR &= ~_MM_MASK_DENORM;
456 switch (Config->get_denormal_model()) {
458 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
462 if (fpu.has_flush_to_zero()) {
463 MXCSR |= _MM_FLUSH_ZERO_ON;
468 MXCSR &= ~_MM_FLUSH_ZERO_ON;
469 if (fpu.has_denormals_are_zero()) {
475 if (fpu.has_flush_to_zero()) {
476 if (fpu.has_denormals_are_zero()) {
477 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
479 MXCSR |= _MM_FLUSH_ZERO_ON;
490 /* this can be changed to modify the translation behaviour for
491 cases where the user has never expressed a preference.
493 static const bool translate_by_default = true;
496 ARDOUR::translation_enable_path ()
498 return Glib::build_filename (user_config_directory(), ".translate");
502 ARDOUR::translations_are_enabled ()
504 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
507 return translate_by_default;
513 if (::read (fd, &c, 1) == 1 && c == '1') {
523 ARDOUR::set_translations_enabled (bool yn)
525 string i18n_enabler = ARDOUR::translation_enable_path();
526 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
540 (void) ::write (fd, &c, 1);
548 ARDOUR::get_available_sync_options ()
550 vector<SyncSource> ret;
552 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
553 if (backend && backend->name() == "JACK") {
554 ret.push_back (Engine);
558 ret.push_back (MIDIClock);
564 /** Return a monotonic value for the number of microseconds that have elapsed
565 * since an arbitrary zero origin.
569 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
571 #include <mach/mach_time.h>
572 #define CLOCK_REALTIME 0
573 #define CLOCK_MONOTONIC 0
575 clock_gettime (int /*clk_id*/, struct timespec *t)
577 static bool initialized = false;
578 static mach_timebase_info_data_t timebase;
580 mach_timebase_info(&timebase);
584 time = mach_absolute_time();
585 double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
586 double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
588 t->tv_nsec = nseconds;
594 ARDOUR::get_microseconds ()
596 #ifdef PLATFORM_WINDOWS
597 microseconds_t ret = 0;
598 LARGE_INTEGER freq, time;
600 if (QueryPerformanceFrequency(&freq))
601 if (QueryPerformanceCounter(&time))
602 ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
607 if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
611 return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
615 /** Return the number of bits per sample for a given sample format.
617 * This is closely related to sndfile_data_width() but does NOT
618 * return a "magic" value to differentiate between 32 bit integer
619 * and 32 bit floating point values.
623 ARDOUR::format_data_width (ARDOUR::SampleFormat format)
629 case ARDOUR::FormatInt16:
631 case ARDOUR::FormatInt24: