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