some LV2 debug tracing
[ardour.git] / libs / ardour / globals.cc
1 /*
2     Copyright (C) 2000 Paul Davis
3
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.
8
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.
13
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.
17 */
18
19 #ifdef WAF_BUILD
20 #include "libardour-config.h"
21 #endif
22
23 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <sys/resource.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <errno.h>
31
32 #ifdef VST_SUPPORT
33 #include <fst.h>
34 #endif
35
36 #ifdef HAVE_AUDIOUNITS
37 #include "ardour/audio_unit.h"
38 #endif
39
40 #ifdef __SSE__
41 #include <xmmintrin.h>
42 #endif
43
44 #include <glibmm/fileutils.h>
45 #include <glibmm/miscutils.h>
46
47 #include <lrdf.h>
48
49 #include "pbd/error.h"
50 #include "pbd/id.h"
51 #include "pbd/strsplit.h"
52 #include "pbd/fpu.h"
53 #include "pbd/file_utils.h"
54 #include "pbd/enumwriter.h"
55
56 #include "midi++/port.h"
57 #include "midi++/manager.h"
58 #include "midi++/mmc.h"
59
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"
85
86 #include "audiographer/routines.h"
87
88 #if defined (__APPLE__)
89        #include <Carbon/Carbon.h> // For Gestalt
90 #endif
91
92 #include "i18n.h"
93
94 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
95 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
96 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
97
98 using namespace ARDOUR;
99 using namespace std;
100 using namespace PBD;
101
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;
107
108 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
109
110 void ARDOUR::setup_enum_writer ();
111
112 /* this is useful for quite a few things that want to check
113    if any bounds-related property has changed
114 */
115 PBD::PropertyChange ARDOUR::bounds_change;
116
117 namespace ARDOUR { 
118         namespace Properties {
119
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. 
124
125                    Declared in ardour/audioregion.h ...
126                 */
127
128                 PBD::PropertyDescriptor<bool> fade_in;
129                 PBD::PropertyDescriptor<bool> fade_out;
130                 PBD::PropertyDescriptor<bool> envelope;
131         }
132 }
133
134 void
135 ARDOUR::make_property_quarks ()
136 {
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));
143 }
144
145 void
146 setup_hardware_optimization (bool try_optimization)
147 {
148         bool generic_mix_functions = true;
149
150         if (try_optimization) {
151
152                 FPU fpu;
153
154 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
155
156                 if (fpu.has_sse()) {
157
158                         info << "Using SSE optimized routines" << endmsg;
159
160                         // SSE SET
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;
166
167                         generic_mix_functions = false;
168
169                 }
170
171 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
172                 long sysVersion = 0;
173
174                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
175                         sysVersion = 0;
176
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;
183
184                         generic_mix_functions = false;
185
186                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
187                 }
188 #endif
189
190                 /* consider FPU denormal handling to be "h/w optimization" */
191
192                 setup_fpu ();
193         }
194
195         if (generic_mix_functions) {
196
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;
202
203                 info << "No H/W specific optimizations in use" << endmsg;
204         }
205         
206         AudioGrapher::Routines::override_compute_peak (compute_peak);
207         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
208 }
209
210 static void
211 lotsa_files_please ()
212 {
213         struct rlimit rl;
214
215         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
216
217                 rl.rlim_cur = rl.rlim_max;
218
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;
222                         } else {
223                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
224                         }
225                 } else {
226                         if (rl.rlim_cur == RLIM_INFINITY) {
227                                 info << _("Removed open file count limit. Excellent!") << endmsg;
228                         } else {
229                                 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
230                         }
231                 }
232         } else {
233                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
234         }
235 }
236
237 int
238 ARDOUR::init (bool use_vst, bool try_optimization)
239 {
240         if (!Glib::thread_supported()) {
241                 Glib::thread_init();
242         }
243
244         (void) bindtextdomain(PACKAGE, LOCALEDIR);
245
246         PBD::ID::init ();
247         SessionEvent::init_event_pool ();
248         
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 ();
257
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
261            property changes.
262         */
263
264         bounds_change.add (ARDOUR::Properties::start);
265         bounds_change.add (ARDOUR::Properties::position);
266         bounds_change.add (ARDOUR::Properties::length);
267
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)
270         */
271
272         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
273
274         setup_enum_writer ();
275
276         // allow ardour the absolute maximum number of open files
277         lotsa_files_please ();
278
279         lrdf_init();
280         Library = new AudioLibrary;
281
282         BootMessage (_("Loading configuration"));
283
284         Config = new RCConfiguration;
285
286         if (Config->load_state ()) {
287                 return -1;
288         }
289         
290         Config->set_use_vst (use_vst);
291
292         Profile = new RuntimeProfile;
293
294
295 #ifdef VST_SUPPORT
296         if (Config->get_use_vst() && fst_init (0)) {
297                 return -1;
298         }
299 #endif
300
301 #ifdef HAVE_AUDIOUNITS
302         AUPluginInfo::load_cached_info ();
303 #endif
304
305         /* Make VAMP look in our library ahead of anything else */
306
307         char *p = getenv ("VAMP_PATH");
308         string vamppath = VAMP_DIR;
309         if (p) {
310                 vamppath += ':';
311                 vamppath += p;
312         }
313         setenv ("VAMP_PATH", vamppath.c_str(), 1);
314
315
316         setup_hardware_optimization (try_optimization);
317
318         SourceFactory::init ();
319         Analyser::init ();
320
321         /* singleton - first object is "it" */
322         new PluginManager ();
323
324         ProcessThread::init ();
325         BufferManager::init (10); // XX should be num_processors_for_dsp
326
327         PannerManager::instance().discover_panners();
328
329         return 0;
330 }
331
332 void
333 ARDOUR::init_post_engine ()
334 {
335         /* the MIDI Manager is needed by the ControlProtocolManager */
336         MIDI::Manager::create (AudioEngine::instance()->jack());
337
338         ControlProtocolManager::instance().discover_control_protocols ();
339
340         XMLNode* node;
341         if ((node = Config->control_protocol_state()) != 0) {
342                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
343         }
344
345         MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
346 }
347
348 int
349 ARDOUR::cleanup ()
350 {
351         delete Library;
352         lrdf_cleanup ();
353         delete &ControlProtocolManager::instance();
354 #ifdef VST_SUPPORT
355         fst_exit ();
356 #endif
357         return 0;
358 }
359
360 string
361 ARDOUR::get_ardour_revision ()
362 {
363         return "$Rev$";
364 }
365
366 void
367 ARDOUR::find_bindings_files (map<string,string>& files)
368 {
369         vector<sys::path> found;
370         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
371
372         if (getenv ("ARDOUR_SAE")) {
373                 Glib::PatternSpec pattern("*SAE-*.bindings");
374                 find_matching_files_in_search_path (spath, pattern, found);
375         } else {
376                 Glib::PatternSpec pattern("*.bindings");
377                 find_matching_files_in_search_path (spath, pattern, found);
378         }
379
380         if (found.empty()) {
381                 return;
382         }
383
384         for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
385                 sys::path path = *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);
390         }
391 }
392
393 bool
394 ARDOUR::no_auto_connect()
395 {
396         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
397 }
398
399 void
400 ARDOUR::setup_fpu ()
401 {
402
403         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
404                 // valgrind doesn't understand this assembler stuff
405                 // September 10th, 2007
406                 return;
407         }
408
409 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
410
411         int MXCSR;
412         FPU fpu;
413
414         /* XXX use real code to determine if the processor supports
415            DenormalsAreZero and FlushToZero
416         */
417
418         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
419                 return;
420         }
421
422         MXCSR  = _mm_getcsr();
423
424         switch (Config->get_denormal_model()) {
425         case DenormalNone:
426                 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
427                 break;
428
429         case DenormalFTZ:
430                 if (fpu.has_flush_to_zero()) {
431                         MXCSR |= _MM_FLUSH_ZERO_ON;
432                 }
433                 break;
434
435         case DenormalDAZ:
436                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
437                 if (fpu.has_denormals_are_zero()) {
438                         MXCSR |= 0x8000;
439                 }
440                 break;
441
442         case DenormalFTZDAZ:
443                 if (fpu.has_flush_to_zero()) {
444                         if (fpu.has_denormals_are_zero()) {
445                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
446                         } else {
447                                 MXCSR |= _MM_FLUSH_ZERO_ON;
448                         }
449                 }
450                 break;
451         }
452
453         _mm_setcsr (MXCSR);
454
455 #endif
456 }
457
458 ARDOUR::OverlapType
459 ARDOUR::coverage (framepos_t sa, framepos_t ea,
460                   framepos_t sb, framepos_t eb)
461 {
462         /* OverlapType returned reflects how the second (B)
463            range overlaps the first (A).
464
465            The diagrams show various relative placements
466            of A and B for each OverlapType.
467
468            Notes:
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
473
474            XXX Logically, Internal should disallow end
475            point equality.
476         */
477
478         /*
479              |--------------------|   A
480                   |------|            B
481                 |-----------------|   B
482
483
484              "B is internal to A"
485
486         */
487
488         if ((sb > sa) && (eb <= ea)) {
489                 return OverlapInternal;
490         }
491
492         /*
493              |--------------------|   A
494            ----|                      B
495            -----------------------|   B
496            --|                        B
497
498              "B overlaps the start of A"
499
500         */
501
502         if ((eb >= sa) && (eb <= ea)) {
503                 return OverlapStart;
504         }
505         /*
506              |---------------------|  A
507                    |----------------- B
508              |----------------------- B
509                                    |- B
510
511             "B overlaps the end of A"
512
513         */
514         if ((sb > sa) && (sb <= ea)) {
515                 return OverlapEnd;
516         }
517         /*
518              |--------------------|     A
519            --------------------------  B
520              |-----------------------  B
521             ----------------------|    B
522              |--------------------|    B
523
524
525            "B overlaps all of A"
526         */
527         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
528                 return OverlapExternal;
529         }
530
531         return OverlapNone;
532 }
533
534 string
535 ARDOUR::translation_kill_path ()
536 {
537         return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
538 }
539
540 bool
541 ARDOUR::translations_are_disabled ()
542 {
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;
545 }