fix up file renaming code a little bit
[ArdourMidi.git] / libs / ardour / globals.cc
blobca2432eda77d60477e5a7a3784ea5b72fcea5a0c
1 /*
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 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
24 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <sys/resource.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
33 #ifdef VST_SUPPORT
34 #include <fst.h>
35 #endif
37 #ifdef HAVE_AUDIOUNITS
38 #include "ardour/audio_unit.h"
39 #endif
41 #ifdef __SSE__
42 #include <xmmintrin.h>
43 #endif
45 #include <glibmm/fileutils.h>
46 #include <glibmm/miscutils.h>
48 #include <lrdf.h>
50 #include "pbd/error.h"
51 #include "pbd/id.h"
52 #include "pbd/strsplit.h"
53 #include "pbd/fpu.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/buffer_manager.h"
68 #include "ardour/control_protocol_manager.h"
69 #include "ardour/debug.h"
70 #include "ardour/filesystem_paths.h"
71 #include "ardour/mix.h"
72 #include "ardour/playlist.h"
73 #include "ardour/plugin_manager.h"
74 #include "ardour/process_thread.h"
75 #include "ardour/profile.h"
76 #include "ardour/region.h"
77 #include "ardour/rc_configuration.h"
78 #include "ardour/route_group.h"
79 #include "ardour/runtime_functions.h"
80 #include "ardour/session.h"
81 #include "ardour/session_event.h"
82 #include "ardour/source_factory.h"
83 #include "ardour/utils.h"
85 #include "audiographer/routines.h"
87 #if defined (__APPLE__)
88 #include <Carbon/Carbon.h> // For Gestalt
89 #endif
91 #include "i18n.h"
93 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
94 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
95 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
97 using namespace ARDOUR;
98 using namespace std;
99 using namespace PBD;
101 compute_peak_t ARDOUR::compute_peak = 0;
102 find_peaks_t ARDOUR::find_peaks = 0;
103 apply_gain_to_buffer_t ARDOUR::apply_gain_to_buffer = 0;
104 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
105 mix_buffers_no_gain_t ARDOUR::mix_buffers_no_gain = 0;
107 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
109 void ARDOUR::setup_enum_writer ();
111 /* this is useful for quite a few things that want to check
112 if any bounds-related property has changed
114 PBD::PropertyChange ARDOUR::bounds_change;
116 namespace ARDOUR {
117 namespace Properties {
119 /* the envelope and fades are not scalar items and so
120 currently (2010/02) are not stored using Property.
121 However, these descriptors enable us to notify
122 about changes to them via PropertyChange.
124 Declared in ardour/audioregion.h ...
127 PBD::PropertyDescriptor<bool> fade_in;
128 PBD::PropertyDescriptor<bool> fade_out;
129 PBD::PropertyDescriptor<bool> envelope;
133 void
134 ARDOUR::make_property_quarks ()
136 Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
137 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n", Properties::fade_in.property_id));
138 Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
139 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n", Properties::fade_out.property_id));
140 Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
141 DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n", Properties::envelope.property_id));
144 void
145 setup_hardware_optimization (bool try_optimization)
147 bool generic_mix_functions = true;
149 if (try_optimization) {
151 FPU fpu;
153 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
155 if (fpu.has_sse()) {
157 info << "Using SSE optimized routines" << endmsg;
159 // SSE SET
160 compute_peak = x86_sse_compute_peak;
161 find_peaks = x86_sse_find_peaks;
162 apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
163 mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
164 mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
166 generic_mix_functions = false;
170 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
171 long sysVersion = 0;
173 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
174 sysVersion = 0;
176 if (sysVersion >= 0x00001040) { // Tiger at least
177 compute_peak = veclib_compute_peak;
178 find_peaks = veclib_find_peaks;
179 apply_gain_to_buffer = veclib_apply_gain_to_buffer;
180 mix_buffers_with_gain = veclib_mix_buffers_with_gain;
181 mix_buffers_no_gain = veclib_mix_buffers_no_gain;
183 generic_mix_functions = false;
185 info << "Apple VecLib H/W specific optimizations in use" << endmsg;
187 #endif
189 /* consider FPU denormal handling to be "h/w optimization" */
191 setup_fpu ();
194 if (generic_mix_functions) {
196 compute_peak = default_compute_peak;
197 find_peaks = default_find_peaks;
198 apply_gain_to_buffer = default_apply_gain_to_buffer;
199 mix_buffers_with_gain = default_mix_buffers_with_gain;
200 mix_buffers_no_gain = default_mix_buffers_no_gain;
202 info << "No H/W specific optimizations in use" << endmsg;
205 AudioGrapher::Routines::override_compute_peak (compute_peak);
206 AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
209 static void
210 lotsa_files_please ()
212 struct rlimit rl;
214 if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
216 rl.rlim_cur = rl.rlim_max;
218 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
219 if (rl.rlim_cur == RLIM_INFINITY) {
220 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
221 } else {
222 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
224 } else {
225 if (rl.rlim_cur == RLIM_INFINITY) {
226 info << _("Removed open file count limit. Excellent!") << endmsg;
227 } else {
228 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
231 } else {
232 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
237 ARDOUR::init (bool use_vst, bool try_optimization)
239 if (!Glib::thread_supported()) {
240 Glib::thread_init();
243 (void) bindtextdomain(PACKAGE, LOCALEDIR);
245 PBD::ID::init ();
246 SessionEvent::init_event_pool ();
248 make_property_quarks ();
249 SessionObject::make_property_quarks ();
250 Region::make_property_quarks ();
251 AudioRegion::make_property_quarks ();
252 RouteGroup::make_property_quarks ();
253 Playlist::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
258 property changes.
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 ();
276 lrdf_init();
277 Library = new AudioLibrary;
279 BootMessage (_("Loading configuration"));
281 Config = new RCConfiguration;
283 if (Config->load_state ()) {
284 return -1;
287 Config->set_use_vst (use_vst);
289 Profile = new RuntimeProfile;
292 #ifdef VST_SUPPORT
293 if (Config->get_use_vst() && fst_init (0)) {
294 return -1;
296 #endif
298 #ifdef HAVE_AUDIOUNITS
299 AUPluginInfo::load_cached_info ();
300 #endif
302 /* Make VAMP look in our library ahead of anything else */
304 char *p = getenv ("VAMP_PATH");
305 string vamppath = VAMP_DIR;
306 if (p) {
307 vamppath += ':';
308 vamppath += p;
310 setenv ("VAMP_PATH", vamppath.c_str(), 1);
313 setup_hardware_optimization (try_optimization);
315 SourceFactory::init ();
316 Analyser::init ();
318 /* singleton - first object is "it" */
319 new PluginManager ();
321 ProcessThread::init ();
322 BufferManager::init (10); // XX should be num_processors_for_dsp
324 return 0;
327 void
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 ();
335 XMLNode* node;
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 ());
344 ARDOUR::cleanup ()
346 delete Library;
347 lrdf_cleanup ();
348 delete &ControlProtocolManager::instance();
349 #ifdef VST_SUPPORT
350 fst_exit ();
351 #endif
352 return 0;
355 string
356 ARDOUR::get_ardour_revision ()
358 return "$Rev$";
361 void
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);
370 } else {
371 Glib::PatternSpec pattern("*.bindings");
372 find_matching_files_in_search_path (spath, pattern, found);
375 if (found.empty()) {
376 return;
379 for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
380 sys::path path = *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);
388 bool
389 ARDOUR::no_auto_connect()
391 return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
394 void
395 ARDOUR::setup_fpu ()
398 if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
399 // valgrind doesn't understand this assembler stuff
400 // September 10th, 2007
401 return;
404 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
406 int MXCSR;
407 FPU fpu;
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()) {
414 return;
417 MXCSR = _mm_getcsr();
419 switch (Config->get_denormal_model()) {
420 case DenormalNone:
421 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
422 break;
424 case DenormalFTZ:
425 if (fpu.has_flush_to_zero()) {
426 MXCSR |= _MM_FLUSH_ZERO_ON;
428 break;
430 case DenormalDAZ:
431 MXCSR &= ~_MM_FLUSH_ZERO_ON;
432 if (fpu.has_denormals_are_zero()) {
433 MXCSR |= 0x8000;
435 break;
437 case DenormalFTZDAZ:
438 if (fpu.has_flush_to_zero()) {
439 if (fpu.has_denormals_are_zero()) {
440 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
441 } else {
442 MXCSR |= _MM_FLUSH_ZERO_ON;
445 break;
448 _mm_setcsr (MXCSR);
450 #endif
453 ARDOUR::OverlapType
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.
463 Notes:
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
470 point equality.
474 |--------------------| A
475 |------| B
476 |-----------------| B
479 "B is internal to A"
483 if ((sb > sa) && (eb <= ea)) {
484 return OverlapInternal;
488 |--------------------| A
489 ----| B
490 -----------------------| B
491 --| B
493 "B overlaps the start of A"
497 if ((eb >= sa) && (eb <= ea)) {
498 return OverlapStart;
501 |---------------------| A
502 |----------------- B
503 |----------------------- B
504 |- B
506 "B overlaps the end of A"
509 if ((sb > sa) && (sb <= ea)) {
510 return OverlapEnd;
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;
526 return OverlapNone;