7c713980c31898dd720260178e2d7d8aa91ac593
[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 LXVST_SUPPORT
37 #include "ardour/vstfx.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                 long 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_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_vst (use_vst);
297 #ifdef LXVST_SUPPORT
298         Config->set_use_lxvst(true);
299 #endif
300
301         Profile = new RuntimeProfile;
302
303
304 #ifdef VST_SUPPORT
305         if (Config->get_use_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         new PluginManager ();
338
339         ProcessThread::init ();
340         BufferManager::init (10); // XX should be num_processors_for_dsp
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
379 int
380 ARDOUR::cleanup ()
381 {
382         delete Library;
383         lrdf_cleanup ();
384         delete &ControlProtocolManager::instance();
385 #ifdef VST_SUPPORT
386         fst_exit ();
387 #endif
388
389 #ifdef LXVST_SUPPOR
390         vstfx_exit();
391 #endif
392         return 0;
393 }
394
395 void
396 ARDOUR::find_bindings_files (map<string,string>& files)
397 {
398         vector<sys::path> found;
399         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
400
401         if (getenv ("ARDOUR_SAE")) {
402                 Glib::PatternSpec pattern("*SAE-*.bindings");
403                 find_matching_files_in_search_path (spath, pattern, found);
404         } else {
405                 Glib::PatternSpec pattern("*.bindings");
406                 find_matching_files_in_search_path (spath, pattern, found);
407         }
408
409         if (found.empty()) {
410                 return;
411         }
412
413         for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
414                 sys::path path = *x;
415                 pair<string,string> namepath;
416                 namepath.second = path.to_string();
417                 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
418                 files.insert (namepath);
419         }
420 }
421
422 bool
423 ARDOUR::no_auto_connect()
424 {
425         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
426 }
427
428 void
429 ARDOUR::setup_fpu ()
430 {
431
432         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
433                 // valgrind doesn't understand this assembler stuff
434                 // September 10th, 2007
435                 return;
436         }
437
438 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
439
440         int MXCSR;
441         FPU fpu;
442
443         /* XXX use real code to determine if the processor supports
444            DenormalsAreZero and FlushToZero
445         */
446
447         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
448                 return;
449         }
450
451         MXCSR  = _mm_getcsr();
452
453         switch (Config->get_denormal_model()) {
454         case DenormalNone:
455                 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
456                 break;
457
458         case DenormalFTZ:
459                 if (fpu.has_flush_to_zero()) {
460                         MXCSR |= _MM_FLUSH_ZERO_ON;
461                 }
462                 break;
463
464         case DenormalDAZ:
465                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
466                 if (fpu.has_denormals_are_zero()) {
467                         MXCSR |= 0x8000;
468                 }
469                 break;
470
471         case DenormalFTZDAZ:
472                 if (fpu.has_flush_to_zero()) {
473                         if (fpu.has_denormals_are_zero()) {
474                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
475                         } else {
476                                 MXCSR |= _MM_FLUSH_ZERO_ON;
477                         }
478                 }
479                 break;
480         }
481
482         _mm_setcsr (MXCSR);
483
484 #endif
485 }
486
487 ARDOUR::OverlapType
488 ARDOUR::coverage (framepos_t sa, framepos_t ea,
489                   framepos_t sb, framepos_t eb)
490 {
491         /* OverlapType returned reflects how the second (B)
492            range overlaps the first (A).
493
494            The diagrams show various relative placements
495            of A and B for each OverlapType.
496
497            Notes:
498               Internal: the start points cannot coincide
499               External: the start and end points can coincide
500               Start: end points can coincide
501               End: start points can coincide
502
503            XXX Logically, Internal should disallow end
504            point equality.
505         */
506
507         /*
508              |--------------------|   A
509                   |------|            B
510                 |-----------------|   B
511
512
513              "B is internal to A"
514
515         */
516
517         if ((sb > sa) && (eb <= ea)) {
518                 return OverlapInternal;
519         }
520
521         /*
522              |--------------------|   A
523            ----|                      B
524            -----------------------|   B
525            --|                        B
526
527              "B overlaps the start of A"
528
529         */
530
531         if ((eb >= sa) && (eb <= ea)) {
532                 return OverlapStart;
533         }
534         /*
535              |---------------------|  A
536                    |----------------- B
537              |----------------------- B
538                                    |- B
539
540             "B overlaps the end of A"
541
542         */
543         if ((sb > sa) && (sb <= ea)) {
544                 return OverlapEnd;
545         }
546         /*
547              |--------------------|     A
548            --------------------------  B
549              |-----------------------  B
550             ----------------------|    B
551              |--------------------|    B
552
553
554            "B overlaps all of A"
555         */
556         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
557                 return OverlapExternal;
558         }
559
560         return OverlapNone;
561 }
562
563 string
564 ARDOUR::translation_kill_path ()
565 {
566         return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
567 }
568
569 bool
570 ARDOUR::translations_are_disabled ()
571 {
572         /* if file does not exist, we don't translate (bundled ardour only) */
573         return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;
574 }