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 */
55 #include <glibmm/fileutils.h>
56 #include <glibmm/miscutils.h>
61 #include "pbd/error.h"
63 #include "pbd/strsplit.h"
65 #include "pbd/file_utils.h"
66 #include "pbd/enumwriter.h"
67 #include "pbd/basename.h"
69 #include "midi++/port.h"
70 #include "midi++/mmc.h"
72 #include "ardour/analyser.h"
73 #include "ardour/audio_library.h"
74 #include "ardour/audio_backend.h"
75 #include "ardour/audioengine.h"
76 #include "ardour/audioplaylist.h"
77 #include "ardour/audioregion.h"
78 #include "ardour/buffer_manager.h"
79 #include "ardour/control_protocol_manager.h"
80 #include "ardour/filesystem_paths.h"
81 #include "ardour/midi_region.h"
82 #include "ardour/midiport_manager.h"
83 #include "ardour/mix.h"
84 #include "ardour/panner_manager.h"
85 #include "ardour/plugin_manager.h"
86 #include "ardour/process_thread.h"
87 #include "ardour/profile.h"
88 #include "ardour/rc_configuration.h"
89 #include "ardour/region.h"
90 #include "ardour/route_group.h"
91 #include "ardour/runtime_functions.h"
92 #include "ardour/session_event.h"
93 #include "ardour/source_factory.h"
95 #include "audiographer/routines.h"
97 #if defined (__APPLE__)
98 #include <Carbon/Carbon.h> // For Gestalt
103 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
104 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
105 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
107 using namespace ARDOUR;
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 (!Glib::thread_supported()) {
226 // this really should be in PBD::init..if there was one
230 (void) bindtextdomain(PACKAGE, localedir);
234 SessionEvent::init_event_pool ();
236 SessionObject::make_property_quarks ();
237 Region::make_property_quarks ();
238 MidiRegion::make_property_quarks ();
239 AudioRegion::make_property_quarks ();
240 RouteGroup::make_property_quarks ();
241 Playlist::make_property_quarks ();
242 AudioPlaylist::make_property_quarks ();
244 /* this is a useful ready to use PropertyChange that many
245 things need to check. This avoids having to compose
246 it every time we want to check for any of the relevant
250 bounds_change.add (ARDOUR::Properties::start);
251 bounds_change.add (ARDOUR::Properties::position);
252 bounds_change.add (ARDOUR::Properties::length);
254 /* provide a state version for the few cases that need it and are not
255 driven by reading state from disk (e.g. undo/redo)
258 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
260 ARDOUR::setup_enum_writer ();
262 // allow ardour the absolute maximum number of open files
263 lotsa_files_please ();
266 Library = new AudioLibrary;
268 BootMessage (_("Loading configuration"));
270 Config = new RCConfiguration;
272 if (Config->load_state ()) {
276 Config->set_use_windows_vst (use_windows_vst);
278 Config->set_use_lxvst(true);
281 Profile = new RuntimeProfile;
284 #ifdef WINDOWS_VST_SUPPORT
285 if (Config->get_use_windows_vst() && fst_init (0)) {
291 if (Config->get_use_lxvst() && vstfx_init (0)) {
296 #ifdef AUDIOUNIT_SUPPORT
297 AUPluginInfo::load_cached_info ();
300 setup_hardware_optimization (try_optimization);
302 SourceFactory::init ();
305 /* singleton - first object is "it" */
306 (void) PluginManager::instance();
308 ProcessThread::init ();
309 /* the + 4 is a bit of a handwave. i don't actually know
310 how many more per-thread buffer sets we need above
311 the h/w concurrency, but its definitely > 1 more.
313 BufferManager::init (hardware_concurrency() + 4);
315 PannerManager::instance().discover_panners();
317 // Initialize parameter metadata
318 EventTypeMap::instance().new_parameter(NullAutomation);
319 EventTypeMap::instance().new_parameter(GainAutomation);
320 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
321 EventTypeMap::instance().new_parameter(PanElevationAutomation);
322 EventTypeMap::instance().new_parameter(PanWidthAutomation);
323 EventTypeMap::instance().new_parameter(PluginAutomation);
324 EventTypeMap::instance().new_parameter(SoloAutomation);
325 EventTypeMap::instance().new_parameter(MuteAutomation);
326 EventTypeMap::instance().new_parameter(MidiCCAutomation);
327 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
328 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
329 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
330 EventTypeMap::instance().new_parameter(FadeInAutomation);
331 EventTypeMap::instance().new_parameter(FadeOutAutomation);
332 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
333 EventTypeMap::instance().new_parameter(MidiCCAutomation);
335 ARDOUR::AudioEngine::create ();
341 ARDOUR::init_post_engine ()
343 ControlProtocolManager::instance().discover_control_protocols ();
346 if ((node = Config->control_protocol_state()) != 0) {
347 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
352 ARDOUR::PluginManager::instance().refresh ();
360 delete &ControlProtocolManager::instance();
361 #ifdef WINDOWS_VST_SUPPORT
368 EnumWriter::destroy ();
373 ARDOUR::find_bindings_files (map<string,string>& files)
375 vector<std::string> found;
376 SearchPath spath = ardour_config_search_path();
378 if (getenv ("ARDOUR_SAE")) {
379 Glib::PatternSpec pattern("*SAE-*.bindings");
380 find_matching_files_in_search_path (spath, pattern, found);
382 Glib::PatternSpec pattern("*.bindings");
383 find_matching_files_in_search_path (spath, pattern, found);
390 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
391 std::string path(*x);
392 pair<string,string> namepath;
393 namepath.second = path;
394 namepath.first = PBD::basename_nosuffix (path);
395 files.insert (namepath);
400 ARDOUR::no_auto_connect()
402 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
409 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
410 // valgrind doesn't understand this assembler stuff
411 // September 10th, 2007
415 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
420 /* XXX use real code to determine if the processor supports
421 DenormalsAreZero and FlushToZero
424 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
428 MXCSR = _mm_getcsr();
430 #ifdef DEBUG_DENORMAL_EXCEPTION
431 /* This will raise a FP exception if a denormal is detected */
432 MXCSR &= ~_MM_MASK_DENORM;
435 switch (Config->get_denormal_model()) {
437 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
441 if (fpu.has_flush_to_zero()) {
442 MXCSR |= _MM_FLUSH_ZERO_ON;
447 MXCSR &= ~_MM_FLUSH_ZERO_ON;
448 if (fpu.has_denormals_are_zero()) {
454 if (fpu.has_flush_to_zero()) {
455 if (fpu.has_denormals_are_zero()) {
456 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
458 MXCSR |= _MM_FLUSH_ZERO_ON;
469 /* this can be changed to modify the translation behaviour for
470 cases where the user has never expressed a preference.
472 static const bool translate_by_default = true;
475 ARDOUR::translation_enable_path ()
477 return Glib::build_filename (user_config_directory(), ".translate");
481 ARDOUR::translations_are_enabled ()
483 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
486 return translate_by_default;
492 if (::read (fd, &c, 1) == 1 && c == '1') {
502 ARDOUR::set_translations_enabled (bool yn)
504 string i18n_enabler = ARDOUR::translation_enable_path();
505 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
527 ARDOUR::get_available_sync_options ()
529 vector<SyncSource> ret;
531 ret.push_back (JACK);
533 ret.push_back (MIDIClock);