fix misspelt #ifdef
[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 WINDOWS_VST_SUPPORT
33 #include <fst.h>
34 #endif
35
36 #ifdef LXVST_SUPPORT
37 #include "ardour/linux_vst_support.h"
38 #endif
39
40 #ifdef AUDIOUNIT_SUPPORT
41 #include "ardour/audio_unit.h"
42 #endif
43
44 #ifdef __SSE__
45 #include <xmmintrin.h>
46 #endif
47
48 #include <glibmm/fileutils.h>
49 #include <glibmm/miscutils.h>
50
51 #include <lrdf.h>
52
53 #include "pbd/error.h"
54 #include "pbd/id.h"
55 #include "pbd/strsplit.h"
56 #include "pbd/fpu.h"
57 #include "pbd/file_utils.h"
58 #include "pbd/enumwriter.h"
59
60 #include "midi++/port.h"
61 #include "midi++/manager.h"
62 #include "midi++/mmc.h"
63
64 #include "ardour/analyser.h"
65 #include "ardour/ardour.h"
66 #include "ardour/audio_library.h"
67 #include "ardour/audioengine.h"
68 #include "ardour/audioregion.h"
69 #include "ardour/audiosource.h"
70 #include "ardour/buffer_manager.h"
71 #include "ardour/control_protocol_manager.h"
72 #include "ardour/dB.h"
73 #include "ardour/debug.h"
74 #include "ardour/filesystem_paths.h"
75 #include "ardour/midi_region.h"
76 #include "ardour/mix.h"
77 #include "ardour/audioplaylist.h"
78 #include "ardour/panner_manager.h"
79 #include "ardour/plugin_manager.h"
80 #include "ardour/process_thread.h"
81 #include "ardour/profile.h"
82 #include "ardour/region.h"
83 #include "ardour/rc_configuration.h"
84 #include "ardour/route_group.h"
85 #include "ardour/runtime_functions.h"
86 #include "ardour/session.h"
87 #include "ardour/session_event.h"
88 #include "ardour/source_factory.h"
89 #include "ardour/utils.h"
90
91 #include "audiographer/routines.h"
92
93 #if defined (__APPLE__)
94        #include <Carbon/Carbon.h> // For Gestalt
95 #endif
96
97 #include "i18n.h"
98
99 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
100 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
101 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
102
103 using namespace ARDOUR;
104 using namespace std;
105 using namespace PBD;
106
107 compute_peak_t          ARDOUR::compute_peak = 0;
108 find_peaks_t            ARDOUR::find_peaks = 0;
109 apply_gain_to_buffer_t  ARDOUR::apply_gain_to_buffer = 0;
110 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
111 mix_buffers_no_gain_t   ARDOUR::mix_buffers_no_gain = 0;
112
113 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
114
115 void ARDOUR::setup_enum_writer ();
116
117 /* this is useful for quite a few things that want to check
118    if any bounds-related property has changed
119 */
120 PBD::PropertyChange ARDOUR::bounds_change;
121
122 namespace ARDOUR {
123         namespace Properties {
124
125                 /* the envelope and fades are not scalar items and so
126                    currently (2010/02) are not stored using Property.
127                    However, these descriptors enable us to notify
128                    about changes to them via PropertyChange.
129
130                    Declared in ardour/audioregion.h ...
131                 */
132
133                 PBD::PropertyDescriptor<bool> fade_in;
134                 PBD::PropertyDescriptor<bool> fade_out;
135                 PBD::PropertyDescriptor<bool> envelope;
136         }
137 }
138
139 void
140 ARDOUR::make_property_quarks ()
141 {
142         Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
143         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n",        Properties::fade_in.property_id));
144         Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
145         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n",       Properties::fade_out.property_id));
146         Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
147         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n",       Properties::envelope.property_id));
148 }
149
150 void
151 setup_hardware_optimization (bool try_optimization)
152 {
153         bool generic_mix_functions = true;
154
155         if (try_optimization) {
156
157                 FPU fpu;
158
159 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
160
161                 if (fpu.has_sse()) {
162
163                         info << "Using SSE optimized routines" << endmsg;
164
165                         // SSE SET
166                         compute_peak          = x86_sse_compute_peak;
167                         find_peaks            = x86_sse_find_peaks;
168                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
169                         // mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
170                         mix_buffers_with_gain = default_mix_buffers_with_gain;
171                         mix_buffers_no_gain   = x86_sse_mix_buffers_no_gain;
172
173                         generic_mix_functions = false;
174
175                 }
176
177 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
178                 SInt32 sysVersion = 0;
179
180                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
181                         sysVersion = 0;
182
183                 if (sysVersion >= 0x00001040) { // Tiger at least
184                         compute_peak           = veclib_compute_peak;
185                         find_peaks             = veclib_find_peaks;
186                         apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
187                         mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
188                         mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
189
190                         generic_mix_functions = false;
191
192                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
193                 }
194 #endif
195
196                 /* consider FPU denormal handling to be "h/w optimization" */
197
198                 setup_fpu ();
199         }
200
201         if (generic_mix_functions) {
202
203                 compute_peak          = default_compute_peak;
204                 find_peaks            = default_find_peaks;
205                 apply_gain_to_buffer  = default_apply_gain_to_buffer;
206                 mix_buffers_with_gain = default_mix_buffers_with_gain;
207                 mix_buffers_no_gain   = default_mix_buffers_no_gain;
208
209                 info << "No H/W specific optimizations in use" << endmsg;
210         }
211
212         AudioGrapher::Routines::override_compute_peak (compute_peak);
213         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
214 }
215
216 static void
217 lotsa_files_please ()
218 {
219         struct rlimit rl;
220
221         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
222
223                 rl.rlim_cur = rl.rlim_max;
224
225                 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
226                         if (rl.rlim_cur == RLIM_INFINITY) {
227                                 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
228                         } else {
229                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
230                         }
231                 } else {
232                         if (rl.rlim_cur == RLIM_INFINITY) {
233                                 info << _("Removed open file count limit. Excellent!") << endmsg;
234                         } else {
235                                 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
236                         }
237                 }
238         } else {
239                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
240         }
241 }
242
243 int
244 ARDOUR::init (bool use_windows_vst, bool try_optimization)
245 {
246         if (!Glib::thread_supported()) {
247                 Glib::thread_init();
248         }
249
250         (void) bindtextdomain(PACKAGE, LOCALEDIR);
251
252         PBD::ID::init ();
253         SessionEvent::init_event_pool ();
254
255         make_property_quarks ();
256         SessionObject::make_property_quarks ();
257         Region::make_property_quarks ();
258         MidiRegion::make_property_quarks ();
259         AudioRegion::make_property_quarks ();
260         RouteGroup::make_property_quarks ();
261         Playlist::make_property_quarks ();
262         AudioPlaylist::make_property_quarks ();
263
264         /* this is a useful ready to use PropertyChange that many
265            things need to check. This avoids having to compose
266            it every time we want to check for any of the relevant
267            property changes.
268         */
269
270         bounds_change.add (ARDOUR::Properties::start);
271         bounds_change.add (ARDOUR::Properties::position);
272         bounds_change.add (ARDOUR::Properties::length);
273
274         /* provide a state version for the few cases that need it and are not
275            driven by reading state from disk (e.g. undo/redo)
276         */
277
278         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
279
280         setup_enum_writer ();
281
282         // allow ardour the absolute maximum number of open files
283         lotsa_files_please ();
284
285         lrdf_init();
286         Library = new AudioLibrary;
287
288         BootMessage (_("Loading configuration"));
289
290         Config = new RCConfiguration;
291
292         if (Config->load_state ()) {
293                 return -1;
294         }
295
296         Config->set_use_windows_vst (use_windows_vst);
297 #ifdef LXVST_SUPPORT
298         Config->set_use_lxvst(true);
299 #endif
300
301         Profile = new RuntimeProfile;
302
303
304 #ifdef WINDOWS_VST_SUPPORT
305         if (Config->get_use_windows_vst() && fst_init (0)) {
306                 return -1;
307         }
308 #endif
309
310 #ifdef LXVST_SUPPORT
311         if (Config->get_use_lxvst() && vstfx_init (0)) {
312                 return -1;
313         }
314 #endif
315
316 #ifdef AUDIOUNIT_SUPPORT
317         AUPluginInfo::load_cached_info ();
318 #endif
319
320         /* Make VAMP look in our library ahead of anything else */
321
322         char *p = getenv ("VAMP_PATH");
323         string vamppath = VAMP_DIR;
324         if (p) {
325                 vamppath += ':';
326                 vamppath += p;
327         }
328         setenv ("VAMP_PATH", vamppath.c_str(), 1);
329
330
331         setup_hardware_optimization (try_optimization);
332
333         SourceFactory::init ();
334         Analyser::init ();
335
336         /* singleton - first object is "it" */
337         (void) PluginManager::instance();
338
339         ProcessThread::init ();
340         BufferManager::init (10); // XX should be num_processors_for_dsp + 1 for the GUI thread
341
342         PannerManager::instance().discover_panners();
343
344         // Initialize parameter metadata
345         EventTypeMap::instance().new_parameter(NullAutomation);
346         EventTypeMap::instance().new_parameter(GainAutomation);
347         EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
348         EventTypeMap::instance().new_parameter(PanElevationAutomation);
349         EventTypeMap::instance().new_parameter(PanWidthAutomation);
350         EventTypeMap::instance().new_parameter(PluginAutomation);
351         EventTypeMap::instance().new_parameter(SoloAutomation);
352         EventTypeMap::instance().new_parameter(MuteAutomation);
353         EventTypeMap::instance().new_parameter(MidiCCAutomation);
354         EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
355         EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
356         EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
357         EventTypeMap::instance().new_parameter(FadeInAutomation);
358         EventTypeMap::instance().new_parameter(FadeOutAutomation);
359         EventTypeMap::instance().new_parameter(EnvelopeAutomation);
360         EventTypeMap::instance().new_parameter(MidiCCAutomation);
361
362         return 0;
363 }
364
365 void
366 ARDOUR::init_post_engine ()
367 {
368         /* the MIDI Manager is needed by the ControlProtocolManager */
369         MIDI::Manager::create (AudioEngine::instance()->jack());
370
371         ControlProtocolManager::instance().discover_control_protocols ();
372
373         XMLNode* node;
374         if ((node = Config->control_protocol_state()) != 0) {
375                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
376         }
377
378         /* find plugins */
379
380         ARDOUR::PluginManager::instance().refresh ();
381 }
382
383 int
384 ARDOUR::cleanup ()
385 {
386         delete Library;
387         lrdf_cleanup ();
388         delete &ControlProtocolManager::instance();
389 #ifdef WINDOWS_VST_SUPPORT
390         fst_exit ();
391 #endif
392
393 #ifdef LXVST_SUPPORT
394         vstfx_exit();
395 #endif
396         return 0;
397 }
398
399 void
400 ARDOUR::find_bindings_files (map<string,string>& files)
401 {
402         vector<sys::path> found;
403         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
404
405         if (getenv ("ARDOUR_SAE")) {
406                 Glib::PatternSpec pattern("*SAE-*.bindings");
407                 find_matching_files_in_search_path (spath, pattern, found);
408         } else {
409                 Glib::PatternSpec pattern("*.bindings");
410                 find_matching_files_in_search_path (spath, pattern, found);
411         }
412
413         if (found.empty()) {
414                 return;
415         }
416
417         for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
418                 sys::path path = *x;
419                 pair<string,string> namepath;
420                 namepath.second = path.to_string();
421                 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
422                 files.insert (namepath);
423         }
424 }
425
426 bool
427 ARDOUR::no_auto_connect()
428 {
429         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
430 }
431
432 void
433 ARDOUR::setup_fpu ()
434 {
435
436         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
437                 // valgrind doesn't understand this assembler stuff
438                 // September 10th, 2007
439                 return;
440         }
441
442 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
443
444         int MXCSR;
445         FPU fpu;
446
447         /* XXX use real code to determine if the processor supports
448            DenormalsAreZero and FlushToZero
449         */
450
451         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
452                 return;
453         }
454
455         MXCSR  = _mm_getcsr();
456
457 #ifdef DEBUG_DENORMAL_EXCEPTION
458         /* This will raise a FP exception if a denormal is detected */
459         MXCSR &= ~_MM_MASK_DENORM;
460 #endif  
461
462         switch (Config->get_denormal_model()) {
463         case DenormalNone:
464                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
465                 break;
466
467         case DenormalFTZ:
468                 if (fpu.has_flush_to_zero()) {
469                         MXCSR |= _MM_FLUSH_ZERO_ON;
470                 }
471                 break;
472
473         case DenormalDAZ:
474                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
475                 if (fpu.has_denormals_are_zero()) {
476                         MXCSR |= 0x40;
477                 }
478                 break;
479
480         case DenormalFTZDAZ:
481                 if (fpu.has_flush_to_zero()) {
482                         if (fpu.has_denormals_are_zero()) {
483                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
484                         } else {
485                                 MXCSR |= _MM_FLUSH_ZERO_ON;
486                         }
487                 }
488                 break;
489         }
490
491         _mm_setcsr (MXCSR);
492
493 #endif
494 }
495
496 ARDOUR::OverlapType
497 ARDOUR::coverage (framepos_t sa, framepos_t ea,
498                   framepos_t sb, framepos_t eb)
499 {
500         /* OverlapType returned reflects how the second (B)
501            range overlaps the first (A).
502
503            The diagrams show various relative placements
504            of A and B for each OverlapType.
505
506            Notes:
507               Internal: the start points cannot coincide
508               External: the start and end points can coincide
509               Start: end points can coincide
510               End: start points can coincide
511
512            XXX Logically, Internal should disallow end
513            point equality.
514         */
515
516         /*
517              |--------------------|   A
518                   |------|            B
519                 |-----------------|   B
520
521
522              "B is internal to A"
523
524         */
525
526         if ((sb > sa) && (eb <= ea)) {
527                 return OverlapInternal;
528         }
529
530         /*
531              |--------------------|   A
532            ----|                      B
533            -----------------------|   B
534            --|                        B
535
536              "B overlaps the start of A"
537
538         */
539
540         if ((eb >= sa) && (eb <= ea)) {
541                 return OverlapStart;
542         }
543         /*
544              |---------------------|  A
545                    |----------------- B
546              |----------------------- B
547                                    |- B
548
549             "B overlaps the end of A"
550
551         */
552         if ((sb > sa) && (sb <= ea)) {
553                 return OverlapEnd;
554         }
555         /*
556              |--------------------|     A
557            --------------------------  B
558              |-----------------------  B
559             ----------------------|    B
560              |--------------------|    B
561
562
563            "B overlaps all of A"
564         */
565         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
566                 return OverlapExternal;
567         }
568
569         return OverlapNone;
570 }
571
572 string
573 ARDOUR::translation_kill_path ()
574 {
575         return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
576 }
577
578 bool
579 ARDOUR::translations_are_disabled ()
580 {
581         /* if file does not exist, we don't translate (bundled ardour only) */
582         return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;
583 }