e07437ce9df954efe0d57ce1e965245333690add
[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/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_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_SUPPOR
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         switch (Config->get_denormal_model()) {
458         case DenormalNone:
459                 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
460                 break;
461
462         case DenormalFTZ:
463                 if (fpu.has_flush_to_zero()) {
464                         MXCSR |= _MM_FLUSH_ZERO_ON;
465                 }
466                 break;
467
468         case DenormalDAZ:
469                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
470                 if (fpu.has_denormals_are_zero()) {
471                         MXCSR |= 0x8000;
472                 }
473                 break;
474
475         case DenormalFTZDAZ:
476                 if (fpu.has_flush_to_zero()) {
477                         if (fpu.has_denormals_are_zero()) {
478                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
479                         } else {
480                                 MXCSR |= _MM_FLUSH_ZERO_ON;
481                         }
482                 }
483                 break;
484         }
485
486         _mm_setcsr (MXCSR);
487
488 #endif
489 }
490
491 ARDOUR::OverlapType
492 ARDOUR::coverage (framepos_t sa, framepos_t ea,
493                   framepos_t sb, framepos_t eb)
494 {
495         /* OverlapType returned reflects how the second (B)
496            range overlaps the first (A).
497
498            The diagrams show various relative placements
499            of A and B for each OverlapType.
500
501            Notes:
502               Internal: the start points cannot coincide
503               External: the start and end points can coincide
504               Start: end points can coincide
505               End: start points can coincide
506
507            XXX Logically, Internal should disallow end
508            point equality.
509         */
510
511         /*
512              |--------------------|   A
513                   |------|            B
514                 |-----------------|   B
515
516
517              "B is internal to A"
518
519         */
520
521         if ((sb > sa) && (eb <= ea)) {
522                 return OverlapInternal;
523         }
524
525         /*
526              |--------------------|   A
527            ----|                      B
528            -----------------------|   B
529            --|                        B
530
531              "B overlaps the start of A"
532
533         */
534
535         if ((eb >= sa) && (eb <= ea)) {
536                 return OverlapStart;
537         }
538         /*
539              |---------------------|  A
540                    |----------------- B
541              |----------------------- B
542                                    |- B
543
544             "B overlaps the end of A"
545
546         */
547         if ((sb > sa) && (sb <= ea)) {
548                 return OverlapEnd;
549         }
550         /*
551              |--------------------|     A
552            --------------------------  B
553              |-----------------------  B
554             ----------------------|    B
555              |--------------------|    B
556
557
558            "B overlaps all of A"
559         */
560         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
561                 return OverlapExternal;
562         }
563
564         return OverlapNone;
565 }
566
567 string
568 ARDOUR::translation_kill_path ()
569 {
570         return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
571 }
572
573 bool
574 ARDOUR::translations_are_disabled ()
575 {
576         /* if file does not exist, we don't translate (bundled ardour only) */
577         return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;
578 }