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
25 #include <sys/types.h>
27 #include <sys/resource.h>
32 #ifdef WINDOWS_VST_SUPPORT
37 #include "ardour/linux_vst_support.h"
40 #ifdef AUDIOUNIT_SUPPORT
41 #include "ardour/audio_unit.h"
45 #include <xmmintrin.h>
49 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
54 #include <glibmm/fileutils.h>
55 #include <glibmm/miscutils.h>
60 #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 compute_peak_t ARDOUR::compute_peak = 0;
110 find_peaks_t ARDOUR::find_peaks = 0;
111 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
112 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
113 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
115 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
116 PBD::Signal0<void> ARDOUR::GUIIdle;
119 extern void setup_enum_writer ();
122 /* this is useful for quite a few things that want to check
123 if any bounds-related property has changed
125 PBD::PropertyChange ARDOUR::bounds_change;
128 setup_hardware_optimization (bool try_optimization)
130 bool generic_mix_functions = true;
132 if (try_optimization) {
136 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
140 info << "Using SSE optimized routines" << endmsg;
143 compute_peak = x86_sse_compute_peak;
144 find_peaks = x86_sse_find_peaks;
145 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
146 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
147 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
149 generic_mix_functions = false;
153 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
154 SInt32 sysVersion = 0;
156 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
159 if (sysVersion >= 0x00001040) { // Tiger at least
160 compute_peak = veclib_compute_peak;
161 find_peaks = veclib_find_peaks;
162 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
163 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
164 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
166 generic_mix_functions = false;
168 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
172 /* consider FPU denormal handling to be "h/w optimization" */
177 if (generic_mix_functions) {
179 compute_peak = default_compute_peak;
180 find_peaks = default_find_peaks;
181 apply_gain_to_buffer = default_apply_gain_to_buffer;
182 mix_buffers_with_gain = default_mix_buffers_with_gain;
183 mix_buffers_no_gain = default_mix_buffers_no_gain;
185 info << "No H/W specific optimizations in use" << endmsg;
188 AudioGrapher::Routines::override_compute_peak (compute_peak);
189 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
193 lotsa_files_please ()
197 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
199 rl.rlim_cur = rl.rlim_max;
201 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
202 if (rl.rlim_cur == RLIM_INFINITY) {
203 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
205 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
208 if (rl.rlim_cur != RLIM_INFINITY) {
209 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
213 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
218 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
220 if (!Glib::thread_supported()) {
224 // this really should be in PBD::init..if there was one
228 (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);
337 ARDOUR::init_post_engine ()
339 /* the MIDI Manager is needed by the ControlProtocolManager */
340 MIDI::Manager::create (AudioEngine::instance()->jack());
342 ControlProtocolManager::instance().discover_control_protocols ();
345 if ((node = Config->control_protocol_state()) != 0) {
346 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
351 ARDOUR::PluginManager::instance().refresh ();
359 delete &ControlProtocolManager::instance();
360 #ifdef WINDOWS_VST_SUPPORT
367 EnumWriter::destroy ();
372 ARDOUR::find_bindings_files (map<string,string>& files)
374 vector<std::string> found;
375 SearchPath spath = ardour_config_search_path();
377 if (getenv ("ARDOUR_SAE")) {
378 Glib::PatternSpec pattern("*SAE-*.bindings");
379 find_matching_files_in_search_path (spath, pattern, found);
381 Glib::PatternSpec pattern("*.bindings");
382 find_matching_files_in_search_path (spath, pattern, found);
389 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
390 std::string path(*x);
391 pair<string,string> namepath;
392 namepath.second = path;
393 namepath.first = PBD::basename_nosuffix (path);
394 files.insert (namepath);
399 ARDOUR::no_auto_connect()
401 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
408 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
409 // valgrind doesn't understand this assembler stuff
410 // September 10th, 2007
414 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
419 /* XXX use real code to determine if the processor supports
420 DenormalsAreZero and FlushToZero
423 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
427 MXCSR = _mm_getcsr();
429 #ifdef DEBUG_DENORMAL_EXCEPTION
430 /* This will raise a FP exception if a denormal is detected */
431 MXCSR &= ~_MM_MASK_DENORM;
434 switch (Config->get_denormal_model()) {
436 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
440 if (fpu.has_flush_to_zero()) {
441 MXCSR |= _MM_FLUSH_ZERO_ON;
446 MXCSR &= ~_MM_FLUSH_ZERO_ON;
447 if (fpu.has_denormals_are_zero()) {
453 if (fpu.has_flush_to_zero()) {
454 if (fpu.has_denormals_are_zero()) {
455 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
457 MXCSR |= _MM_FLUSH_ZERO_ON;
469 ARDOUR::translation_kill_path ()
471 return Glib::build_filename (user_config_directory(), ".love_is_the_language_of_audio");
475 ARDOUR::translations_are_disabled ()
477 /* if file does not exist, we don't translate (bundled ardour only) */
478 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;
482 ARDOUR::get_available_sync_options ()
484 vector<SyncSource> ret;
486 ret.push_back (JACK);
488 ret.push_back (MIDIClock);