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"
64 #include "pbd/strsplit.h"
66 #include "pbd/file_utils.h"
67 #include "pbd/enumwriter.h"
68 #include "pbd/basename.h"
70 #include "midi++/port.h"
71 #include "midi++/manager.h"
72 #include "midi++/mmc.h"
74 #include "ardour/analyser.h"
75 #include "ardour/audio_library.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 bool libardour_initialized = false;
113 compute_peak_t ARDOUR::compute_peak = 0;
114 find_peaks_t ARDOUR::find_peaks = 0;
115 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
116 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
117 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
119 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
120 PBD::Signal0<void> ARDOUR::GUIIdle;
123 extern void setup_enum_writer ();
126 /* this is useful for quite a few things that want to check
127 if any bounds-related property has changed
129 PBD::PropertyChange ARDOUR::bounds_change;
132 setup_hardware_optimization (bool try_optimization)
134 bool generic_mix_functions = true;
136 if (try_optimization) {
140 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
144 info << "Using SSE optimized routines" << endmsg;
147 compute_peak = x86_sse_compute_peak;
148 find_peaks = x86_sse_find_peaks;
149 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
150 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
151 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
153 generic_mix_functions = false;
157 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
158 SInt32 sysVersion = 0;
160 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
163 if (sysVersion >= 0x00001040) { // Tiger at least
164 compute_peak = veclib_compute_peak;
165 find_peaks = veclib_find_peaks;
166 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
167 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
168 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
170 generic_mix_functions = false;
172 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
176 /* consider FPU denormal handling to be "h/w optimization" */
181 if (generic_mix_functions) {
183 compute_peak = default_compute_peak;
184 find_peaks = default_find_peaks;
185 apply_gain_to_buffer = default_apply_gain_to_buffer;
186 mix_buffers_with_gain = default_mix_buffers_with_gain;
187 mix_buffers_no_gain = default_mix_buffers_no_gain;
189 info << "No H/W specific optimizations in use" << endmsg;
192 AudioGrapher::Routines::override_compute_peak (compute_peak);
193 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
197 lotsa_files_please ()
201 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
203 rl.rlim_cur = rl.rlim_max;
205 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
206 if (rl.rlim_cur == RLIM_INFINITY) {
207 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
209 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
212 if (rl.rlim_cur != RLIM_INFINITY) {
213 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
217 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
222 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
224 if (libardour_initialized) {
228 if (!PBD::init()) return false;
230 // this really should be in PBD::init..if there was one
234 (void) bindtextdomain(PACKAGE, localedir);
237 SessionEvent::init_event_pool ();
239 SessionObject::make_property_quarks ();
240 Region::make_property_quarks ();
241 MidiRegion::make_property_quarks ();
242 AudioRegion::make_property_quarks ();
243 RouteGroup::make_property_quarks ();
244 Playlist::make_property_quarks ();
245 AudioPlaylist::make_property_quarks ();
247 /* this is a useful ready to use PropertyChange that many
248 things need to check. This avoids having to compose
249 it every time we want to check for any of the relevant
253 bounds_change.add (ARDOUR::Properties::start);
254 bounds_change.add (ARDOUR::Properties::position);
255 bounds_change.add (ARDOUR::Properties::length);
257 /* provide a state version for the few cases that need it and are not
258 driven by reading state from disk (e.g. undo/redo)
261 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
263 ARDOUR::setup_enum_writer ();
265 // allow ardour the absolute maximum number of open files
266 lotsa_files_please ();
269 Library = new AudioLibrary;
271 BootMessage (_("Loading configuration"));
273 Config = new RCConfiguration;
275 if (Config->load_state ()) {
279 Config->set_use_windows_vst (use_windows_vst);
281 Config->set_use_lxvst(true);
284 Profile = new RuntimeProfile;
287 #ifdef WINDOWS_VST_SUPPORT
288 if (Config->get_use_windows_vst() && fst_init (0)) {
294 if (Config->get_use_lxvst() && vstfx_init (0)) {
299 #ifdef AUDIOUNIT_SUPPORT
300 AUPluginInfo::load_cached_info ();
303 setup_hardware_optimization (try_optimization);
305 SourceFactory::init ();
308 /* singleton - first object is "it" */
309 (void) PluginManager::instance();
311 ProcessThread::init ();
312 /* the + 4 is a bit of a handwave. i don't actually know
313 how many more per-thread buffer sets we need above
314 the h/w concurrency, but its definitely > 1 more.
316 BufferManager::init (hardware_concurrency() + 4);
318 PannerManager::instance().discover_panners();
320 // Initialize parameter metadata
321 EventTypeMap::instance().new_parameter(NullAutomation);
322 EventTypeMap::instance().new_parameter(GainAutomation);
323 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
324 EventTypeMap::instance().new_parameter(PanElevationAutomation);
325 EventTypeMap::instance().new_parameter(PanWidthAutomation);
326 EventTypeMap::instance().new_parameter(PluginAutomation);
327 EventTypeMap::instance().new_parameter(SoloAutomation);
328 EventTypeMap::instance().new_parameter(MuteAutomation);
329 EventTypeMap::instance().new_parameter(MidiCCAutomation);
330 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
331 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
332 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
333 EventTypeMap::instance().new_parameter(FadeInAutomation);
334 EventTypeMap::instance().new_parameter(FadeOutAutomation);
335 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
336 EventTypeMap::instance().new_parameter(MidiCCAutomation);
338 libardour_initialized = true;
344 ARDOUR::init_post_engine ()
346 /* the MIDI Manager is needed by the ControlProtocolManager */
347 MIDI::Manager::create (AudioEngine::instance()->jack());
349 ControlProtocolManager::instance().discover_control_protocols ();
352 if ((node = Config->control_protocol_state()) != 0) {
353 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
358 ARDOUR::PluginManager::instance().refresh ();
366 delete &ControlProtocolManager::instance();
367 #ifdef WINDOWS_VST_SUPPORT
379 ARDOUR::find_bindings_files (map<string,string>& files)
381 vector<std::string> found;
382 SearchPath spath = ardour_config_search_path();
384 if (getenv ("ARDOUR_SAE")) {
385 Glib::PatternSpec pattern("*SAE-*.bindings");
386 find_matching_files_in_search_path (spath, pattern, found);
388 Glib::PatternSpec pattern("*.bindings");
389 find_matching_files_in_search_path (spath, pattern, found);
396 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
397 std::string path(*x);
398 pair<string,string> namepath;
399 namepath.second = path;
400 namepath.first = PBD::basename_nosuffix (path);
401 files.insert (namepath);
406 ARDOUR::no_auto_connect()
408 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
415 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
416 // valgrind doesn't understand this assembler stuff
417 // September 10th, 2007
421 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
426 /* XXX use real code to determine if the processor supports
427 DenormalsAreZero and FlushToZero
430 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
434 MXCSR = _mm_getcsr();
436 #ifdef DEBUG_DENORMAL_EXCEPTION
437 /* This will raise a FP exception if a denormal is detected */
438 MXCSR &= ~_MM_MASK_DENORM;
441 switch (Config->get_denormal_model()) {
443 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
447 if (fpu.has_flush_to_zero()) {
448 MXCSR |= _MM_FLUSH_ZERO_ON;
453 MXCSR &= ~_MM_FLUSH_ZERO_ON;
454 if (fpu.has_denormals_are_zero()) {
460 if (fpu.has_flush_to_zero()) {
461 if (fpu.has_denormals_are_zero()) {
462 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
464 MXCSR |= _MM_FLUSH_ZERO_ON;
475 /* this can be changed to modify the translation behaviour for
476 cases where the user has never expressed a preference.
478 static const bool translate_by_default = true;
481 ARDOUR::translation_enable_path ()
483 return Glib::build_filename (user_config_directory(), ".translate");
487 ARDOUR::translations_are_enabled ()
489 int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
492 return translate_by_default;
498 if (::read (fd, &c, 1) == 1 && c == '1') {
508 ARDOUR::set_translations_enabled (bool yn)
510 string i18n_enabler = ARDOUR::translation_enable_path();
511 int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
533 ARDOUR::get_available_sync_options ()
535 vector<SyncSource> ret;
537 ret.push_back (JACK);
539 ret.push_back (MIDIClock);