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>
39 #ifdef WINDOWS_VST_SUPPORT
44 #include "ardour/linux_vst_support.h"
47 #ifdef AUDIOUNIT_SUPPORT
48 #include "ardour/audio_unit.h"
51 #if defined(__SSE__) || defined(USE_XMMINTRIN)
52 #include <xmmintrin.h>
56 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
61 #include <glibmm/fileutils.h>
62 #include <glibmm/miscutils.h>
69 #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++/manager.h"
79 #include "midi++/mmc.h"
81 #include "ardour/analyser.h"
82 #include "ardour/audio_library.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/filesystem_paths.h"
89 #include "ardour/midi_region.h"
90 #include "ardour/mix.h"
91 #include "ardour/panner_manager.h"
92 #include "ardour/plugin_manager.h"
93 #include "ardour/process_thread.h"
94 #include "ardour/profile.h"
95 #include "ardour/rc_configuration.h"
96 #include "ardour/region.h"
97 #include "ardour/route_group.h"
98 #include "ardour/runtime_functions.h"
99 #include "ardour/session_event.h"
100 #include "ardour/source_factory.h"
102 #include "audiographer/routines.h"
104 #if defined (__APPLE__)
105 #include <Carbon/Carbon.h> // For Gestalt
110 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
111 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
112 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
114 using namespace ARDOUR;
118 compute_peak_t ARDOUR::compute_peak = 0;
119 find_peaks_t ARDOUR::find_peaks = 0;
120 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
121 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
122 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
124 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
125 PBD::Signal0<void> ARDOUR::GUIIdle;
128 extern void setup_enum_writer ();
131 /* this is useful for quite a few things that want to check
132 if any bounds-related property has changed
134 PBD::PropertyChange ARDOUR::bounds_change;
137 setup_hardware_optimization (bool try_optimization)
139 bool generic_mix_functions = true;
141 if (try_optimization) {
145 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
149 info << "Using SSE optimized routines" << endmsg;
152 compute_peak = x86_sse_compute_peak;
153 find_peaks = x86_sse_find_peaks;
154 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
155 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
156 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
158 generic_mix_functions = false;
162 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
163 SInt32 sysVersion = 0;
165 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
168 if (sysVersion >= 0x00001040) { // Tiger at least
169 compute_peak = veclib_compute_peak;
170 find_peaks = veclib_find_peaks;
171 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
172 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
173 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
175 generic_mix_functions = false;
177 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
181 /* consider FPU denormal handling to be "h/w optimization" */
186 if (generic_mix_functions) {
188 compute_peak = default_compute_peak;
189 find_peaks = default_find_peaks;
190 apply_gain_to_buffer = default_apply_gain_to_buffer;
191 mix_buffers_with_gain = default_mix_buffers_with_gain;
192 mix_buffers_no_gain = default_mix_buffers_no_gain;
194 info << "No H/W specific optimizations in use" << endmsg;
197 AudioGrapher::Routines::override_compute_peak (compute_peak);
198 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
202 lotsa_files_please ()
204 #ifndef PLATFORM_WINDOWS
207 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
209 rl.rlim_cur = rl.rlim_max;
211 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
212 if (rl.rlim_cur == RLIM_INFINITY) {
213 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
215 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
218 if (rl.rlim_cur != RLIM_INFINITY) {
219 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
223 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
229 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
231 if (!Glib::thread_supported()) {
235 // this really should be in PBD::init..if there was one
239 (void) bindtextdomain(PACKAGE, localedir);
243 SessionEvent::init_event_pool ();
245 SessionObject::make_property_quarks ();
246 Region::make_property_quarks ();
247 MidiRegion::make_property_quarks ();
248 AudioRegion::make_property_quarks ();
249 RouteGroup::make_property_quarks ();
250 Playlist::make_property_quarks ();
251 AudioPlaylist::make_property_quarks ();
253 /* this is a useful ready to use PropertyChange that many
254 things need to check. This avoids having to compose
255 it every time we want to check for any of the relevant
259 bounds_change.add (ARDOUR::Properties::start);
260 bounds_change.add (ARDOUR::Properties::position);
261 bounds_change.add (ARDOUR::Properties::length);
263 /* provide a state version for the few cases that need it and are not
264 driven by reading state from disk (e.g. undo/redo)
267 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
269 ARDOUR::setup_enum_writer ();
271 // allow ardour the absolute maximum number of open files
272 lotsa_files_please ();
277 Library = new AudioLibrary;
279 BootMessage (_("Loading configuration"));
281 Config = new RCConfiguration;
283 if (Config->load_state ()) {
287 Config->set_use_windows_vst (use_windows_vst);
289 Config->set_use_lxvst(true);
292 Profile = new RuntimeProfile;
295 #ifdef WINDOWS_VST_SUPPORT
296 if (Config->get_use_windows_vst() && fst_init (0)) {
302 if (Config->get_use_lxvst() && vstfx_init (0)) {
307 #ifdef AUDIOUNIT_SUPPORT
308 AUPluginInfo::load_cached_info ();
311 setup_hardware_optimization (try_optimization);
313 SourceFactory::init ();
316 /* singleton - first object is "it" */
317 (void) PluginManager::instance();
319 ProcessThread::init ();
320 /* the + 4 is a bit of a handwave. i don't actually know
321 how many more per-thread buffer sets we need above
322 the h/w concurrency, but its definitely > 1 more.
324 BufferManager::init (hardware_concurrency() + 4);
326 PannerManager::instance().discover_panners();
328 // Initialize parameter metadata
329 EventTypeMap::instance().new_parameter(NullAutomation);
330 EventTypeMap::instance().new_parameter(GainAutomation);
331 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
332 EventTypeMap::instance().new_parameter(PanElevationAutomation);
333 EventTypeMap::instance().new_parameter(PanWidthAutomation);
334 EventTypeMap::instance().new_parameter(PluginAutomation);
335 EventTypeMap::instance().new_parameter(SoloAutomation);
336 EventTypeMap::instance().new_parameter(MuteAutomation);
337 EventTypeMap::instance().new_parameter(MidiCCAutomation);
338 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
339 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
340 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
341 EventTypeMap::instance().new_parameter(FadeInAutomation);
342 EventTypeMap::instance().new_parameter(FadeOutAutomation);
343 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
344 EventTypeMap::instance().new_parameter(MidiCCAutomation);
350 ARDOUR::init_post_engine ()
352 /* the MIDI Manager is needed by the ControlProtocolManager */
353 MIDI::Manager::create (AudioEngine::instance()->jack());
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 ();
374 delete &ControlProtocolManager::instance();
375 #ifdef WINDOWS_VST_SUPPORT
382 EnumWriter::destroy ();
387 ARDOUR::find_bindings_files (map<string,string>& files)
389 vector<std::string> found;
390 SearchPath spath = ardour_config_search_path();
392 if (getenv ("ARDOUR_SAE")) {
393 Glib::PatternSpec pattern("*SAE-*.bindings");
394 find_matching_files_in_search_path (spath, pattern, found);
396 Glib::PatternSpec pattern("*.bindings");
397 find_matching_files_in_search_path (spath, pattern, found);
404 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
405 std::string path(*x);
406 pair<string,string> namepath;
407 namepath.second = path;
408 namepath.first = PBD::basename_nosuffix (path);
409 files.insert (namepath);
414 ARDOUR::no_auto_connect()
416 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
423 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
424 // valgrind doesn't understand this assembler stuff
425 // September 10th, 2007
429 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
434 /* XXX use real code to determine if the processor supports
435 DenormalsAreZero and FlushToZero
438 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
442 MXCSR = _mm_getcsr();
444 #ifdef DEBUG_DENORMAL_EXCEPTION
445 /* This will raise a FP exception if a denormal is detected */
446 MXCSR &= ~_MM_MASK_DENORM;
449 switch (Config->get_denormal_model()) {
451 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
455 if (fpu.has_flush_to_zero()) {
456 MXCSR |= _MM_FLUSH_ZERO_ON;
461 MXCSR &= ~_MM_FLUSH_ZERO_ON;
462 if (fpu.has_denormals_are_zero()) {
468 if (fpu.has_flush_to_zero()) {
469 if (fpu.has_denormals_are_zero()) {
470 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
472 MXCSR |= _MM_FLUSH_ZERO_ON;
483 /* this can be changed to modify the translation behaviour for
484 cases where the user has never expressed a preference.
486 static const bool translate_by_default = true;
489 ARDOUR::translation_enable_path ()
491 return Glib::build_filename (user_config_directory(), ".translate");
495 ARDOUR::translations_are_enabled ()
497 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
500 return translate_by_default;
506 if (::read (fd, &c, 1) == 1 && c == '1') {
516 ARDOUR::set_translations_enabled (bool yn)
518 string i18n_enabler = ARDOUR::translation_enable_path();
519 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
541 ARDOUR::get_available_sync_options ()
543 vector<SyncSource> ret;
545 ret.push_back (JACK);
547 ret.push_back (MIDIClock);