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>
33 #ifdef WINDOWS_VST_SUPPORT
38 #include "ardour/linux_vst_support.h"
41 #ifdef AUDIOUNIT_SUPPORT
42 #include "ardour/audio_unit.h"
46 #include <xmmintrin.h>
50 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
53 #include <glibmm/fileutils.h>
54 #include <glibmm/miscutils.h>
59 #include "pbd/error.h"
62 #include "pbd/strsplit.h"
64 #include "pbd/file_utils.h"
65 #include "pbd/enumwriter.h"
66 #include "pbd/basename.h"
68 #include "midi++/port.h"
69 #include "midi++/manager.h"
70 #include "midi++/mmc.h"
72 #include "ardour/analyser.h"
73 #include "ardour/audio_library.h"
74 #include "ardour/audioengine.h"
75 #include "ardour/audioplaylist.h"
76 #include "ardour/audioregion.h"
77 #include "ardour/buffer_manager.h"
78 #include "ardour/control_protocol_manager.h"
79 #include "ardour/filesystem_paths.h"
80 #include "ardour/midi_region.h"
81 #include "ardour/mix.h"
82 #include "ardour/panner_manager.h"
83 #include "ardour/plugin_manager.h"
84 #include "ardour/process_thread.h"
85 #include "ardour/profile.h"
86 #include "ardour/rc_configuration.h"
87 #include "ardour/region.h"
88 #include "ardour/route_group.h"
89 #include "ardour/runtime_functions.h"
90 #include "ardour/session_event.h"
91 #include "ardour/source_factory.h"
93 #include "audiographer/routines.h"
95 #if defined (__APPLE__)
96 #include <Carbon/Carbon.h> // For Gestalt
101 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
102 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
103 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
105 using namespace ARDOUR;
109 bool libardour_initialized = false;
111 compute_peak_t ARDOUR::compute_peak = 0;
112 find_peaks_t ARDOUR::find_peaks = 0;
113 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
114 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
115 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
117 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
118 PBD::Signal0<void> ARDOUR::GUIIdle;
121 extern void setup_enum_writer ();
124 /* this is useful for quite a few things that want to check
125 if any bounds-related property has changed
127 PBD::PropertyChange ARDOUR::bounds_change;
130 setup_hardware_optimization (bool try_optimization)
132 bool generic_mix_functions = true;
134 if (try_optimization) {
138 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
142 info << "Using SSE optimized routines" << endmsg;
145 compute_peak = x86_sse_compute_peak;
146 find_peaks = x86_sse_find_peaks;
147 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
148 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
149 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
151 generic_mix_functions = false;
155 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
156 SInt32 sysVersion = 0;
158 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
161 if (sysVersion >= 0x00001040) { // Tiger at least
162 compute_peak = veclib_compute_peak;
163 find_peaks = veclib_find_peaks;
164 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
165 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
166 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
168 generic_mix_functions = false;
170 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
174 /* consider FPU denormal handling to be "h/w optimization" */
179 if (generic_mix_functions) {
181 compute_peak = default_compute_peak;
182 find_peaks = default_find_peaks;
183 apply_gain_to_buffer = default_apply_gain_to_buffer;
184 mix_buffers_with_gain = default_mix_buffers_with_gain;
185 mix_buffers_no_gain = default_mix_buffers_no_gain;
187 info << "No H/W specific optimizations in use" << endmsg;
190 AudioGrapher::Routines::override_compute_peak (compute_peak);
191 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
195 lotsa_files_please ()
199 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
201 rl.rlim_cur = rl.rlim_max;
203 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
204 if (rl.rlim_cur == RLIM_INFINITY) {
205 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
207 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
210 if (rl.rlim_cur != RLIM_INFINITY) {
211 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
215 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
220 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
222 if (libardour_initialized) {
226 if (!PBD::init()) return false;
229 (void) bindtextdomain(PACKAGE, localedir);
232 SessionEvent::init_event_pool ();
234 SessionObject::make_property_quarks ();
235 Region::make_property_quarks ();
236 MidiRegion::make_property_quarks ();
237 AudioRegion::make_property_quarks ();
238 RouteGroup::make_property_quarks ();
239 Playlist::make_property_quarks ();
240 AudioPlaylist::make_property_quarks ();
242 /* this is a useful ready to use PropertyChange that many
243 things need to check. This avoids having to compose
244 it every time we want to check for any of the relevant
248 bounds_change.add (ARDOUR::Properties::start);
249 bounds_change.add (ARDOUR::Properties::position);
250 bounds_change.add (ARDOUR::Properties::length);
252 /* provide a state version for the few cases that need it and are not
253 driven by reading state from disk (e.g. undo/redo)
256 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
258 ARDOUR::setup_enum_writer ();
260 // allow ardour the absolute maximum number of open files
261 lotsa_files_please ();
264 Library = new AudioLibrary;
266 BootMessage (_("Loading configuration"));
268 Config = new RCConfiguration;
270 if (Config->load_state ()) {
274 Config->set_use_windows_vst (use_windows_vst);
276 Config->set_use_lxvst(true);
279 Profile = new RuntimeProfile;
282 #ifdef WINDOWS_VST_SUPPORT
283 if (Config->get_use_windows_vst() && fst_init (0)) {
289 if (Config->get_use_lxvst() && vstfx_init (0)) {
294 #ifdef AUDIOUNIT_SUPPORT
295 AUPluginInfo::load_cached_info ();
298 setup_hardware_optimization (try_optimization);
300 SourceFactory::init ();
303 /* singleton - first object is "it" */
304 (void) PluginManager::instance();
306 ProcessThread::init ();
307 /* the + 4 is a bit of a handwave. i don't actually know
308 how many more per-thread buffer sets we need above
309 the h/w concurrency, but its definitely > 1 more.
311 BufferManager::init (hardware_concurrency() + 4);
313 PannerManager::instance().discover_panners();
315 // Initialize parameter metadata
316 EventTypeMap::instance().new_parameter(NullAutomation);
317 EventTypeMap::instance().new_parameter(GainAutomation);
318 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
319 EventTypeMap::instance().new_parameter(PanElevationAutomation);
320 EventTypeMap::instance().new_parameter(PanWidthAutomation);
321 EventTypeMap::instance().new_parameter(PluginAutomation);
322 EventTypeMap::instance().new_parameter(SoloAutomation);
323 EventTypeMap::instance().new_parameter(MuteAutomation);
324 EventTypeMap::instance().new_parameter(MidiCCAutomation);
325 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
326 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
327 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
328 EventTypeMap::instance().new_parameter(FadeInAutomation);
329 EventTypeMap::instance().new_parameter(FadeOutAutomation);
330 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
331 EventTypeMap::instance().new_parameter(MidiCCAutomation);
333 libardour_initialized = true;
339 ARDOUR::init_post_engine ()
341 /* the MIDI Manager is needed by the ControlProtocolManager */
342 MIDI::Manager::create (AudioEngine::instance()->jack());
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
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);