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/mix.h"
71 #include "ardour/audioplaylist.h"
72 #include "ardour/plugin_manager.h"
73 #include "ardour/process_thread.h"
74 #include "ardour/profile.h"
75 #include "ardour/region.h"
76 #include "ardour/rc_configuration.h"
77 #include "ardour/route_group.h"
78 #include "ardour/runtime_functions.h"
79 #include "ardour/session.h"
80 #include "ardour/session_event.h"
81 #include "ardour/source_factory.h"
82 #include "ardour/utils.h"
84 #include "audiographer/routines.h"
86 #if defined (__APPLE__)
87 #include <Carbon/Carbon.h> // For Gestalt
92 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
93 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
94 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
96 using namespace ARDOUR;
100 compute_peak_t ARDOUR::compute_peak = 0;
101 find_peaks_t ARDOUR::find_peaks = 0;
102 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
103 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
104 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
106 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
108 void ARDOUR::setup_enum_writer ();
110 /* this is useful for quite a few things that want to check
111 if any bounds-related property has changed
113 PBD::PropertyChange ARDOUR::bounds_change;
116 namespace Properties {
118 /* the envelope and fades are not scalar items and so
119 currently (2010/02) are not stored using Property.
120 However, these descriptors enable us to notify
121 about changes to them via PropertyChange.
123 Declared in ardour/audioregion.h ...
126 PBD::PropertyDescriptor<bool> fade_in;
127 PBD::PropertyDescriptor<bool> fade_out;
128 PBD::PropertyDescriptor<bool> envelope;
133 ARDOUR::make_property_quarks ()
135 Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
136 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in.property_id));
137 Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
138 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out.property_id));
139 Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
140 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id));
144 setup_hardware_optimization (bool try_optimization)
146 bool generic_mix_functions = true;
148 if (try_optimization) {
152 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
156 info << "Using SSE optimized routines" << endmsg;
159 compute_peak = x86_sse_compute_peak;
160 find_peaks = x86_sse_find_peaks;
161 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
162 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
163 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
165 generic_mix_functions = false;
169 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
172 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
175 if (sysVersion >= 0x00001040) { // Tiger at least
176 compute_peak = veclib_compute_peak;
177 find_peaks = veclib_find_peaks;
178 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
179 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
180 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
182 generic_mix_functions = false;
184 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
188 /* consider FPU denormal handling to be "h/w optimization" */
193 if (generic_mix_functions) {
195 compute_peak = default_compute_peak;
196 find_peaks = default_find_peaks;
197 apply_gain_to_buffer = default_apply_gain_to_buffer;
198 mix_buffers_with_gain = default_mix_buffers_with_gain;
199 mix_buffers_no_gain = default_mix_buffers_no_gain;
201 info << "No H/W specific optimizations in use" << endmsg;
204 AudioGrapher::Routines::override_compute_peak (compute_peak);
205 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
209 lotsa_files_please ()
213 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
215 rl.rlim_cur = rl.rlim_max;
217 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
218 if (rl.rlim_cur == RLIM_INFINITY) {
219 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
221 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
224 if (rl.rlim_cur == RLIM_INFINITY) {
225 info << _("Removed open file count limit. Excellent!") << endmsg;
227 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
231 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
236 ARDOUR::init (bool use_vst, bool try_optimization)
238 if (!Glib::thread_supported()) {
242 (void) bindtextdomain(PACKAGE, LOCALEDIR);
245 SessionEvent::init_event_pool ();
247 make_property_quarks ();
248 SessionObject::make_property_quarks ();
249 Region::make_property_quarks ();
250 AudioRegion::make_property_quarks ();
251 RouteGroup::make_property_quarks ();
252 Playlist::make_property_quarks ();
253 AudioPlaylist::make_property_quarks ();
255 /* this is a useful ready to use PropertyChange that many
256 things need to check. This avoids having to compose
257 it every time we want to check for any of the relevant
261 bounds_change.add (ARDOUR::Properties::start);
262 bounds_change.add (ARDOUR::Properties::position);
263 bounds_change.add (ARDOUR::Properties::length);
265 /* provide a state version for the few cases that need it and are not
266 driven by reading state from disk (e.g. undo/redo)
269 Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
271 setup_enum_writer ();
273 // allow ardour the absolute maximum number of open files
274 lotsa_files_please ();
277 Library = new AudioLibrary;
279 BootMessage (_("Loading configuration"));
281 Config = new RCConfiguration;
283 if (Config->load_state ()) {
287 Config->set_use_vst (use_vst);
289 Profile = new RuntimeProfile;
293 if (Config->get_use_vst() && fst_init (0)) {
298 #ifdef HAVE_AUDIOUNITS
299 AUPluginInfo::load_cached_info ();
302 /* Make VAMP look in our library ahead of anything else */
304 char *p = getenv ("VAMP_PATH");
305 string vamppath = VAMP_DIR;
310 setenv ("VAMP_PATH", vamppath.c_str(), 1);
313 setup_hardware_optimization (try_optimization);
315 SourceFactory::init ();
318 /* singleton - first object is "it" */
319 new PluginManager ();
321 ProcessThread::init ();
322 BufferManager::init (10); // XX should be num_processors_for_dsp
328 ARDOUR::init_post_engine ()
330 /* the MIDI Manager is needed by the ControlProtocolManager */
331 MIDI::Manager::create (AudioEngine::instance()->jack());
333 ControlProtocolManager::instance().discover_control_protocols ();
336 if ((node = Config->control_protocol_state()) != 0) {
337 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
340 MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
348 delete &ControlProtocolManager::instance();
356 ARDOUR::get_ardour_revision ()
362 ARDOUR::find_bindings_files (map<string,string>& files)
364 vector<sys::path> found;
365 SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
367 if (getenv ("ARDOUR_SAE")) {
368 Glib::PatternSpec pattern("*SAE-*.bindings");
369 find_matching_files_in_search_path (spath, pattern, found);
371 Glib::PatternSpec pattern("*.bindings");
372 find_matching_files_in_search_path (spath, pattern, found);
379 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
381 pair<string,string> namepath;
382 namepath.second = path.to_string();
383 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
384 files.insert (namepath);
389 ARDOUR::no_auto_connect()
391 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
398 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
399 // valgrind doesn't understand this assembler stuff
400 // September 10th, 2007
404 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
409 /* XXX use real code to determine if the processor supports
410 DenormalsAreZero and FlushToZero
413 if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
417 MXCSR = _mm_getcsr();
419 switch (Config->get_denormal_model()) {
421 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
425 if (fpu.has_flush_to_zero()) {
426 MXCSR |= _MM_FLUSH_ZERO_ON;
431 MXCSR &= ~_MM_FLUSH_ZERO_ON;
432 if (fpu.has_denormals_are_zero()) {
438 if (fpu.has_flush_to_zero()) {
439 if (fpu.has_denormals_are_zero()) {
440 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
442 MXCSR |= _MM_FLUSH_ZERO_ON;
454 ARDOUR::coverage (framepos_t sa, framepos_t ea,
455 framepos_t sb, framepos_t eb)
457 /* OverlapType returned reflects how the second (B)
458 range overlaps the first (A).
460 The diagrams show various relative placements
461 of A and B for each OverlapType.
464 Internal: the start points cannot coincide
465 External: the start and end points can coincide
466 Start: end points can coincide
467 End: start points can coincide
469 XXX Logically, Internal should disallow end
474 |--------------------| A
476 |-----------------| B
483 if ((sb > sa) && (eb <= ea)) {
484 return OverlapInternal;
488 |--------------------| A
490 -----------------------| B
493 "B overlaps the start of A"
497 if ((eb >= sa) && (eb <= ea)) {
501 |---------------------| A
503 |----------------------- B
506 "B overlaps the end of A"
509 if ((sb > sa) && (sb <= ea)) {
513 |--------------------| A
514 -------------------------- B
515 |----------------------- B
516 ----------------------| B
517 |--------------------| B
520 "B overlaps all of A"
522 if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
523 return OverlapExternal;
530 ARDOUR::translation_kill_path ()
532 return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
536 ARDOUR::translations_are_disabled ()
538 /* if file does not exist, we don't translate (bundled ardour only) */
539 return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;