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++/manager.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/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 /* the MIDI Manager is needed by the ControlProtocolManager */
344 MIDI::Manager::create (AudioEngine::instance()->port_engine());
346 ControlProtocolManager::instance().discover_control_protocols ();
349 if ((node = Config->control_protocol_state()) != 0) {
350 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
355 ARDOUR::PluginManager::instance().refresh ();
363 delete &ControlProtocolManager::instance();
364 #ifdef WINDOWS_VST_SUPPORT
371 EnumWriter::destroy ();
376 ARDOUR::find_bindings_files (map<string,string>& files)
378 vector<std::string> found;
379 SearchPath spath = ardour_config_search_path();
381 if (getenv ("ARDOUR_SAE")) {
382 Glib::PatternSpec pattern("*SAE-*.bindings");
383 find_matching_files_in_search_path (spath, pattern, found);
385 Glib::PatternSpec pattern("*.bindings");
386 find_matching_files_in_search_path (spath, pattern, found);
393 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
394 std::string path(*x);
395 pair<string,string> namepath;
396 namepath.second = path;
397 namepath.first = PBD::basename_nosuffix (path);
398 files.insert (namepath);
403 ARDOUR::no_auto_connect()
405 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
412 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
413 // valgrind doesn't understand this assembler stuff
414 // September 10th, 2007
418 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
423 /* XXX use real code to determine if the processor supports
424 DenormalsAreZero and FlushToZero
427 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
431 MXCSR = _mm_getcsr();
433 #ifdef DEBUG_DENORMAL_EXCEPTION
434 /* This will raise a FP exception if a denormal is detected */
435 MXCSR &= ~_MM_MASK_DENORM;
438 switch (Config->get_denormal_model()) {
440 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
444 if (fpu.has_flush_to_zero()) {
445 MXCSR |= _MM_FLUSH_ZERO_ON;
450 MXCSR &= ~_MM_FLUSH_ZERO_ON;
451 if (fpu.has_denormals_are_zero()) {
457 if (fpu.has_flush_to_zero()) {
458 if (fpu.has_denormals_are_zero()) {
459 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
461 MXCSR |= _MM_FLUSH_ZERO_ON;
472 /* this can be changed to modify the translation behaviour for
473 cases where the user has never expressed a preference.
475 static const bool translate_by_default = true;
478 ARDOUR::translation_enable_path ()
480 return Glib::build_filename (user_config_directory(), ".translate");
484 ARDOUR::translations_are_enabled ()
486 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
489 return translate_by_default;
495 if (::read (fd, &c, 1) == 1 && c == '1') {
505 ARDOUR::set_translations_enabled (bool yn)
507 string i18n_enabler = ARDOUR::translation_enable_path();
508 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
530 ARDOUR::get_available_sync_options ()
532 vector<SyncSource> ret;
534 ret.push_back (JACK);
536 ret.push_back (MIDIClock);