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>
48 #include <glibmm/fileutils.h>
49 #include <glibmm/miscutils.h>
53 #include "pbd/error.h"
55 #include "pbd/strsplit.h"
57 #include "pbd/file_utils.h"
58 #include "pbd/enumwriter.h"
60 #include "midi++/port.h"
61 #include "midi++/manager.h"
62 #include "midi++/mmc.h"
64 #include "ardour/analyser.h"
65 #include "ardour/ardour.h"
66 #include "ardour/audio_library.h"
67 #include "ardour/audioengine.h"
68 #include "ardour/audioregion.h"
69 #include "ardour/audiosource.h"
70 #include "ardour/buffer_manager.h"
71 #include "ardour/control_protocol_manager.h"
72 #include "ardour/dB.h"
73 #include "ardour/debug.h"
74 #include "ardour/filesystem_paths.h"
75 #include "ardour/midi_region.h"
76 #include "ardour/mix.h"
77 #include "ardour/audioplaylist.h"
78 #include "ardour/panner_manager.h"
79 #include "ardour/plugin_manager.h"
80 #include "ardour/process_thread.h"
81 #include "ardour/profile.h"
82 #include "ardour/region.h"
83 #include "ardour/rc_configuration.h"
84 #include "ardour/route_group.h"
85 #include "ardour/runtime_functions.h"
86 #include "ardour/session.h"
87 #include "ardour/session_event.h"
88 #include "ardour/source_factory.h"
89 #include "ardour/utils.h"
91 #include "audiographer/routines.h"
93 #if defined (__APPLE__)
94 #include <Carbon/Carbon.h> // For Gestalt
99 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
100 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
101 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
103 using namespace ARDOUR;
107 compute_peak_t ARDOUR::compute_peak = 0;
108 find_peaks_t ARDOUR::find_peaks = 0;
109 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
110 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
111 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
113 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
115 void ARDOUR::setup_enum_writer ();
117 /* this is useful for quite a few things that want to check
118 if any bounds-related property has changed
120 PBD::PropertyChange ARDOUR::bounds_change;
123 namespace Properties {
125 /* the envelope and fades are not scalar items and so
126 currently (2010/02) are not stored using Property.
127 However, these descriptors enable us to notify
128 about changes to them via PropertyChange.
130 Declared in ardour/audioregion.h ...
133 PBD::PropertyDescriptor<bool> fade_in;
134 PBD::PropertyDescriptor<bool> fade_out;
135 PBD::PropertyDescriptor<bool> envelope;
140 ARDOUR::make_property_quarks ()
142 Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
143 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in.property_id));
144 Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
145 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out.property_id));
146 Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
147 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id));
151 setup_hardware_optimization (bool try_optimization)
153 bool generic_mix_functions = true;
155 if (try_optimization) {
159 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
163 info << "Using SSE optimized routines" << endmsg;
166 compute_peak = x86_sse_compute_peak;
167 find_peaks = x86_sse_find_peaks;
168 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
169 // mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
170 mix_buffers_with_gain = default_mix_buffers_with_gain;
171 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
173 generic_mix_functions = false;
177 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
178 SInt32 sysVersion = 0;
180 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
183 if (sysVersion >= 0x00001040) { // Tiger at least
184 compute_peak = veclib_compute_peak;
185 find_peaks = veclib_find_peaks;
186 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
187 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
188 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
190 generic_mix_functions = false;
192 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
196 /* consider FPU denormal handling to be "h/w optimization" */
201 if (generic_mix_functions) {
203 compute_peak = default_compute_peak;
204 find_peaks = default_find_peaks;
205 apply_gain_to_buffer = default_apply_gain_to_buffer;
206 mix_buffers_with_gain = default_mix_buffers_with_gain;
207 mix_buffers_no_gain = default_mix_buffers_no_gain;
209 info << "No H/W specific optimizations in use" << endmsg;
212 AudioGrapher::Routines::override_compute_peak (compute_peak);
213 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
217 lotsa_files_please ()
221 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
223 rl.rlim_cur = rl.rlim_max;
225 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
226 if (rl.rlim_cur == RLIM_INFINITY) {
227 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
229 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
232 if (rl.rlim_cur == RLIM_INFINITY) {
233 info << _("Removed open file count limit. Excellent!") << endmsg;
235 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
239 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
244 ARDOUR::init (bool use_windows_vst, bool try_optimization)
246 if (!Glib::thread_supported()) {
250 (void) bindtextdomain(PACKAGE, LOCALEDIR);
253 SessionEvent::init_event_pool ();
255 make_property_quarks ();
256 SessionObject::make_property_quarks ();
257 Region::make_property_quarks ();
258 MidiRegion::make_property_quarks ();
259 AudioRegion::make_property_quarks ();
260 RouteGroup::make_property_quarks ();
261 Playlist::make_property_quarks ();
262 AudioPlaylist::make_property_quarks ();
264 /* this is a useful ready to use PropertyChange that many
265 things need to check. This avoids having to compose
266 it every time we want to check for any of the relevant
270 bounds_change.add (ARDOUR::Properties::start);
271 bounds_change.add (ARDOUR::Properties::position);
272 bounds_change.add (ARDOUR::Properties::length);
274 /* provide a state version for the few cases that need it and are not
275 driven by reading state from disk (e.g. undo/redo)
278 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
280 setup_enum_writer ();
282 // allow ardour the absolute maximum number of open files
283 lotsa_files_please ();
286 Library = new AudioLibrary;
288 BootMessage (_("Loading configuration"));
290 Config = new RCConfiguration;
292 if (Config->load_state ()) {
296 Config->set_use_windows_vst (use_windows_vst);
298 Config->set_use_lxvst(true);
301 Profile = new RuntimeProfile;
304 #ifdef WINDOWS_VST_SUPPORT
305 if (Config->get_use_windows_vst() && fst_init (0)) {
311 if (Config->get_use_lxvst() && vstfx_init (0)) {
316 #ifdef AUDIOUNIT_SUPPORT
317 AUPluginInfo::load_cached_info ();
320 /* Make VAMP look in our library ahead of anything else */
322 SearchPath sp (ardour_dll_directory());
323 sp.add_subdirectory_to_paths ("vamp");
324 setenv ("VAMP_PATH", sp.to_string().c_str(), 1);
326 setup_hardware_optimization (try_optimization);
328 SourceFactory::init ();
331 /* singleton - first object is "it" */
332 (void) PluginManager::instance();
334 ProcessThread::init ();
335 BufferManager::init (10); // XX should be num_processors_for_dsp + 1 for the GUI thread
337 PannerManager::instance().discover_panners();
339 // Initialize parameter metadata
340 EventTypeMap::instance().new_parameter(NullAutomation);
341 EventTypeMap::instance().new_parameter(GainAutomation);
342 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
343 EventTypeMap::instance().new_parameter(PanElevationAutomation);
344 EventTypeMap::instance().new_parameter(PanWidthAutomation);
345 EventTypeMap::instance().new_parameter(PluginAutomation);
346 EventTypeMap::instance().new_parameter(SoloAutomation);
347 EventTypeMap::instance().new_parameter(MuteAutomation);
348 EventTypeMap::instance().new_parameter(MidiCCAutomation);
349 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
350 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
351 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
352 EventTypeMap::instance().new_parameter(FadeInAutomation);
353 EventTypeMap::instance().new_parameter(FadeOutAutomation);
354 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
355 EventTypeMap::instance().new_parameter(MidiCCAutomation);
361 ARDOUR::init_post_engine ()
363 /* the MIDI Manager is needed by the ControlProtocolManager */
364 MIDI::Manager::create (AudioEngine::instance()->jack());
366 ControlProtocolManager::instance().discover_control_protocols ();
369 if ((node = Config->control_protocol_state()) != 0) {
370 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
375 ARDOUR::PluginManager::instance().refresh ();
383 delete &ControlProtocolManager::instance();
384 #ifdef WINDOWS_VST_SUPPORT
395 ARDOUR::find_bindings_files (map<string,string>& files)
397 vector<sys::path> found;
398 SearchPath spath = ardour_config_search_path();
400 if (getenv ("ARDOUR_SAE")) {
401 Glib::PatternSpec pattern("*SAE-*.bindings");
402 find_matching_files_in_search_path (spath, pattern, found);
404 Glib::PatternSpec pattern("*.bindings");
405 find_matching_files_in_search_path (spath, pattern, found);
412 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
414 pair<string,string> namepath;
415 namepath.second = path.to_string();
416 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
417 files.insert (namepath);
422 ARDOUR::no_auto_connect()
424 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
431 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
432 // valgrind doesn't understand this assembler stuff
433 // September 10th, 2007
437 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
442 /* XXX use real code to determine if the processor supports
443 DenormalsAreZero and FlushToZero
446 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
450 MXCSR = _mm_getcsr();
452 #ifdef DEBUG_DENORMAL_EXCEPTION
453 /* This will raise a FP exception if a denormal is detected */
454 MXCSR &= ~_MM_MASK_DENORM;
457 switch (Config->get_denormal_model()) {
459 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
463 if (fpu.has_flush_to_zero()) {
464 MXCSR |= _MM_FLUSH_ZERO_ON;
469 MXCSR &= ~_MM_FLUSH_ZERO_ON;
470 if (fpu.has_denormals_are_zero()) {
476 if (fpu.has_flush_to_zero()) {
477 if (fpu.has_denormals_are_zero()) {
478 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
480 MXCSR |= _MM_FLUSH_ZERO_ON;
492 ARDOUR::translation_kill_path ()
494 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
498 ARDOUR::translations_are_disabled ()
500 /* if file does not exist, we don't translate (bundled ardour only) */
501 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;