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>
29 #include <sys/resource.h>
35 #ifdef WINDOWS_VST_SUPPORT
40 #include "ardour/linux_vst_support.h"
43 #ifdef AUDIOUNIT_SUPPORT
44 #include "ardour/audio_unit.h"
48 #include <xmmintrin.h>
52 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
57 #include <glibmm/fileutils.h>
58 #include <glibmm/miscutils.h>
65 #include "pbd/error.h"
67 #include "pbd/strsplit.h"
69 #include "pbd/file_utils.h"
70 #include "pbd/enumwriter.h"
71 #include "pbd/basename.h"
73 #include "midi++/port.h"
74 #include "midi++/manager.h"
75 #include "midi++/mmc.h"
77 #include "ardour/analyser.h"
78 #include "ardour/audio_library.h"
79 #include "ardour/audioengine.h"
80 #include "ardour/audioplaylist.h"
81 #include "ardour/audioregion.h"
82 #include "ardour/buffer_manager.h"
83 #include "ardour/control_protocol_manager.h"
84 #include "ardour/filesystem_paths.h"
85 #include "ardour/midi_region.h"
86 #include "ardour/mix.h"
87 #include "ardour/panner_manager.h"
88 #include "ardour/plugin_manager.h"
89 #include "ardour/process_thread.h"
90 #include "ardour/profile.h"
91 #include "ardour/rc_configuration.h"
92 #include "ardour/region.h"
93 #include "ardour/route_group.h"
94 #include "ardour/runtime_functions.h"
95 #include "ardour/session_event.h"
96 #include "ardour/source_factory.h"
98 #include "audiographer/routines.h"
100 #if defined (__APPLE__)
101 #include <Carbon/Carbon.h> // For Gestalt
106 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
107 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
108 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
110 using namespace ARDOUR;
114 compute_peak_t ARDOUR::compute_peak = 0;
115 find_peaks_t ARDOUR::find_peaks = 0;
116 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
117 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
118 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
120 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
121 PBD::Signal0<void> ARDOUR::GUIIdle;
124 extern void setup_enum_writer ();
127 /* this is useful for quite a few things that want to check
128 if any bounds-related property has changed
130 PBD::PropertyChange ARDOUR::bounds_change;
133 setup_hardware_optimization (bool try_optimization)
135 bool generic_mix_functions = true;
137 if (try_optimization) {
141 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
145 info << "Using SSE optimized routines" << endmsg;
148 compute_peak = x86_sse_compute_peak;
149 find_peaks = x86_sse_find_peaks;
150 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
151 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
152 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
154 generic_mix_functions = false;
158 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
159 SInt32 sysVersion = 0;
161 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
164 if (sysVersion >= 0x00001040) { // Tiger at least
165 compute_peak = veclib_compute_peak;
166 find_peaks = veclib_find_peaks;
167 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
168 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
169 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
171 generic_mix_functions = false;
173 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
177 /* consider FPU denormal handling to be "h/w optimization" */
182 if (generic_mix_functions) {
184 compute_peak = default_compute_peak;
185 find_peaks = default_find_peaks;
186 apply_gain_to_buffer = default_apply_gain_to_buffer;
187 mix_buffers_with_gain = default_mix_buffers_with_gain;
188 mix_buffers_no_gain = default_mix_buffers_no_gain;
190 info << "No H/W specific optimizations in use" << endmsg;
193 AudioGrapher::Routines::override_compute_peak (compute_peak);
194 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
198 lotsa_files_please ()
203 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
205 rl.rlim_cur = rl.rlim_max;
207 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
208 if (rl.rlim_cur == RLIM_INFINITY) {
209 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
211 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
214 if (rl.rlim_cur != RLIM_INFINITY) {
215 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
219 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
225 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
227 if (!Glib::thread_supported()) {
231 // this really should be in PBD::init..if there was one
235 (void) bindtextdomain(PACKAGE, localedir);
239 SessionEvent::init_event_pool ();
241 SessionObject::make_property_quarks ();
242 Region::make_property_quarks ();
243 MidiRegion::make_property_quarks ();
244 AudioRegion::make_property_quarks ();
245 RouteGroup::make_property_quarks ();
246 Playlist::make_property_quarks ();
247 AudioPlaylist::make_property_quarks ();
249 /* this is a useful ready to use PropertyChange that many
250 things need to check. This avoids having to compose
251 it every time we want to check for any of the relevant
255 bounds_change.add (ARDOUR::Properties::start);
256 bounds_change.add (ARDOUR::Properties::position);
257 bounds_change.add (ARDOUR::Properties::length);
259 /* provide a state version for the few cases that need it and are not
260 driven by reading state from disk (e.g. undo/redo)
263 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
265 ARDOUR::setup_enum_writer ();
267 // allow ardour the absolute maximum number of open files
268 lotsa_files_please ();
273 Library = new AudioLibrary;
275 BootMessage (_("Loading configuration"));
277 Config = new RCConfiguration;
279 if (Config->load_state ()) {
283 Config->set_use_windows_vst (use_windows_vst);
285 Config->set_use_lxvst(true);
288 Profile = new RuntimeProfile;
291 #ifdef WINDOWS_VST_SUPPORT
292 if (Config->get_use_windows_vst() && fst_init (0)) {
298 if (Config->get_use_lxvst() && vstfx_init (0)) {
303 #ifdef AUDIOUNIT_SUPPORT
304 AUPluginInfo::load_cached_info ();
307 setup_hardware_optimization (try_optimization);
309 SourceFactory::init ();
312 /* singleton - first object is "it" */
313 (void) PluginManager::instance();
315 ProcessThread::init ();
316 /* the + 4 is a bit of a handwave. i don't actually know
317 how many more per-thread buffer sets we need above
318 the h/w concurrency, but its definitely > 1 more.
320 BufferManager::init (hardware_concurrency() + 4);
322 PannerManager::instance().discover_panners();
324 // Initialize parameter metadata
325 EventTypeMap::instance().new_parameter(NullAutomation);
326 EventTypeMap::instance().new_parameter(GainAutomation);
327 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
328 EventTypeMap::instance().new_parameter(PanElevationAutomation);
329 EventTypeMap::instance().new_parameter(PanWidthAutomation);
330 EventTypeMap::instance().new_parameter(PluginAutomation);
331 EventTypeMap::instance().new_parameter(SoloAutomation);
332 EventTypeMap::instance().new_parameter(MuteAutomation);
333 EventTypeMap::instance().new_parameter(MidiCCAutomation);
334 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
335 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
336 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
337 EventTypeMap::instance().new_parameter(FadeInAutomation);
338 EventTypeMap::instance().new_parameter(FadeOutAutomation);
339 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
340 EventTypeMap::instance().new_parameter(MidiCCAutomation);
346 ARDOUR::init_post_engine ()
348 /* the MIDI Manager is needed by the ControlProtocolManager */
349 MIDI::Manager::create (AudioEngine::instance()->jack());
351 ControlProtocolManager::instance().discover_control_protocols ();
354 if ((node = Config->control_protocol_state()) != 0) {
355 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
360 ARDOUR::PluginManager::instance().refresh ();
370 delete &ControlProtocolManager::instance();
371 #ifdef WINDOWS_VST_SUPPORT
378 EnumWriter::destroy ();
383 ARDOUR::find_bindings_files (map<string,string>& files)
385 vector<std::string> found;
386 SearchPath spath = ardour_config_search_path();
388 if (getenv ("ARDOUR_SAE")) {
389 Glib::PatternSpec pattern("*SAE-*.bindings");
390 find_matching_files_in_search_path (spath, pattern, found);
392 Glib::PatternSpec pattern("*.bindings");
393 find_matching_files_in_search_path (spath, pattern, found);
400 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
401 std::string path(*x);
402 pair<string,string> namepath;
403 namepath.second = path;
404 namepath.first = PBD::basename_nosuffix (path);
405 files.insert (namepath);
410 ARDOUR::no_auto_connect()
412 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
419 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
420 // valgrind doesn't understand this assembler stuff
421 // September 10th, 2007
425 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
430 /* XXX use real code to determine if the processor supports
431 DenormalsAreZero and FlushToZero
434 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
438 MXCSR = _mm_getcsr();
440 #ifdef DEBUG_DENORMAL_EXCEPTION
441 /* This will raise a FP exception if a denormal is detected */
442 MXCSR &= ~_MM_MASK_DENORM;
445 switch (Config->get_denormal_model()) {
447 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
451 if (fpu.has_flush_to_zero()) {
452 MXCSR |= _MM_FLUSH_ZERO_ON;
457 MXCSR &= ~_MM_FLUSH_ZERO_ON;
458 if (fpu.has_denormals_are_zero()) {
464 if (fpu.has_flush_to_zero()) {
465 if (fpu.has_denormals_are_zero()) {
466 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
468 MXCSR |= _MM_FLUSH_ZERO_ON;
479 /* this can be changed to modify the translation behaviour for
480 cases where the user has never expressed a preference.
482 static const bool translate_by_default = true;
485 ARDOUR::translation_enable_path ()
487 return Glib::build_filename (user_config_directory(), ".translate");
491 ARDOUR::translations_are_enabled ()
493 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
496 return translate_by_default;
502 if (::read (fd, &c, 1) == 1 && c == '1') {
512 ARDOUR::set_translations_enabled (bool yn)
514 string i18n_enabler = ARDOUR::translation_enable_path();
515 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
537 ARDOUR::get_available_sync_options ()
539 vector<SyncSource> ret;
541 ret.push_back (JACK);
543 ret.push_back (MIDIClock);