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"
23 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
26 #include <sys/types.h>
28 #include <sys/resource.h>
34 #ifdef WINDOWS_VST_SUPPORT
39 #include "ardour/linux_vst_support.h"
42 #ifdef AUDIOUNIT_SUPPORT
43 #include "ardour/audio_unit.h"
47 #include <xmmintrin.h>
51 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
56 #include <glibmm/fileutils.h>
57 #include <glibmm/miscutils.h>
62 #include "pbd/error.h"
64 #include "pbd/strsplit.h"
66 #include "pbd/file_utils.h"
67 #include "pbd/enumwriter.h"
68 #include "pbd/basename.h"
70 #include "midi++/port.h"
71 #include "midi++/mmc.h"
73 #include "ardour/analyser.h"
74 #include "ardour/audio_library.h"
75 #include "ardour/audio_backend.h"
76 #include "ardour/audioengine.h"
77 #include "ardour/audioplaylist.h"
78 #include "ardour/audioregion.h"
79 #include "ardour/buffer_manager.h"
80 #include "ardour/control_protocol_manager.h"
81 #include "ardour/filesystem_paths.h"
82 #include "ardour/midi_region.h"
83 #include "ardour/midiport_manager.h"
84 #include "ardour/mix.h"
85 #include "ardour/panner_manager.h"
86 #include "ardour/plugin_manager.h"
87 #include "ardour/process_thread.h"
88 #include "ardour/profile.h"
89 #include "ardour/rc_configuration.h"
90 #include "ardour/region.h"
91 #include "ardour/route_group.h"
92 #include "ardour/runtime_functions.h"
93 #include "ardour/session_event.h"
94 #include "ardour/source_factory.h"
96 #include "audiographer/routines.h"
98 #if defined (__APPLE__)
99 #include <Carbon/Carbon.h> // For Gestalt
104 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
105 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
106 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
108 using namespace ARDOUR;
112 compute_peak_t ARDOUR::compute_peak = 0;
113 find_peaks_t ARDOUR::find_peaks = 0;
114 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
115 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
116 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
118 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
119 PBD::Signal0<void> ARDOUR::GUIIdle;
122 extern void setup_enum_writer ();
125 /* this is useful for quite a few things that want to check
126 if any bounds-related property has changed
128 PBD::PropertyChange ARDOUR::bounds_change;
131 setup_hardware_optimization (bool try_optimization)
133 bool generic_mix_functions = true;
135 if (try_optimization) {
139 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
143 info << "Using SSE optimized routines" << endmsg;
146 compute_peak = x86_sse_compute_peak;
147 find_peaks = x86_sse_find_peaks;
148 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
149 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
150 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
152 generic_mix_functions = false;
156 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
157 SInt32 sysVersion = 0;
159 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
162 if (sysVersion >= 0x00001040) { // Tiger at least
163 compute_peak = veclib_compute_peak;
164 find_peaks = veclib_find_peaks;
165 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
166 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
167 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
169 generic_mix_functions = false;
171 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
175 /* consider FPU denormal handling to be "h/w optimization" */
180 if (generic_mix_functions) {
182 compute_peak = default_compute_peak;
183 find_peaks = default_find_peaks;
184 apply_gain_to_buffer = default_apply_gain_to_buffer;
185 mix_buffers_with_gain = default_mix_buffers_with_gain;
186 mix_buffers_no_gain = default_mix_buffers_no_gain;
188 info << "No H/W specific optimizations in use" << endmsg;
191 AudioGrapher::Routines::override_compute_peak (compute_peak);
192 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
196 lotsa_files_please ()
200 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
202 rl.rlim_cur = rl.rlim_max;
204 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
205 if (rl.rlim_cur == RLIM_INFINITY) {
206 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
208 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
211 if (rl.rlim_cur != RLIM_INFINITY) {
212 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
216 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
221 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
223 if (!Glib::thread_supported()) {
227 // this really should be in PBD::init..if there was one
231 (void) bindtextdomain(PACKAGE, localedir);
235 SessionEvent::init_event_pool ();
237 SessionObject::make_property_quarks ();
238 Region::make_property_quarks ();
239 MidiRegion::make_property_quarks ();
240 AudioRegion::make_property_quarks ();
241 RouteGroup::make_property_quarks ();
242 Playlist::make_property_quarks ();
243 AudioPlaylist::make_property_quarks ();
245 /* this is a useful ready to use PropertyChange that many
246 things need to check. This avoids having to compose
247 it every time we want to check for any of the relevant
251 bounds_change.add (ARDOUR::Properties::start);
252 bounds_change.add (ARDOUR::Properties::position);
253 bounds_change.add (ARDOUR::Properties::length);
255 /* provide a state version for the few cases that need it and are not
256 driven by reading state from disk (e.g. undo/redo)
259 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
261 ARDOUR::setup_enum_writer ();
263 // allow ardour the absolute maximum number of open files
264 lotsa_files_please ();
267 Library = new AudioLibrary;
269 BootMessage (_("Loading configuration"));
271 Config = new RCConfiguration;
273 if (Config->load_state ()) {
277 Config->set_use_windows_vst (use_windows_vst);
279 Config->set_use_lxvst(true);
282 Profile = new RuntimeProfile;
285 #ifdef WINDOWS_VST_SUPPORT
286 if (Config->get_use_windows_vst() && fst_init (0)) {
292 if (Config->get_use_lxvst() && vstfx_init (0)) {
297 #ifdef AUDIOUNIT_SUPPORT
298 AUPluginInfo::load_cached_info ();
301 setup_hardware_optimization (try_optimization);
303 SourceFactory::init ();
306 /* singleton - first object is "it" */
307 (void) PluginManager::instance();
309 ProcessThread::init ();
310 /* the + 4 is a bit of a handwave. i don't actually know
311 how many more per-thread buffer sets we need above
312 the h/w concurrency, but its definitely > 1 more.
314 BufferManager::init (hardware_concurrency() + 4);
316 PannerManager::instance().discover_panners();
318 // Initialize parameter metadata
319 EventTypeMap::instance().new_parameter(NullAutomation);
320 EventTypeMap::instance().new_parameter(GainAutomation);
321 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
322 EventTypeMap::instance().new_parameter(PanElevationAutomation);
323 EventTypeMap::instance().new_parameter(PanWidthAutomation);
324 EventTypeMap::instance().new_parameter(PluginAutomation);
325 EventTypeMap::instance().new_parameter(SoloAutomation);
326 EventTypeMap::instance().new_parameter(MuteAutomation);
327 EventTypeMap::instance().new_parameter(MidiCCAutomation);
328 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
329 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
330 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
331 EventTypeMap::instance().new_parameter(FadeInAutomation);
332 EventTypeMap::instance().new_parameter(FadeOutAutomation);
333 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
334 EventTypeMap::instance().new_parameter(MidiCCAutomation);
336 ARDOUR::AudioEngine::create ();
342 ARDOUR::init_post_engine ()
344 ControlProtocolManager::instance().discover_control_protocols ();
347 if ((node = Config->control_protocol_state()) != 0) {
348 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
353 ARDOUR::PluginManager::instance().refresh ();
361 delete &ControlProtocolManager::instance();
362 #ifdef WINDOWS_VST_SUPPORT
369 EnumWriter::destroy ();
374 ARDOUR::find_bindings_files (map<string,string>& files)
376 vector<std::string> found;
377 SearchPath spath = ardour_config_search_path();
379 if (getenv ("ARDOUR_SAE")) {
380 Glib::PatternSpec pattern("*SAE-*.bindings");
381 find_matching_files_in_search_path (spath, pattern, found);
383 Glib::PatternSpec pattern("*.bindings");
384 find_matching_files_in_search_path (spath, pattern, found);
391 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
392 std::string path(*x);
393 pair<string,string> namepath;
394 namepath.second = path;
395 namepath.first = PBD::basename_nosuffix (path);
396 files.insert (namepath);
401 ARDOUR::no_auto_connect()
403 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
410 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
411 // valgrind doesn't understand this assembler stuff
412 // September 10th, 2007
416 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
421 /* XXX use real code to determine if the processor supports
422 DenormalsAreZero and FlushToZero
425 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
429 MXCSR = _mm_getcsr();
431 #ifdef DEBUG_DENORMAL_EXCEPTION
432 /* This will raise a FP exception if a denormal is detected */
433 MXCSR &= ~_MM_MASK_DENORM;
436 switch (Config->get_denormal_model()) {
438 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
442 if (fpu.has_flush_to_zero()) {
443 MXCSR |= _MM_FLUSH_ZERO_ON;
448 MXCSR &= ~_MM_FLUSH_ZERO_ON;
449 if (fpu.has_denormals_are_zero()) {
455 if (fpu.has_flush_to_zero()) {
456 if (fpu.has_denormals_are_zero()) {
457 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
459 MXCSR |= _MM_FLUSH_ZERO_ON;
470 /* this can be changed to modify the translation behaviour for
471 cases where the user has never expressed a preference.
473 static const bool translate_by_default = true;
476 ARDOUR::translation_enable_path ()
478 return Glib::build_filename (user_config_directory(), ".translate");
482 ARDOUR::translations_are_enabled ()
484 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
487 return translate_by_default;
493 if (::read (fd, &c, 1) == 1 && c == '1') {
503 ARDOUR::set_translations_enabled (bool yn)
505 string i18n_enabler = ARDOUR::translation_enable_path();
506 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
528 ARDOUR::get_available_sync_options ()
530 vector<SyncSource> ret;
532 ret.push_back (JACK);
534 ret.push_back (MIDIClock);
540 /** Return a monotonic value for the number of microseconds that have elapsed
541 * since an arbitrary zero origin.
545 ARDOUR::get_microseconds ()
548 if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
552 return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);