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>
36 #ifdef HAVE_AUDIOUNITS
37 #include "ardour/audio_unit.h"
41 #include <xmmintrin.h>
44 #include <glibmm/fileutils.h>
45 #include <glibmm/miscutils.h>
49 #include "pbd/error.h"
51 #include "pbd/strsplit.h"
53 #include "pbd/file_utils.h"
54 #include "pbd/enumwriter.h"
56 #include "midi++/port.h"
57 #include "midi++/manager.h"
58 #include "midi++/mmc.h"
60 #include "ardour/analyser.h"
61 #include "ardour/ardour.h"
62 #include "ardour/audio_library.h"
63 #include "ardour/audioengine.h"
64 #include "ardour/audioregion.h"
65 #include "ardour/audiosource.h"
66 #include "ardour/buffer_manager.h"
67 #include "ardour/control_protocol_manager.h"
68 #include "ardour/debug.h"
69 #include "ardour/filesystem_paths.h"
70 #include "ardour/midi_region.h"
71 #include "ardour/mix.h"
72 #include "ardour/audioplaylist.h"
73 #include "ardour/panner_manager.h"
74 #include "ardour/plugin_manager.h"
75 #include "ardour/process_thread.h"
76 #include "ardour/profile.h"
77 #include "ardour/region.h"
78 #include "ardour/rc_configuration.h"
79 #include "ardour/route_group.h"
80 #include "ardour/runtime_functions.h"
81 #include "ardour/session.h"
82 #include "ardour/session_event.h"
83 #include "ardour/source_factory.h"
84 #include "ardour/utils.h"
86 #include "audiographer/routines.h"
88 #if defined (__APPLE__)
89 #include <Carbon/Carbon.h> // For Gestalt
94 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
95 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
96 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
98 using namespace ARDOUR;
102 compute_peak_t ARDOUR::compute_peak = 0;
103 find_peaks_t ARDOUR::find_peaks = 0;
104 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
105 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
106 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
108 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
110 void ARDOUR::setup_enum_writer ();
112 /* this is useful for quite a few things that want to check
113 if any bounds-related property has changed
115 PBD::PropertyChange ARDOUR::bounds_change;
118 namespace Properties {
120 /* the envelope and fades are not scalar items and so
121 currently (2010/02) are not stored using Property.
122 However, these descriptors enable us to notify
123 about changes to them via PropertyChange.
125 Declared in ardour/audioregion.h ...
128 PBD::PropertyDescriptor<bool> fade_in;
129 PBD::PropertyDescriptor<bool> fade_out;
130 PBD::PropertyDescriptor<bool> envelope;
135 ARDOUR::make_property_quarks ()
137 Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
138 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in.property_id));
139 Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
140 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out.property_id));
141 Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
142 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id));
146 setup_hardware_optimization (bool try_optimization)
148 bool generic_mix_functions = true;
150 if (try_optimization) {
154 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
158 info << "Using SSE optimized routines" << endmsg;
161 compute_peak = x86_sse_compute_peak;
162 find_peaks = x86_sse_find_peaks;
163 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
164 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
165 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
167 generic_mix_functions = false;
171 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
174 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
177 if (sysVersion >= 0x00001040) { // Tiger at least
178 compute_peak = veclib_compute_peak;
179 find_peaks = veclib_find_peaks;
180 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
181 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
182 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
184 generic_mix_functions = false;
186 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
190 /* consider FPU denormal handling to be "h/w optimization" */
195 if (generic_mix_functions) {
197 compute_peak = default_compute_peak;
198 find_peaks = default_find_peaks;
199 apply_gain_to_buffer = default_apply_gain_to_buffer;
200 mix_buffers_with_gain = default_mix_buffers_with_gain;
201 mix_buffers_no_gain = default_mix_buffers_no_gain;
203 info << "No H/W specific optimizations in use" << endmsg;
206 AudioGrapher::Routines::override_compute_peak (compute_peak);
207 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
211 lotsa_files_please ()
215 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
217 rl.rlim_cur = rl.rlim_max;
219 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
220 if (rl.rlim_cur == RLIM_INFINITY) {
221 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
223 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
226 if (rl.rlim_cur == RLIM_INFINITY) {
227 info << _("Removed open file count limit. Excellent!") << endmsg;
229 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
233 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
238 ARDOUR::init (bool use_vst, bool try_optimization)
240 if (!Glib::thread_supported()) {
244 (void) bindtextdomain(PACKAGE, LOCALEDIR);
247 SessionEvent::init_event_pool ();
249 make_property_quarks ();
250 SessionObject::make_property_quarks ();
251 Region::make_property_quarks ();
252 MidiRegion::make_property_quarks ();
253 AudioRegion::make_property_quarks ();
254 RouteGroup::make_property_quarks ();
255 Playlist::make_property_quarks ();
256 AudioPlaylist::make_property_quarks ();
258 /* this is a useful ready to use PropertyChange that many
259 things need to check. This avoids having to compose
260 it every time we want to check for any of the relevant
264 bounds_change.add (ARDOUR::Properties::start);
265 bounds_change.add (ARDOUR::Properties::position);
266 bounds_change.add (ARDOUR::Properties::length);
268 /* provide a state version for the few cases that need it and are not
269 driven by reading state from disk (e.g. undo/redo)
272 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
274 setup_enum_writer ();
276 // allow ardour the absolute maximum number of open files
277 lotsa_files_please ();
280 Library = new AudioLibrary;
282 BootMessage (_("Loading configuration"));
284 Config = new RCConfiguration;
286 if (Config->load_state ()) {
290 Config->set_use_vst (use_vst);
292 Profile = new RuntimeProfile;
296 if (Config->get_use_vst() && fst_init (0)) {
301 #ifdef HAVE_AUDIOUNITS
302 AUPluginInfo::load_cached_info ();
305 /* Make VAMP look in our library ahead of anything else */
307 char *p = getenv ("VAMP_PATH");
308 string vamppath = VAMP_DIR;
313 setenv ("VAMP_PATH", vamppath.c_str(), 1);
316 setup_hardware_optimization (try_optimization);
318 SourceFactory::init ();
321 /* singleton - first object is "it" */
322 new PluginManager ();
324 ProcessThread::init ();
325 BufferManager::init (10); // XX should be num_processors_for_dsp
327 PannerManager::instance().discover_panners();
333 ARDOUR::init_post_engine ()
335 /* the MIDI Manager is needed by the ControlProtocolManager */
336 MIDI::Manager::create (AudioEngine::instance()->jack());
338 ControlProtocolManager::instance().discover_control_protocols ();
341 if ((node = Config->control_protocol_state()) != 0) {
342 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
345 MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
353 delete &ControlProtocolManager::instance();
361 ARDOUR::get_ardour_revision ()
367 ARDOUR::find_bindings_files (map<string,string>& files)
369 vector<sys::path> found;
370 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
372 if (getenv ("ARDOUR_SAE")) {
373 Glib::PatternSpec pattern("*SAE-*.bindings");
374 find_matching_files_in_search_path (spath, pattern, found);
376 Glib::PatternSpec pattern("*.bindings");
377 find_matching_files_in_search_path (spath, pattern, found);
384 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
386 pair<string,string> namepath;
387 namepath.second = path.to_string();
388 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
389 files.insert (namepath);
394 ARDOUR::no_auto_connect()
396 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
403 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
404 // valgrind doesn't understand this assembler stuff
405 // September 10th, 2007
409 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
414 /* XXX use real code to determine if the processor supports
415 DenormalsAreZero and FlushToZero
418 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
422 MXCSR = _mm_getcsr();
424 switch (Config->get_denormal_model()) {
426 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
430 if (fpu.has_flush_to_zero()) {
431 MXCSR |= _MM_FLUSH_ZERO_ON;
436 MXCSR &= ~_MM_FLUSH_ZERO_ON;
437 if (fpu.has_denormals_are_zero()) {
443 if (fpu.has_flush_to_zero()) {
444 if (fpu.has_denormals_are_zero()) {
445 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
447 MXCSR |= _MM_FLUSH_ZERO_ON;
459 ARDOUR::coverage (framepos_t sa, framepos_t ea,
460 framepos_t sb, framepos_t eb)
462 /* OverlapType returned reflects how the second (B)
463 range overlaps the first (A).
465 The diagrams show various relative placements
466 of A and B for each OverlapType.
469 Internal: the start points cannot coincide
470 External: the start and end points can coincide
471 Start: end points can coincide
472 End: start points can coincide
474 XXX Logically, Internal should disallow end
479 |--------------------| A
481 |-----------------| B
488 if ((sb > sa) && (eb <= ea)) {
489 return OverlapInternal;
493 |--------------------| A
495 -----------------------| B
498 "B overlaps the start of A"
502 if ((eb >= sa) && (eb <= ea)) {
506 |---------------------| A
508 |----------------------- B
511 "B overlaps the end of A"
514 if ((sb > sa) && (sb <= ea)) {
518 |--------------------| A
519 -------------------------- B
520 |----------------------- B
521 ----------------------| B
522 |--------------------| B
525 "B overlaps all of A"
527 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
528 return OverlapExternal;
535 ARDOUR::translation_kill_path ()
537 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
541 ARDOUR::translations_are_disabled ()
543 /* if file does not exist, we don't translate (bundled ardour only) */
544 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;