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/audioengine.h"
76 #include "ardour/audioplaylist.h"
77 #include "ardour/audioregion.h"
78 #include "ardour/buffer_manager.h"
79 #include "ardour/control_protocol_manager.h"
80 #include "ardour/filesystem_paths.h"
81 #include "ardour/midi_region.h"
82 #include "ardour/mix.h"
83 #include "ardour/panner_manager.h"
84 #include "ardour/plugin_manager.h"
85 #include "ardour/process_thread.h"
86 #include "ardour/profile.h"
87 #include "ardour/rc_configuration.h"
88 #include "ardour/region.h"
89 #include "ardour/route_group.h"
90 #include "ardour/runtime_functions.h"
91 #include "ardour/session_event.h"
92 #include "ardour/source_factory.h"
94 #include "audiographer/routines.h"
96 #if defined (__APPLE__)
97 #include <Carbon/Carbon.h> // For Gestalt
102 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
103 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
104 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
106 using namespace ARDOUR;
110 compute_peak_t ARDOUR::compute_peak = 0;
111 find_peaks_t ARDOUR::find_peaks = 0;
112 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
113 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
114 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
116 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
117 PBD::Signal0<void> ARDOUR::GUIIdle;
120 extern void setup_enum_writer ();
123 /* this is useful for quite a few things that want to check
124 if any bounds-related property has changed
126 PBD::PropertyChange ARDOUR::bounds_change;
129 setup_hardware_optimization (bool try_optimization)
131 bool generic_mix_functions = true;
133 if (try_optimization) {
137 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
141 info << "Using SSE optimized routines" << endmsg;
144 compute_peak = x86_sse_compute_peak;
145 find_peaks = x86_sse_find_peaks;
146 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
147 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
148 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
150 generic_mix_functions = false;
154 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
155 SInt32 sysVersion = 0;
157 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
160 if (sysVersion >= 0x00001040) { // Tiger at least
161 compute_peak = veclib_compute_peak;
162 find_peaks = veclib_find_peaks;
163 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
164 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
165 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
167 generic_mix_functions = false;
169 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
173 /* consider FPU denormal handling to be "h/w optimization" */
178 if (generic_mix_functions) {
180 compute_peak = default_compute_peak;
181 find_peaks = default_find_peaks;
182 apply_gain_to_buffer = default_apply_gain_to_buffer;
183 mix_buffers_with_gain = default_mix_buffers_with_gain;
184 mix_buffers_no_gain = default_mix_buffers_no_gain;
186 info << "No H/W specific optimizations in use" << endmsg;
189 AudioGrapher::Routines::override_compute_peak (compute_peak);
190 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
194 lotsa_files_please ()
198 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
200 rl.rlim_cur = rl.rlim_max;
202 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
203 if (rl.rlim_cur == RLIM_INFINITY) {
204 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
206 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
209 if (rl.rlim_cur != RLIM_INFINITY) {
210 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
214 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
219 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
221 if (!Glib::thread_supported()) {
225 // this really should be in PBD::init..if there was one
229 (void) bindtextdomain(PACKAGE, localedir);
233 SessionEvent::init_event_pool ();
235 SessionObject::make_property_quarks ();
236 Region::make_property_quarks ();
237 MidiRegion::make_property_quarks ();
238 AudioRegion::make_property_quarks ();
239 RouteGroup::make_property_quarks ();
240 Playlist::make_property_quarks ();
241 AudioPlaylist::make_property_quarks ();
243 /* this is a useful ready to use PropertyChange that many
244 things need to check. This avoids having to compose
245 it every time we want to check for any of the relevant
249 bounds_change.add (ARDOUR::Properties::start);
250 bounds_change.add (ARDOUR::Properties::position);
251 bounds_change.add (ARDOUR::Properties::length);
253 /* provide a state version for the few cases that need it and are not
254 driven by reading state from disk (e.g. undo/redo)
257 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
259 ARDOUR::setup_enum_writer ();
261 // allow ardour the absolute maximum number of open files
262 lotsa_files_please ();
265 Library = new AudioLibrary;
267 BootMessage (_("Loading configuration"));
269 Config = new RCConfiguration;
271 if (Config->load_state ()) {
275 Config->set_use_windows_vst (use_windows_vst);
277 Config->set_use_lxvst(true);
280 Profile = new RuntimeProfile;
283 #ifdef WINDOWS_VST_SUPPORT
284 if (Config->get_use_windows_vst() && fst_init (0)) {
290 if (Config->get_use_lxvst() && vstfx_init (0)) {
295 #ifdef AUDIOUNIT_SUPPORT
296 AUPluginInfo::load_cached_info ();
299 setup_hardware_optimization (try_optimization);
301 SourceFactory::init ();
304 /* singleton - first object is "it" */
305 (void) PluginManager::instance();
307 ProcessThread::init ();
308 /* the + 4 is a bit of a handwave. i don't actually know
309 how many more per-thread buffer sets we need above
310 the h/w concurrency, but its definitely > 1 more.
312 BufferManager::init (hardware_concurrency() + 4);
314 PannerManager::instance().discover_panners();
316 // Initialize parameter metadata
317 EventTypeMap::instance().new_parameter(NullAutomation);
318 EventTypeMap::instance().new_parameter(GainAutomation);
319 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
320 EventTypeMap::instance().new_parameter(PanElevationAutomation);
321 EventTypeMap::instance().new_parameter(PanWidthAutomation);
322 EventTypeMap::instance().new_parameter(PluginAutomation);
323 EventTypeMap::instance().new_parameter(SoloAutomation);
324 EventTypeMap::instance().new_parameter(MuteAutomation);
325 EventTypeMap::instance().new_parameter(MidiCCAutomation);
326 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
327 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
328 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
329 EventTypeMap::instance().new_parameter(FadeInAutomation);
330 EventTypeMap::instance().new_parameter(FadeOutAutomation);
331 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
332 EventTypeMap::instance().new_parameter(MidiCCAutomation);
338 ARDOUR::init_post_engine ()
340 /* the MIDI Manager is needed by the ControlProtocolManager */
341 MIDI::Manager::create (AudioEngine::instance()->jack());
343 ControlProtocolManager::instance().discover_control_protocols ();
346 if ((node = Config->control_protocol_state()) != 0) {
347 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
352 ARDOUR::PluginManager::instance().refresh ();
360 delete &ControlProtocolManager::instance();
361 #ifdef WINDOWS_VST_SUPPORT
368 EnumWriter::destroy ();
373 ARDOUR::find_bindings_files (map<string,string>& files)
375 vector<std::string> found;
376 SearchPath spath = ardour_config_search_path();
378 if (getenv ("ARDOUR_SAE")) {
379 Glib::PatternSpec pattern("*SAE-*.bindings");
380 find_matching_files_in_search_path (spath, pattern, found);
382 Glib::PatternSpec pattern("*.bindings");
383 find_matching_files_in_search_path (spath, pattern, found);
390 for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
391 std::string path(*x);
392 pair<string,string> namepath;
393 namepath.second = path;
394 namepath.first = PBD::basename_nosuffix (path);
395 files.insert (namepath);
400 ARDOUR::no_auto_connect()
402 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
409 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
410 // valgrind doesn't understand this assembler stuff
411 // September 10th, 2007
415 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
420 /* XXX use real code to determine if the processor supports
421 DenormalsAreZero and FlushToZero
424 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
428 MXCSR = _mm_getcsr();
430 #ifdef DEBUG_DENORMAL_EXCEPTION
431 /* This will raise a FP exception if a denormal is detected */
432 MXCSR &= ~_MM_MASK_DENORM;
435 switch (Config->get_denormal_model()) {
437 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
441 if (fpu.has_flush_to_zero()) {
442 MXCSR |= _MM_FLUSH_ZERO_ON;
447 MXCSR &= ~_MM_FLUSH_ZERO_ON;
448 if (fpu.has_denormals_are_zero()) {
454 if (fpu.has_flush_to_zero()) {
455 if (fpu.has_denormals_are_zero()) {
456 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
458 MXCSR |= _MM_FLUSH_ZERO_ON;
469 /* this can be changed to modify the translation behaviour for
470 cases where the user has never expressed a preference.
472 static const bool translate_by_default = true;
475 ARDOUR::translation_enable_path ()
477 return Glib::build_filename (user_config_directory(), ".translate");
481 ARDOUR::translations_are_enabled ()
483 if (Glib::file_test (translation_enable_path(), Glib::FILE_TEST_EXISTS)) {
487 return translate_by_default;
491 ARDOUR::set_translations_enabled (bool yn)
493 string i18n_enabler = ARDOUR::translation_enable_path();
496 int fd = ::open (i18n_enabler.c_str(), O_RDONLY|O_CREAT, 0644);
504 return unlink (i18n_enabler.c_str()) == 0;
509 ARDOUR::get_available_sync_options ()
511 vector<SyncSource> ret;
513 ret.push_back (JACK);
515 ret.push_back (MIDIClock);