clean up debugging
[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/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"
84
85 #include "audiographer/routines.h"
86
87 #if defined (__APPLE__)
88        #include <Carbon/Carbon.h> // For Gestalt
89 #endif
90
91 #include "i18n.h"
92
93 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
94 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
95 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
96
97 using namespace ARDOUR;
98 using namespace std;
99 using namespace PBD;
100
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;
106
107 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
108
109 void ARDOUR::setup_enum_writer ();
110
111 /* this is useful for quite a few things that want to check
112    if any bounds-related property has changed
113 */
114 PBD::PropertyChange ARDOUR::bounds_change;
115
116 namespace ARDOUR { 
117         namespace Properties {
118
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. 
123
124                    Declared in ardour/audioregion.h ...
125                 */
126
127                 PBD::PropertyDescriptor<bool> fade_in;
128                 PBD::PropertyDescriptor<bool> fade_out;
129                 PBD::PropertyDescriptor<bool> envelope;
130         }
131 }
132
133 void
134 ARDOUR::make_property_quarks ()
135 {
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));
142 }
143
144 void
145 setup_hardware_optimization (bool try_optimization)
146 {
147         bool generic_mix_functions = true;
148
149         if (try_optimization) {
150
151                 FPU fpu;
152
153 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
154
155                 if (fpu.has_sse()) {
156
157                         info << "Using SSE optimized routines" << endmsg;
158
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;
165
166                         generic_mix_functions = false;
167
168                 }
169
170 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
171                 long sysVersion = 0;
172
173                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
174                         sysVersion = 0;
175
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;
182
183                         generic_mix_functions = false;
184
185                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
186                 }
187 #endif
188
189                 /* consider FPU denormal handling to be "h/w optimization" */
190
191                 setup_fpu ();
192         }
193
194         if (generic_mix_functions) {
195
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;
201
202                 info << "No H/W specific optimizations in use" << endmsg;
203         }
204         
205         AudioGrapher::Routines::override_compute_peak (compute_peak);
206         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
207 }
208
209 static void
210 lotsa_files_please ()
211 {
212         struct rlimit rl;
213
214         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
215
216                 rl.rlim_cur = rl.rlim_max;
217
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;
223                         }
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;
229                         }
230                 }
231         } else {
232                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
233         }
234 }
235
236 int
237 ARDOUR::init (bool use_vst, bool try_optimization)
238 {
239         if (!Glib::thread_supported()) {
240                 Glib::thread_init();
241         }
242
243         (void) bindtextdomain(PACKAGE, LOCALEDIR);
244
245         PBD::ID::init ();
246         SessionEvent::init_event_pool ();
247         
248         make_property_quarks ();
249         SessionObject::make_property_quarks ();
250         Region::make_property_quarks ();
251         MidiRegion::make_property_quarks ();
252         AudioRegion::make_property_quarks ();
253         RouteGroup::make_property_quarks ();
254         Playlist::make_property_quarks ();
255         AudioPlaylist::make_property_quarks ();
256
257         /* this is a useful ready to use PropertyChange that many
258            things need to check. This avoids having to compose
259            it every time we want to check for any of the relevant
260            property changes.
261         */
262
263         bounds_change.add (ARDOUR::Properties::start);
264         bounds_change.add (ARDOUR::Properties::position);
265         bounds_change.add (ARDOUR::Properties::length);
266
267         /* provide a state version for the few cases that need it and are not
268            driven by reading state from disk (e.g. undo/redo)
269         */
270
271         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
272
273         setup_enum_writer ();
274
275         // allow ardour the absolute maximum number of open files
276         lotsa_files_please ();
277
278         lrdf_init();
279         Library = new AudioLibrary;
280
281         BootMessage (_("Loading configuration"));
282
283         Config = new RCConfiguration;
284
285         if (Config->load_state ()) {
286                 return -1;
287         }
288         
289         Config->set_use_vst (use_vst);
290
291         Profile = new RuntimeProfile;
292
293
294 #ifdef VST_SUPPORT
295         if (Config->get_use_vst() && fst_init (0)) {
296                 return -1;
297         }
298 #endif
299
300 #ifdef HAVE_AUDIOUNITS
301         AUPluginInfo::load_cached_info ();
302 #endif
303
304         /* Make VAMP look in our library ahead of anything else */
305
306         char *p = getenv ("VAMP_PATH");
307         string vamppath = VAMP_DIR;
308         if (p) {
309                 vamppath += ':';
310                 vamppath += p;
311         }
312         setenv ("VAMP_PATH", vamppath.c_str(), 1);
313
314
315         setup_hardware_optimization (try_optimization);
316
317         SourceFactory::init ();
318         Analyser::init ();
319
320         /* singleton - first object is "it" */
321         new PluginManager ();
322
323         ProcessThread::init ();
324         BufferManager::init (10); // XX should be num_processors_for_dsp
325
326         return 0;
327 }
328
329 void
330 ARDOUR::init_post_engine ()
331 {
332         /* the MIDI Manager is needed by the ControlProtocolManager */
333         MIDI::Manager::create (AudioEngine::instance()->jack());
334
335         ControlProtocolManager::instance().discover_control_protocols ();
336
337         XMLNode* node;
338         if ((node = Config->control_protocol_state()) != 0) {
339                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
340         }
341
342         MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
343 }
344
345 int
346 ARDOUR::cleanup ()
347 {
348         delete Library;
349         lrdf_cleanup ();
350         delete &ControlProtocolManager::instance();
351 #ifdef VST_SUPPORT
352         fst_exit ();
353 #endif
354         return 0;
355 }
356
357 string
358 ARDOUR::get_ardour_revision ()
359 {
360         return "$Rev$";
361 }
362
363 void
364 ARDOUR::find_bindings_files (map<string,string>& files)
365 {
366         vector<sys::path> found;
367         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
368
369         if (getenv ("ARDOUR_SAE")) {
370                 Glib::PatternSpec pattern("*SAE-*.bindings");
371                 find_matching_files_in_search_path (spath, pattern, found);
372         } else {
373                 Glib::PatternSpec pattern("*.bindings");
374                 find_matching_files_in_search_path (spath, pattern, found);
375         }
376
377         if (found.empty()) {
378                 return;
379         }
380
381         for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
382                 sys::path path = *x;
383                 pair<string,string> namepath;
384                 namepath.second = path.to_string();
385                 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
386                 files.insert (namepath);
387         }
388 }
389
390 bool
391 ARDOUR::no_auto_connect()
392 {
393         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
394 }
395
396 void
397 ARDOUR::setup_fpu ()
398 {
399
400         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
401                 // valgrind doesn't understand this assembler stuff
402                 // September 10th, 2007
403                 return;
404         }
405
406 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
407
408         int MXCSR;
409         FPU fpu;
410
411         /* XXX use real code to determine if the processor supports
412            DenormalsAreZero and FlushToZero
413         */
414
415         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
416                 return;
417         }
418
419         MXCSR  = _mm_getcsr();
420
421         switch (Config->get_denormal_model()) {
422         case DenormalNone:
423                 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
424                 break;
425
426         case DenormalFTZ:
427                 if (fpu.has_flush_to_zero()) {
428                         MXCSR |= _MM_FLUSH_ZERO_ON;
429                 }
430                 break;
431
432         case DenormalDAZ:
433                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
434                 if (fpu.has_denormals_are_zero()) {
435                         MXCSR |= 0x8000;
436                 }
437                 break;
438
439         case DenormalFTZDAZ:
440                 if (fpu.has_flush_to_zero()) {
441                         if (fpu.has_denormals_are_zero()) {
442                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
443                         } else {
444                                 MXCSR |= _MM_FLUSH_ZERO_ON;
445                         }
446                 }
447                 break;
448         }
449
450         _mm_setcsr (MXCSR);
451
452 #endif
453 }
454
455 ARDOUR::OverlapType
456 ARDOUR::coverage (framepos_t sa, framepos_t ea,
457                   framepos_t sb, framepos_t eb)
458 {
459         /* OverlapType returned reflects how the second (B)
460            range overlaps the first (A).
461
462            The diagrams show various relative placements
463            of A and B for each OverlapType.
464
465            Notes:
466               Internal: the start points cannot coincide
467               External: the start and end points can coincide
468               Start: end points can coincide
469               End: start points can coincide
470
471            XXX Logically, Internal should disallow end
472            point equality.
473         */
474
475         /*
476              |--------------------|   A
477                   |------|            B
478                 |-----------------|   B
479
480
481              "B is internal to A"
482
483         */
484
485         if ((sb > sa) && (eb <= ea)) {
486                 return OverlapInternal;
487         }
488
489         /*
490              |--------------------|   A
491            ----|                      B
492            -----------------------|   B
493            --|                        B
494
495              "B overlaps the start of A"
496
497         */
498
499         if ((eb >= sa) && (eb <= ea)) {
500                 return OverlapStart;
501         }
502         /*
503              |---------------------|  A
504                    |----------------- B
505              |----------------------- B
506                                    |- B
507
508             "B overlaps the end of A"
509
510         */
511         if ((sb > sa) && (sb <= ea)) {
512                 return OverlapEnd;
513         }
514         /*
515              |--------------------|     A
516            --------------------------  B
517              |-----------------------  B
518             ----------------------|    B
519              |--------------------|    B
520
521
522            "B overlaps all of A"
523         */
524         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
525                 return OverlapExternal;
526         }
527
528         return OverlapNone;
529 }
530
531 string
532 ARDOUR::translation_kill_path ()
533 {
534         return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
535 }
536
537 bool
538 ARDOUR::translations_are_disabled ()
539 {
540         /* if file does not exist, we don't translate (bundled ardour only) */
541         return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;
542 }