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