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;
134 PBD::Signal2<void,std::string,std::string> ARDOUR::CopyConfigurationFiles;
137 extern void setup_enum_writer ();
140 /* this is useful for quite a few things that want to check
141 if any bounds-related property has changed
143 PBD::PropertyChange ARDOUR::bounds_change;
146 setup_hardware_optimization (bool try_optimization)
148 bool generic_mix_functions = true;
150 if (try_optimization) {
154 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
158 info << "Using SSE optimized routines" << endmsg;
161 compute_peak = x86_sse_compute_peak;
162 find_peaks = x86_sse_find_peaks;
163 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
164 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
165 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
167 generic_mix_functions = false;
171 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
172 SInt32 sysVersion = 0;
174 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
177 if (sysVersion >= 0x00001040) { // Tiger at least
178 compute_peak = veclib_compute_peak;
179 find_peaks = veclib_find_peaks;
180 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
181 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
182 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
184 generic_mix_functions = false;
186 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
190 /* consider FPU denormal handling to be "h/w optimization" */
195 if (generic_mix_functions) {
197 compute_peak = default_compute_peak;
198 find_peaks = default_find_peaks;
199 apply_gain_to_buffer = default_apply_gain_to_buffer;
200 mix_buffers_with_gain = default_mix_buffers_with_gain;
201 mix_buffers_no_gain = default_mix_buffers_no_gain;
203 info << "No H/W specific optimizations in use" << endmsg;
206 AudioGrapher::Routines::override_compute_peak (compute_peak);
207 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
211 lotsa_files_please ()
213 #ifndef PLATFORM_WINDOWS
216 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
219 /* See the COMPATIBILITY note on the Apple setrlimit() man page */
220 rl.rlim_cur = min ((rlim_t) OPEN_MAX, rl.rlim_max);
222 rl.rlim_cur = rl.rlim_max;
225 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
226 if (rl.rlim_cur == RLIM_INFINITY) {
227 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
229 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
232 if (rl.rlim_cur != RLIM_INFINITY) {
233 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
237 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
243 maybe_copy_old_configuration_files ()
245 int version = atoi (X_(PROGRAM_VERSION));
251 string old_config_dir = user_config_directory (version-1);
252 string current_config_dir = user_config_directory ();
254 if (Glib::file_test (old_config_dir, Glib::FILE_TEST_IS_DIR)) {
255 CopyConfigurationFiles (old_config_dir, current_config_dir); /* EMIT SIGNAL */
260 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
262 if (libardour_initialized) {
266 if (!PBD::init()) return false;
269 (void) bindtextdomain(PACKAGE, localedir);
270 (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
273 SessionEvent::init_event_pool ();
275 Operations::make_operations_quarks ();
276 SessionObject::make_property_quarks ();
277 Region::make_property_quarks ();
278 MidiRegion::make_property_quarks ();
279 AudioRegion::make_property_quarks ();
280 RouteGroup::make_property_quarks ();
281 Playlist::make_property_quarks ();
282 AudioPlaylist::make_property_quarks ();
284 /* this is a useful ready to use PropertyChange that many
285 things need to check. This avoids having to compose
286 it every time we want to check for any of the relevant
290 bounds_change.add (ARDOUR::Properties::start);
291 bounds_change.add (ARDOUR::Properties::position);
292 bounds_change.add (ARDOUR::Properties::length);
294 /* provide a state version for the few cases that need it and are not
295 driven by reading state from disk (e.g. undo/redo)
298 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
300 ARDOUR::setup_enum_writer ();
302 // allow ardour the absolute maximum number of open files
303 lotsa_files_please ();
305 maybe_copy_old_configuration_files ();
310 Library = new AudioLibrary;
312 BootMessage (_("Loading configuration"));
314 Config = new RCConfiguration;
316 if (Config->load_state ()) {
320 Config->set_use_windows_vst (use_windows_vst);
322 Config->set_use_lxvst(true);
325 Profile = new RuntimeProfile;
328 #ifdef WINDOWS_VST_SUPPORT
329 if (Config->get_use_windows_vst() && fst_init (0)) {
335 if (Config->get_use_lxvst() && vstfx_init (0)) {
340 #ifdef AUDIOUNIT_SUPPORT
341 AUPluginInfo::load_cached_info ();
344 setup_hardware_optimization (try_optimization);
346 SourceFactory::init ();
349 /* singletons - first object is "it" */
350 (void) PluginManager::instance();
352 (void) URIMap::instance();
354 (void) EventTypeMap::instance();
356 ProcessThread::init ();
357 /* the + 4 is a bit of a handwave. i don't actually know
358 how many more per-thread buffer sets we need above
359 the h/w concurrency, but its definitely > 1 more.
361 BufferManager::init (hardware_concurrency() + 4);
363 PannerManager::instance().discover_panners();
365 ARDOUR::AudioEngine::create ();
367 libardour_initialized = true;
373 ARDOUR::init_post_engine ()
375 ControlProtocolManager::instance().discover_control_protocols ();
378 if ((node = Config->control_protocol_state()) != 0) {
379 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
384 ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
390 if (!libardour_initialized) {
394 ARDOUR::AudioEngine::destroy ();
400 delete &ControlProtocolManager::instance();
401 #ifdef WINDOWS_VST_SUPPORT
408 delete &PluginManager::instance();
416 ARDOUR::find_bindings_files (map<string,string>& files)
418 vector<std::string> found;
419 Searchpath spath = ardour_config_search_path();
421 if (getenv ("ARDOUR_SAE")) {
422 find_files_matching_pattern (found, spath, "*SAE-*.bindings");
424 find_files_matching_pattern (found, spath, "*.bindings");
431 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
432 std::string path(*x);
433 pair<string,string> namepath;
434 namepath.second = path;
435 namepath.first = PBD::basename_nosuffix (path);
436 files.insert (namepath);
441 ARDOUR::no_auto_connect()
443 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
450 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
451 // valgrind doesn't understand this assembler stuff
452 // September 10th, 2007
456 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
461 /* XXX use real code to determine if the processor supports
462 DenormalsAreZero and FlushToZero
465 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
469 MXCSR = _mm_getcsr();
471 #ifdef DEBUG_DENORMAL_EXCEPTION
472 /* This will raise a FP exception if a denormal is detected */
473 MXCSR &= ~_MM_MASK_DENORM;
476 switch (Config->get_denormal_model()) {
478 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
482 if (fpu.has_flush_to_zero()) {
483 MXCSR |= _MM_FLUSH_ZERO_ON;
488 MXCSR &= ~_MM_FLUSH_ZERO_ON;
489 if (fpu.has_denormals_are_zero()) {
495 if (fpu.has_flush_to_zero()) {
496 if (fpu.has_denormals_are_zero()) {
497 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
499 MXCSR |= _MM_FLUSH_ZERO_ON;
510 /* this can be changed to modify the translation behaviour for
511 cases where the user has never expressed a preference.
513 static const bool translate_by_default = true;
516 ARDOUR::translation_enable_path ()
518 return Glib::build_filename (user_config_directory(), ".translate");
522 ARDOUR::translations_are_enabled ()
524 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
527 return translate_by_default;
533 if (::read (fd, &c, 1) == 1 && c == '1') {
543 ARDOUR::set_translations_enabled (bool yn)
545 string i18n_enabler = ARDOUR::translation_enable_path();
546 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
560 (void) ::write (fd, &c, 1);
568 ARDOUR::get_available_sync_options ()
570 vector<SyncSource> ret;
572 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
573 if (backend && backend->name() == "JACK") {
574 ret.push_back (Engine);
578 ret.push_back (MIDIClock);
584 /** Return a monotonic value for the number of microseconds that have elapsed
585 * since an arbitrary zero origin.
589 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
591 #include <mach/mach_time.h>
592 #define CLOCK_REALTIME 0
593 #define CLOCK_MONOTONIC 0
595 clock_gettime (int /*clk_id*/, struct timespec *t)
597 static bool initialized = false;
598 static mach_timebase_info_data_t timebase;
600 mach_timebase_info(&timebase);
604 time = mach_absolute_time();
605 double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
606 double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
608 t->tv_nsec = nseconds;
614 ARDOUR::get_microseconds ()
616 #ifdef PLATFORM_WINDOWS
617 microseconds_t ret = 0;
618 LARGE_INTEGER freq, time;
620 if (QueryPerformanceFrequency(&freq))
621 if (QueryPerformanceCounter(&time))
622 ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
627 if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
631 return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
635 /** Return the number of bits per sample for a given sample format.
637 * This is closely related to sndfile_data_width() but does NOT
638 * return a "magic" value to differentiate between 32 bit integer
639 * and 32 bit floating point values.
643 ARDOUR::format_data_width (ARDOUR::SampleFormat format)
649 case ARDOUR::FormatInt16:
651 case ARDOUR::FormatInt24: