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
227 (void) bindtextdomain(PACKAGE, localedir);
230 SessionEvent::init_event_pool ();
232 SessionObject::make_property_quarks ();
233 Region::make_property_quarks ();
234 MidiRegion::make_property_quarks ();
235 AudioRegion::make_property_quarks ();
236 RouteGroup::make_property_quarks ();
237 Playlist::make_property_quarks ();
238 AudioPlaylist::make_property_quarks ();
240 /* this is a useful ready to use PropertyChange that many
241 things need to check. This avoids having to compose
242 it every time we want to check for any of the relevant
246 bounds_change.add (ARDOUR::Properties::start);
247 bounds_change.add (ARDOUR::Properties::position);
248 bounds_change.add (ARDOUR::Properties::length);
250 /* provide a state version for the few cases that need it and are not
251 driven by reading state from disk (e.g. undo/redo)
254 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
256 ARDOUR::setup_enum_writer ();
258 // allow ardour the absolute maximum number of open files
259 lotsa_files_please ();
262 Library = new AudioLibrary;
264 BootMessage (_("Loading configuration"));
266 Config = new RCConfiguration;
268 if (Config->load_state ()) {
272 Config->set_use_windows_vst (use_windows_vst);
274 Config->set_use_lxvst(true);
277 Profile = new RuntimeProfile;
280 #ifdef WINDOWS_VST_SUPPORT
281 if (Config->get_use_windows_vst() && fst_init (0)) {
287 if (Config->get_use_lxvst() && vstfx_init (0)) {
292 #ifdef AUDIOUNIT_SUPPORT
293 AUPluginInfo::load_cached_info ();
296 setup_hardware_optimization (try_optimization);
298 SourceFactory::init ();
301 /* singleton - first object is "it" */
302 (void) PluginManager::instance();
304 ProcessThread::init ();
305 /* the + 4 is a bit of a handwave. i don't actually know
306 how many more per-thread buffer sets we need above
307 the h/w concurrency, but its definitely > 1 more.
309 BufferManager::init (hardware_concurrency() + 4);
311 PannerManager::instance().discover_panners();
313 // Initialize parameter metadata
314 EventTypeMap::instance().new_parameter(NullAutomation);
315 EventTypeMap::instance().new_parameter(GainAutomation);
316 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
317 EventTypeMap::instance().new_parameter(PanElevationAutomation);
318 EventTypeMap::instance().new_parameter(PanWidthAutomation);
319 EventTypeMap::instance().new_parameter(PluginAutomation);
320 EventTypeMap::instance().new_parameter(SoloAutomation);
321 EventTypeMap::instance().new_parameter(MuteAutomation);
322 EventTypeMap::instance().new_parameter(MidiCCAutomation);
323 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
324 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
325 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
326 EventTypeMap::instance().new_parameter(FadeInAutomation);
327 EventTypeMap::instance().new_parameter(FadeOutAutomation);
328 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
329 EventTypeMap::instance().new_parameter(MidiCCAutomation);
335 ARDOUR::init_post_engine ()
337 /* the MIDI Manager is needed by the ControlProtocolManager */
338 MIDI::Manager::create (AudioEngine::instance()->jack());
340 ControlProtocolManager::instance().discover_control_protocols ();
343 if ((node = Config->control_protocol_state()) != 0) {
344 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
349 ARDOUR::PluginManager::instance().refresh ();
357 delete &ControlProtocolManager::instance();
358 #ifdef WINDOWS_VST_SUPPORT
365 EnumWriter::destroy ();
370 ARDOUR::find_bindings_files (map<string,string>& files)
372 vector<std::string> found;
373 SearchPath spath = ardour_config_search_path();
375 if (getenv ("ARDOUR_SAE")) {
376 Glib::PatternSpec pattern("*SAE-*.bindings");
377 find_matching_files_in_search_path (spath, pattern, found);
379 Glib::PatternSpec pattern("*.bindings");
380 find_matching_files_in_search_path (spath, pattern, found);
387 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
388 std::string path(*x);
389 pair<string,string> namepath;
390 namepath.second = path;
391 namepath.first = PBD::basename_nosuffix (path);
392 files.insert (namepath);
397 ARDOUR::no_auto_connect()
399 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
406 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
407 // valgrind doesn't understand this assembler stuff
408 // September 10th, 2007
412 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
417 /* XXX use real code to determine if the processor supports
418 DenormalsAreZero and FlushToZero
421 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
425 MXCSR = _mm_getcsr();
427 #ifdef DEBUG_DENORMAL_EXCEPTION
428 /* This will raise a FP exception if a denormal is detected */
429 MXCSR &= ~_MM_MASK_DENORM;
432 switch (Config->get_denormal_model()) {
434 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
438 if (fpu.has_flush_to_zero()) {
439 MXCSR |= _MM_FLUSH_ZERO_ON;
444 MXCSR &= ~_MM_FLUSH_ZERO_ON;
445 if (fpu.has_denormals_are_zero()) {
451 if (fpu.has_flush_to_zero()) {
452 if (fpu.has_denormals_are_zero()) {
453 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
455 MXCSR |= _MM_FLUSH_ZERO_ON;
467 ARDOUR::translation_kill_path ()
469 return Glib::build_filename (user_config_directory(), ".love_is_the_language_of_audio");
473 ARDOUR::translations_are_disabled ()
475 /* if file does not exist, we don't translate (bundled ardour only) */
476 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;
480 ARDOUR::get_available_sync_options ()
482 vector<SyncSource> ret;
484 ret.push_back (JACK);
486 ret.push_back (MIDIClock);