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.
21 #include "libardour-config.h"
24 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
26 #include <sys/types.h>
28 #include <sys/resource.h>
37 #ifdef HAVE_AUDIOUNITS
38 #include "ardour/audio_unit.h"
42 #include <xmmintrin.h>
45 #include <glibmm/fileutils.h>
46 #include <glibmm/miscutils.h>
50 #include "pbd/error.h"
52 #include "pbd/strsplit.h"
54 #include "pbd/file_utils.h"
55 #include "pbd/enumwriter.h"
57 #include "midi++/port.h"
58 #include "midi++/manager.h"
59 #include "midi++/mmc.h"
61 #include "ardour/analyser.h"
62 #include "ardour/ardour.h"
63 #include "ardour/audio_library.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/audioregion.h"
66 #include "ardour/audiosource.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/playlist.h"
72 #include "ardour/plugin_manager.h"
73 #include "ardour/profile.h"
74 #include "ardour/region.h"
75 #include "ardour/rc_configuration.h"
76 #include "ardour/route_group.h"
77 #include "ardour/runtime_functions.h"
78 #include "ardour/session.h"
79 #include "ardour/session_event.h"
80 #include "ardour/source_factory.h"
81 #include "ardour/utils.h"
83 #include "audiographer/routines.h"
85 #if defined (__APPLE__)
86 #include <Carbon/Carbon.h> // For Gestalt
91 ARDOUR::RCConfiguration
* ARDOUR::Config
= 0;
92 ARDOUR::RuntimeProfile
* ARDOUR::Profile
= 0;
93 ARDOUR::AudioLibrary
* ARDOUR::Library
= 0;
95 using namespace ARDOUR
;
99 MIDI::Port
*ARDOUR::default_mmc_port
= 0;
100 MIDI::Port
*ARDOUR::default_mtc_port
= 0;
101 MIDI::Port
*ARDOUR::default_midi_port
= 0;
102 MIDI::Port
*ARDOUR::default_midi_clock_port
= 0;
104 compute_peak_t
ARDOUR::compute_peak
= 0;
105 find_peaks_t
ARDOUR::find_peaks
= 0;
106 apply_gain_to_buffer_t
ARDOUR::apply_gain_to_buffer
= 0;
107 mix_buffers_with_gain_t
ARDOUR::mix_buffers_with_gain
= 0;
108 mix_buffers_no_gain_t
ARDOUR::mix_buffers_no_gain
= 0;
110 PBD::Signal1
<void,std::string
> ARDOUR::BootMessage
;
112 void ARDOUR::setup_enum_writer ();
114 /* this is useful for quite a few things that want to check
115 if any bounds-related property has changed
117 PBD::PropertyChange
ARDOUR::bounds_change
;
120 namespace Properties
{
122 /* the envelope and fades are not scalar items and so
123 currently (2010/02) are not stored using Property.
124 However, these descriptors enable us to notify
125 about changes to them via PropertyChange.
127 Declared in ardour/audioregion.h ...
130 PBD::PropertyDescriptor
<bool> fade_in
;
131 PBD::PropertyDescriptor
<bool> fade_out
;
132 PBD::PropertyDescriptor
<bool> envelope
;
137 ARDOUR::make_property_quarks ()
139 Properties::fade_in
.property_id
= g_quark_from_static_string (X_("fade_in_FAKE"));
140 DEBUG_TRACE (DEBUG::Properties
, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in
.property_id
));
141 Properties::fade_out
.property_id
= g_quark_from_static_string (X_("fade_out_FAKE"));
142 DEBUG_TRACE (DEBUG::Properties
, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out
.property_id
));
143 Properties::envelope
.property_id
= g_quark_from_static_string (X_("envelope_FAKE"));
144 DEBUG_TRACE (DEBUG::Properties
, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope
.property_id
));
148 ARDOUR::setup_midi ()
150 if (Config
->midi_ports
.size() == 0) {
154 BootMessage (_("Configuring MIDI ports"));
156 for (std::map
<string
,XMLNode
>::iterator i
= Config
->midi_ports
.begin(); i
!= Config
->midi_ports
.end(); ++i
) {
157 MIDI::Manager::instance()->add_port (i
->second
);
161 const MIDI::Manager::PortList
& ports
= MIDI::Manager::instance()->get_midi_ports();
163 if (ports
.size() > 1) {
165 first
= ports
.front();
167 /* More than one port, so try using specific names for each port */
169 default_mmc_port
= MIDI::Manager::instance()->port (Config
->get_mmc_port_name());
170 default_mtc_port
= MIDI::Manager::instance()->port (Config
->get_mtc_port_name());
171 default_midi_port
= MIDI::Manager::instance()->port (Config
->get_midi_port_name());
172 default_midi_clock_port
= MIDI::Manager::instance()->port (Config
->get_midi_clock_port_name());
174 /* If that didn't work, just use the first listed port */
176 if (default_mmc_port
== 0) {
177 default_mmc_port
= first
;
180 if (default_mtc_port
== 0) {
181 default_mtc_port
= first
;
184 if (default_midi_port
== 0) {
185 default_midi_port
= first
;
188 if (default_midi_clock_port
== 0) {
189 default_midi_clock_port
= first
;
192 } else if (ports
.size() == 1) {
194 first
= ports
.front();
196 /* Only one port described, so use it for both MTC and MMC */
198 default_mmc_port
= first
;
199 default_mtc_port
= default_mmc_port
;
200 default_midi_port
= default_mmc_port
;
201 default_midi_clock_port
= default_mmc_port
;
204 if (default_mmc_port
== 0) {
205 warning
<< string_compose (_("No MMC control (MIDI port \"%1\" not available)"), Config
->get_mmc_port_name())
210 if (default_mtc_port
== 0) {
211 warning
<< string_compose (_("No MTC support (MIDI port \"%1\" not available)"), Config
->get_mtc_port_name())
215 if (default_midi_port
== 0) {
216 warning
<< string_compose (_("No MIDI parameter support (MIDI port \"%1\" not available)"), Config
->get_midi_port_name())
220 if (default_midi_clock_port
== 0) {
221 warning
<< string_compose (_("No MIDI Clock support (MIDI port \"%1\" not available)"), Config
->get_midi_clock_port_name())
229 setup_hardware_optimization (bool try_optimization
)
231 bool generic_mix_functions
= true;
233 if (try_optimization
) {
237 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
241 info
<< "Using SSE optimized routines" << endmsg
;
244 compute_peak
= x86_sse_compute_peak
;
245 find_peaks
= x86_sse_find_peaks
;
246 apply_gain_to_buffer
= x86_sse_apply_gain_to_buffer
;
247 mix_buffers_with_gain
= x86_sse_mix_buffers_with_gain
;
248 mix_buffers_no_gain
= x86_sse_mix_buffers_no_gain
;
250 generic_mix_functions
= false;
254 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
257 if (noErr
!= Gestalt(gestaltSystemVersion
, &sysVersion
))
260 if (sysVersion
>= 0x00001040) { // Tiger at least
261 compute_peak
= veclib_compute_peak
;
262 find_peaks
= veclib_find_peaks
;
263 apply_gain_to_buffer
= veclib_apply_gain_to_buffer
;
264 mix_buffers_with_gain
= veclib_mix_buffers_with_gain
;
265 mix_buffers_no_gain
= veclib_mix_buffers_no_gain
;
267 generic_mix_functions
= false;
269 info
<< "Apple VecLib H/W specific optimizations in use" << endmsg
;
273 /* consider FPU denormal handling to be "h/w optimization" */
278 if (generic_mix_functions
) {
280 compute_peak
= default_compute_peak
;
281 find_peaks
= default_find_peaks
;
282 apply_gain_to_buffer
= default_apply_gain_to_buffer
;
283 mix_buffers_with_gain
= default_mix_buffers_with_gain
;
284 mix_buffers_no_gain
= default_mix_buffers_no_gain
;
286 info
<< "No H/W specific optimizations in use" << endmsg
;
289 AudioGrapher::Routines::override_compute_peak (compute_peak
);
290 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer
);
294 lotsa_files_please ()
298 if (getrlimit (RLIMIT_NOFILE
, &rl
) == 0) {
300 rl
.rlim_cur
= rl
.rlim_max
;
302 if (setrlimit (RLIMIT_NOFILE
, &rl
) != 0) {
303 if (rl
.rlim_cur
== RLIM_INFINITY
) {
304 error
<< _("Could not set system open files limit to \"unlimited\"") << endmsg
;
306 error
<< string_compose (_("Could not set system open files limit to %1"), rl
.rlim_cur
) << endmsg
;
309 if (rl
.rlim_cur
== RLIM_INFINITY
) {
310 info
<< _("Removed open file count limit. Excellent!") << endmsg
;
312 info
<< string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME
, rl
.rlim_cur
) << endmsg
;
316 error
<< string_compose (_("Could not get system open files limit (%1)"), strerror (errno
)) << endmsg
;
321 ARDOUR::init (bool use_vst
, bool try_optimization
)
323 if (!Glib::thread_supported()) {
327 (void) bindtextdomain(PACKAGE
, LOCALEDIR
);
330 SessionEvent::init_event_pool ();
332 make_property_quarks ();
333 SessionObject::make_property_quarks ();
334 Region::make_property_quarks ();
335 AudioRegion::make_property_quarks ();
336 RouteGroup::make_property_quarks ();
337 Playlist::make_property_quarks ();
339 /* this is a useful ready to use PropertyChange that many
340 things need to check. This avoids having to compose
341 it every time we want to check for any of the relevant
345 bounds_change
.add (ARDOUR::Properties::start
);
346 bounds_change
.add (ARDOUR::Properties::position
);
347 bounds_change
.add (ARDOUR::Properties::length
);
349 /* provide a state version for the few cases that need it and are not
350 driven by reading state from disk (e.g. undo/redo)
353 Stateful::current_state_version
= CURRENT_SESSION_FILE_VERSION
;
355 setup_enum_writer ();
357 // allow ardour the absolute maximum number of open files
358 lotsa_files_please ();
361 Library
= new AudioLibrary
;
363 BootMessage (_("Loading configuration"));
365 Config
= new RCConfiguration
;
367 if (Config
->load_state ()) {
372 Config
->set_use_vst (use_vst
);
374 cerr
<< "After config loaded, MTC port name = " << Config
->get_mtc_port_name() << endl
;
376 Profile
= new RuntimeProfile
;
380 if (Config
->get_use_vst() && fst_init (0)) {
385 #ifdef HAVE_AUDIOUNITS
386 AUPluginInfo::load_cached_info ();
389 /* Make VAMP look in our library ahead of anything else */
391 char *p
= getenv ("VAMP_PATH");
392 string vamppath
= VAMP_DIR
;
397 setenv ("VAMP_PATH", vamppath
.c_str(), 1);
400 setup_hardware_optimization (try_optimization
);
402 SourceFactory::init ();
405 /* singleton - first object is "it" */
406 new PluginManager ();
412 ARDOUR::init_post_engine ()
414 ControlProtocolManager::instance().discover_control_protocols ();
417 if ((node
= Config
->control_protocol_state()) != 0) {
418 ControlProtocolManager::instance().set_state (*node
, Stateful::loading_state_version
);
427 delete &ControlProtocolManager::instance();
435 ARDOUR::get_ardour_revision ()
441 ARDOUR::find_bindings_files (map
<string
,string
>& files
)
443 vector
<sys::path
> found
;
444 SearchPath spath
= ardour_search_path() + user_config_directory() + system_config_search_path();
446 if (getenv ("ARDOUR_SAE")) {
447 Glib::PatternSpec
pattern("*SAE-*.bindings");
448 find_matching_files_in_search_path (spath
, pattern
, found
);
450 Glib::PatternSpec
pattern("*.bindings");
451 find_matching_files_in_search_path (spath
, pattern
, found
);
458 for (vector
<sys::path
>::iterator x
= found
.begin(); x
!= found
.end(); ++x
) {
460 pair
<string
,string
> namepath
;
461 namepath
.second
= path
.to_string();
462 namepath
.first
= path
.leaf().substr (0, path
.leaf().find_first_of ('.'));
463 files
.insert (namepath
);
468 ARDOUR::no_auto_connect()
470 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
477 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
478 // valgrind doesn't understand this assembler stuff
479 // September 10th, 2007
483 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
488 /* XXX use real code to determine if the processor supports
489 DenormalsAreZero and FlushToZero
492 if (!fpu
.has_flush_to_zero() && !fpu
.has_denormals_are_zero()) {
496 MXCSR
= _mm_getcsr();
498 switch (Config
->get_denormal_model()) {
500 MXCSR
&= ~(_MM_FLUSH_ZERO_ON
|0x8000);
504 if (fpu
.has_flush_to_zero()) {
505 MXCSR
|= _MM_FLUSH_ZERO_ON
;
510 MXCSR
&= ~_MM_FLUSH_ZERO_ON
;
511 if (fpu
.has_denormals_are_zero()) {
517 if (fpu
.has_flush_to_zero()) {
518 if (fpu
.has_denormals_are_zero()) {
519 MXCSR
|= _MM_FLUSH_ZERO_ON
| 0x8000;
521 MXCSR
|= _MM_FLUSH_ZERO_ON
;
533 ARDOUR::coverage (nframes_t sa
, nframes_t ea
,
534 nframes_t sb
, nframes_t eb
)
536 /* OverlapType returned reflects how the second (B)
537 range overlaps the first (A).
539 The diagrams show various relative placements
540 of A and B for each OverlapType.
543 Internal: the start points cannot coincide
544 External: the start and end points can coincide
545 Start: end points can coincide
546 End: start points can coincide
548 XXX Logically, Internal should disallow end
553 |--------------------| A
555 |-----------------| B
562 if ((sb
>= sa
) && (eb
<= ea
)) {
564 if ((sb
> sa
) && (eb
<= ea
)) {
566 return OverlapInternal
;
570 |--------------------| A
572 -----------------------| B
575 "B overlaps the start of A"
579 if ((eb
>= sa
) && (eb
<= ea
)) {
583 |---------------------| A
585 |----------------------- B
588 "B overlaps the end of A"
591 if ((sb
> sa
) && (sb
<= ea
)) {
595 |--------------------| A
596 -------------------------- B
597 |----------------------- B
598 ----------------------| B
599 |--------------------| B
602 "B overlaps all of A"
604 if ((sa
>= sb
) && (sa
<= eb
) && (ea
<= eb
)) {
605 return OverlapExternal
;