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 char *p = getenv ("VAMP_PATH");
323 string vamppath = VAMP_DIR;
328 setenv ("VAMP_PATH", vamppath.c_str(), 1);
331 setup_hardware_optimization (try_optimization);
333 SourceFactory::init ();
336 /* singleton - first object is "it" */
337 (void) PluginManager::instance();
339 ProcessThread::init ();
340 BufferManager::init (10); // XX should be num_processors_for_dsp + 1 for the GUI thread
342 PannerManager::instance().discover_panners();
344 // Initialize parameter metadata
345 EventTypeMap::instance().new_parameter(NullAutomation);
346 EventTypeMap::instance().new_parameter(GainAutomation);
347 EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
348 EventTypeMap::instance().new_parameter(PanElevationAutomation);
349 EventTypeMap::instance().new_parameter(PanWidthAutomation);
350 EventTypeMap::instance().new_parameter(PluginAutomation);
351 EventTypeMap::instance().new_parameter(SoloAutomation);
352 EventTypeMap::instance().new_parameter(MuteAutomation);
353 EventTypeMap::instance().new_parameter(MidiCCAutomation);
354 EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
355 EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
356 EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
357 EventTypeMap::instance().new_parameter(FadeInAutomation);
358 EventTypeMap::instance().new_parameter(FadeOutAutomation);
359 EventTypeMap::instance().new_parameter(EnvelopeAutomation);
360 EventTypeMap::instance().new_parameter(MidiCCAutomation);
366 ARDOUR::init_post_engine ()
368 /* the MIDI Manager is needed by the ControlProtocolManager */
369 MIDI::Manager::create (AudioEngine::instance()->jack());
371 ControlProtocolManager::instance().discover_control_protocols ();
374 if ((node = Config->control_protocol_state()) != 0) {
375 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
380 ARDOUR::PluginManager::instance().refresh ();
388 delete &ControlProtocolManager::instance();
389 #ifdef WINDOWS_VST_SUPPORT
400 ARDOUR::find_bindings_files (map<string,string>& files)
402 vector<sys::path> found;
403 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
405 if (getenv ("ARDOUR_SAE")) {
406 Glib::PatternSpec pattern("*SAE-*.bindings");
407 find_matching_files_in_search_path (spath, pattern, found);
409 Glib::PatternSpec pattern("*.bindings");
410 find_matching_files_in_search_path (spath, pattern, found);
417 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
419 pair<string,string> namepath;
420 namepath.second = path.to_string();
421 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
422 files.insert (namepath);
427 ARDOUR::no_auto_connect()
429 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
436 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
437 // valgrind doesn't understand this assembler stuff
438 // September 10th, 2007
442 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
447 /* XXX use real code to determine if the processor supports
448 DenormalsAreZero and FlushToZero
451 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
455 MXCSR = _mm_getcsr();
457 #ifdef DEBUG_DENORMAL_EXCEPTION
458 /* This will raise a FP exception if a denormal is detected */
459 MXCSR &= ~_MM_MASK_DENORM;
462 switch (Config->get_denormal_model()) {
464 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
468 if (fpu.has_flush_to_zero()) {
469 MXCSR |= _MM_FLUSH_ZERO_ON;
474 MXCSR &= ~_MM_FLUSH_ZERO_ON;
475 if (fpu.has_denormals_are_zero()) {
481 if (fpu.has_flush_to_zero()) {
482 if (fpu.has_denormals_are_zero()) {
483 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
485 MXCSR |= _MM_FLUSH_ZERO_ON;
497 ARDOUR::coverage (framepos_t sa, framepos_t ea,
498 framepos_t sb, framepos_t eb)
500 /* OverlapType returned reflects how the second (B)
501 range overlaps the first (A).
503 The diagrams show various relative placements
504 of A and B for each OverlapType.
507 Internal: the start points cannot coincide
508 External: the start and end points can coincide
509 Start: end points can coincide
510 End: start points can coincide
512 XXX Logically, Internal should disallow end
517 |--------------------| A
519 |-----------------| B
526 if ((sb > sa) && (eb <= ea)) {
527 return OverlapInternal;
531 |--------------------| A
533 -----------------------| B
536 "B overlaps the start of A"
540 if ((eb >= sa) && (eb <= ea)) {
544 |---------------------| A
546 |----------------------- B
549 "B overlaps the end of A"
552 if ((sb > sa) && (sb <= ea)) {
556 |--------------------| A
557 -------------------------- B
558 |----------------------- B
559 ----------------------| B
560 |--------------------| B
563 "B overlaps all of A"
565 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
566 return OverlapExternal;
573 ARDOUR::translation_kill_path ()
575 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
579 ARDOUR::translations_are_disabled ()
581 /* if file does not exist, we don't translate (bundled ardour only) */
582 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;