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) {
217 rl.rlim_cur = rl.rlim_max;
219 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
220 if (rl.rlim_cur == RLIM_INFINITY) {
222 /* For some reason, Apple doesn't do this the
223 * same way as Linux, and asking for
224 * RLIM_INFINITY even though that is
225 * rl.rlim_cur doesn't work.
227 * So try some actual large numbers in the hope
228 * that one of them will work.
232 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
234 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
236 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
237 error << _("Could not set system open files limit to a reasonable value. Be careful!") << endmsg;
241 info << string_compose ("Configured system open file limit to %1", rl.rlim_cur) << endmsg;
243 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
246 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
249 if (rl.rlim_cur != RLIM_INFINITY) {
250 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
254 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
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 ();
308 Library = new AudioLibrary;
310 BootMessage (_("Loading configuration"));
312 Config = new RCConfiguration;
314 if (Config->load_state ()) {
318 Config->set_use_windows_vst (use_windows_vst);
320 Config->set_use_lxvst(true);
323 Profile = new RuntimeProfile;
326 #ifdef WINDOWS_VST_SUPPORT
327 if (Config->get_use_windows_vst() && fst_init (0)) {
333 if (Config->get_use_lxvst() && vstfx_init (0)) {
338 #ifdef AUDIOUNIT_SUPPORT
339 AUPluginInfo::load_cached_info ();
342 setup_hardware_optimization (try_optimization);
344 SourceFactory::init ();
347 /* singletons - first object is "it" */
348 (void) PluginManager::instance();
349 (void) URIMap::instance();
350 (void) EventTypeMap::instance();
352 ProcessThread::init ();
353 /* the + 4 is a bit of a handwave. i don't actually know
354 how many more per-thread buffer sets we need above
355 the h/w concurrency, but its definitely > 1 more.
357 BufferManager::init (hardware_concurrency() + 4);
359 PannerManager::instance().discover_panners();
361 ARDOUR::AudioEngine::create ();
363 libardour_initialized = true;
369 ARDOUR::init_post_engine ()
371 ControlProtocolManager::instance().discover_control_protocols ();
374 if ((node = Config->control_protocol_state()) != 0) {
375 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
380 ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
386 if (!libardour_initialized) {
390 ARDOUR::AudioEngine::destroy ();
396 delete &ControlProtocolManager::instance();
397 #ifdef WINDOWS_VST_SUPPORT
404 delete &PluginManager::instance();
412 ARDOUR::find_bindings_files (map<string,string>& files)
414 vector<std::string> found;
415 Searchpath spath = ardour_config_search_path();
417 if (getenv ("ARDOUR_SAE")) {
418 find_files_matching_pattern (found, spath, "*SAE-*.bindings");
420 find_files_matching_pattern (found, spath, "*.bindings");
427 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
428 std::string path(*x);
429 pair<string,string> namepath;
430 namepath.second = path;
431 namepath.first = PBD::basename_nosuffix (path);
432 files.insert (namepath);
437 ARDOUR::no_auto_connect()
439 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
446 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
447 // valgrind doesn't understand this assembler stuff
448 // September 10th, 2007
452 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
457 /* XXX use real code to determine if the processor supports
458 DenormalsAreZero and FlushToZero
461 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
465 MXCSR = _mm_getcsr();
467 #ifdef DEBUG_DENORMAL_EXCEPTION
468 /* This will raise a FP exception if a denormal is detected */
469 MXCSR &= ~_MM_MASK_DENORM;
472 switch (Config->get_denormal_model()) {
474 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
478 if (fpu.has_flush_to_zero()) {
479 MXCSR |= _MM_FLUSH_ZERO_ON;
484 MXCSR &= ~_MM_FLUSH_ZERO_ON;
485 if (fpu.has_denormals_are_zero()) {
491 if (fpu.has_flush_to_zero()) {
492 if (fpu.has_denormals_are_zero()) {
493 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
495 MXCSR |= _MM_FLUSH_ZERO_ON;
506 /* this can be changed to modify the translation behaviour for
507 cases where the user has never expressed a preference.
509 static const bool translate_by_default = true;
512 ARDOUR::translation_enable_path ()
514 return Glib::build_filename (user_config_directory(), ".translate");
518 ARDOUR::translations_are_enabled ()
520 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
523 return translate_by_default;
529 if (::read (fd, &c, 1) == 1 && c == '1') {
539 ARDOUR::set_translations_enabled (bool yn)
541 string i18n_enabler = ARDOUR::translation_enable_path();
542 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
556 (void) ::write (fd, &c, 1);
564 ARDOUR::get_available_sync_options ()
566 vector<SyncSource> ret;
568 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
569 if (backend && backend->name() == "JACK") {
570 ret.push_back (Engine);
574 ret.push_back (MIDIClock);
580 /** Return a monotonic value for the number of microseconds that have elapsed
581 * since an arbitrary zero origin.
585 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
587 #include <mach/mach_time.h>
588 #define CLOCK_REALTIME 0
589 #define CLOCK_MONOTONIC 0
591 clock_gettime (int /*clk_id*/, struct timespec *t)
593 static bool initialized = false;
594 static mach_timebase_info_data_t timebase;
596 mach_timebase_info(&timebase);
600 time = mach_absolute_time();
601 double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
602 double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
604 t->tv_nsec = nseconds;
610 ARDOUR::get_microseconds ()
612 #ifdef PLATFORM_WINDOWS
613 microseconds_t ret = 0;
614 LARGE_INTEGER freq, time;
616 if (QueryPerformanceFrequency(&freq))
617 if (QueryPerformanceCounter(&time))
618 ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
623 if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
627 return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);