Merge branch 'master' into audioengine
[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 <cstdlib>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <sys/resource.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <time.h>
33
34 #ifdef WINDOWS_VST_SUPPORT
35 #include <fst.h>
36 #endif
37
38 #ifdef LXVST_SUPPORT
39 #include "ardour/linux_vst_support.h"
40 #endif
41
42 #ifdef AUDIOUNIT_SUPPORT
43 #include "ardour/audio_unit.h"
44 #endif
45
46 #ifdef __SSE__
47 #include <xmmintrin.h>
48 #endif
49
50 #ifdef check
51 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
52 #endif 
53
54 #include <giomm.h>
55
56 #include <glibmm/fileutils.h>
57 #include <glibmm/miscutils.h>
58
59 #include <lrdf.h>
60
61 #include "pbd/cpus.h"
62 #include "pbd/error.h"
63 #include "pbd/id.h"
64 #include "pbd/strsplit.h"
65 #include "pbd/fpu.h"
66 #include "pbd/file_utils.h"
67 #include "pbd/enumwriter.h"
68 #include "pbd/basename.h"
69
70 #include "midi++/port.h"
71 #include "midi++/mmc.h"
72
73 #include "ardour/analyser.h"
74 #include "ardour/audio_library.h"
75 #include "ardour/audio_backend.h"
76 #include "ardour/audioengine.h"
77 #include "ardour/audioplaylist.h"
78 #include "ardour/audioregion.h"
79 #include "ardour/buffer_manager.h"
80 #include "ardour/control_protocol_manager.h"
81 #include "ardour/filesystem_paths.h"
82 #include "ardour/midi_region.h"
83 #include "ardour/midiport_manager.h"
84 #include "ardour/mix.h"
85 #include "ardour/panner_manager.h"
86 #include "ardour/plugin_manager.h"
87 #include "ardour/process_thread.h"
88 #include "ardour/profile.h"
89 #include "ardour/rc_configuration.h"
90 #include "ardour/region.h"
91 #include "ardour/route_group.h"
92 #include "ardour/runtime_functions.h"
93 #include "ardour/session_event.h"
94 #include "ardour/source_factory.h"
95
96 #include "audiographer/routines.h"
97
98 #if defined (__APPLE__)
99        #include <Carbon/Carbon.h> // For Gestalt
100 #endif
101
102 #include "i18n.h"
103
104 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
105 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
106 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
107
108 using namespace ARDOUR;
109 using namespace std;
110 using namespace PBD;
111
112 compute_peak_t          ARDOUR::compute_peak = 0;
113 find_peaks_t            ARDOUR::find_peaks = 0;
114 apply_gain_to_buffer_t  ARDOUR::apply_gain_to_buffer = 0;
115 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
116 mix_buffers_no_gain_t   ARDOUR::mix_buffers_no_gain = 0;
117
118 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
119 PBD::Signal0<void> ARDOUR::GUIIdle;
120
121 namespace ARDOUR {
122 extern void setup_enum_writer ();
123 }
124
125 /* this is useful for quite a few things that want to check
126    if any bounds-related property has changed
127 */
128 PBD::PropertyChange ARDOUR::bounds_change;
129
130 void
131 setup_hardware_optimization (bool try_optimization)
132 {
133         bool generic_mix_functions = true;
134
135         if (try_optimization) {
136
137                 FPU fpu;
138
139 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
140
141                 if (fpu.has_sse()) {
142
143                         info << "Using SSE optimized routines" << endmsg;
144
145                         // SSE SET
146                         compute_peak          = x86_sse_compute_peak;
147                         find_peaks            = x86_sse_find_peaks;
148                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
149                         mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
150                         mix_buffers_no_gain   = x86_sse_mix_buffers_no_gain;
151
152                         generic_mix_functions = false;
153
154                 }
155
156 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
157                 SInt32 sysVersion = 0;
158
159                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
160                         sysVersion = 0;
161
162                 if (sysVersion >= 0x00001040) { // Tiger at least
163                         compute_peak           = veclib_compute_peak;
164                         find_peaks             = veclib_find_peaks;
165                         apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
166                         mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
167                         mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
168
169                         generic_mix_functions = false;
170
171                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
172                 }
173 #endif
174
175                 /* consider FPU denormal handling to be "h/w optimization" */
176
177                 setup_fpu ();
178         }
179
180         if (generic_mix_functions) {
181
182                 compute_peak          = default_compute_peak;
183                 find_peaks            = default_find_peaks;
184                 apply_gain_to_buffer  = default_apply_gain_to_buffer;
185                 mix_buffers_with_gain = default_mix_buffers_with_gain;
186                 mix_buffers_no_gain   = default_mix_buffers_no_gain;
187
188                 info << "No H/W specific optimizations in use" << endmsg;
189         }
190
191         AudioGrapher::Routines::override_compute_peak (compute_peak);
192         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
193 }
194
195 static void
196 lotsa_files_please ()
197 {
198         struct rlimit rl;
199
200         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
201
202                 rl.rlim_cur = rl.rlim_max;
203
204                 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
205                         if (rl.rlim_cur == RLIM_INFINITY) {
206                                 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
207                         } else {
208                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
209                         }
210                 } else {
211                         if (rl.rlim_cur != RLIM_INFINITY) {
212                                 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
213                         }
214                 }
215         } else {
216                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
217         }
218 }
219
220 int
221 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
222 {
223         if (!Glib::thread_supported()) {
224                 Glib::thread_init();
225         }
226
227         // this really should be in PBD::init..if there was one
228         Gio::init ();
229
230 #ifdef ENABLE_NLS
231         (void) bindtextdomain(PACKAGE, localedir);
232 #endif
233
234         PBD::ID::init ();
235         SessionEvent::init_event_pool ();
236
237         SessionObject::make_property_quarks ();
238         Region::make_property_quarks ();
239         MidiRegion::make_property_quarks ();
240         AudioRegion::make_property_quarks ();
241         RouteGroup::make_property_quarks ();
242         Playlist::make_property_quarks ();
243         AudioPlaylist::make_property_quarks ();
244
245         /* this is a useful ready to use PropertyChange that many
246            things need to check. This avoids having to compose
247            it every time we want to check for any of the relevant
248            property changes.
249         */
250
251         bounds_change.add (ARDOUR::Properties::start);
252         bounds_change.add (ARDOUR::Properties::position);
253         bounds_change.add (ARDOUR::Properties::length);
254
255         /* provide a state version for the few cases that need it and are not
256            driven by reading state from disk (e.g. undo/redo)
257         */
258
259         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
260
261         ARDOUR::setup_enum_writer ();
262
263         // allow ardour the absolute maximum number of open files
264         lotsa_files_please ();
265
266         lrdf_init();
267         Library = new AudioLibrary;
268
269         BootMessage (_("Loading configuration"));
270
271         Config = new RCConfiguration;
272
273         if (Config->load_state ()) {
274                 return -1;
275         }
276
277         Config->set_use_windows_vst (use_windows_vst);
278 #ifdef LXVST_SUPPORT
279         Config->set_use_lxvst(true);
280 #endif
281
282         Profile = new RuntimeProfile;
283
284
285 #ifdef WINDOWS_VST_SUPPORT
286         if (Config->get_use_windows_vst() && fst_init (0)) {
287                 return -1;
288         }
289 #endif
290
291 #ifdef LXVST_SUPPORT
292         if (Config->get_use_lxvst() && vstfx_init (0)) {
293                 return -1;
294         }
295 #endif
296
297 #ifdef AUDIOUNIT_SUPPORT
298         AUPluginInfo::load_cached_info ();
299 #endif
300
301         setup_hardware_optimization (try_optimization);
302
303         SourceFactory::init ();
304         Analyser::init ();
305
306         /* singleton - first object is "it" */
307         (void) PluginManager::instance();
308
309         ProcessThread::init ();
310         /* the + 4 is a bit of a handwave. i don't actually know
311            how many more per-thread buffer sets we need above
312            the h/w concurrency, but its definitely > 1 more.
313         */
314         BufferManager::init (hardware_concurrency() + 4); 
315
316         PannerManager::instance().discover_panners();
317
318         // Initialize parameter metadata
319         EventTypeMap::instance().new_parameter(NullAutomation);
320         EventTypeMap::instance().new_parameter(GainAutomation);
321         EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
322         EventTypeMap::instance().new_parameter(PanElevationAutomation);
323         EventTypeMap::instance().new_parameter(PanWidthAutomation);
324         EventTypeMap::instance().new_parameter(PluginAutomation);
325         EventTypeMap::instance().new_parameter(SoloAutomation);
326         EventTypeMap::instance().new_parameter(MuteAutomation);
327         EventTypeMap::instance().new_parameter(MidiCCAutomation);
328         EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
329         EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
330         EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
331         EventTypeMap::instance().new_parameter(FadeInAutomation);
332         EventTypeMap::instance().new_parameter(FadeOutAutomation);
333         EventTypeMap::instance().new_parameter(EnvelopeAutomation);
334         EventTypeMap::instance().new_parameter(MidiCCAutomation);
335
336         ARDOUR::AudioEngine::create ();
337
338         return 0;
339 }
340
341 void
342 ARDOUR::init_post_engine ()
343 {
344         ControlProtocolManager::instance().discover_control_protocols ();
345
346         XMLNode* node;
347         if ((node = Config->control_protocol_state()) != 0) {
348                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
349         }
350
351         /* find plugins */
352
353         ARDOUR::PluginManager::instance().refresh ();
354 }
355
356 int
357 ARDOUR::cleanup ()
358 {
359         delete Library;
360         lrdf_cleanup ();
361         delete &ControlProtocolManager::instance();
362 #ifdef WINDOWS_VST_SUPPORT
363         fst_exit ();
364 #endif
365
366 #ifdef LXVST_SUPPORT
367         vstfx_exit();
368 #endif
369         EnumWriter::destroy ();
370         return 0;
371 }
372
373 void
374 ARDOUR::find_bindings_files (map<string,string>& files)
375 {
376         vector<std::string> found;
377         SearchPath spath = ardour_config_search_path();
378
379         if (getenv ("ARDOUR_SAE")) {
380                 Glib::PatternSpec pattern("*SAE-*.bindings");
381                 find_matching_files_in_search_path (spath, pattern, found);
382         } else {
383                 Glib::PatternSpec pattern("*.bindings");
384                 find_matching_files_in_search_path (spath, pattern, found);
385         }
386
387         if (found.empty()) {
388                 return;
389         }
390
391         for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
392                 std::string path(*x);
393                 pair<string,string> namepath;
394                 namepath.second = path;
395                 namepath.first = PBD::basename_nosuffix (path);
396                 files.insert (namepath);
397         }
398 }
399
400 bool
401 ARDOUR::no_auto_connect()
402 {
403         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
404 }
405
406 void
407 ARDOUR::setup_fpu ()
408 {
409
410         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
411                 // valgrind doesn't understand this assembler stuff
412                 // September 10th, 2007
413                 return;
414         }
415
416 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
417
418         int MXCSR;
419         FPU fpu;
420
421         /* XXX use real code to determine if the processor supports
422            DenormalsAreZero and FlushToZero
423         */
424
425         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
426                 return;
427         }
428
429         MXCSR  = _mm_getcsr();
430
431 #ifdef DEBUG_DENORMAL_EXCEPTION
432         /* This will raise a FP exception if a denormal is detected */
433         MXCSR &= ~_MM_MASK_DENORM;
434 #endif  
435
436         switch (Config->get_denormal_model()) {
437         case DenormalNone:
438                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
439                 break;
440
441         case DenormalFTZ:
442                 if (fpu.has_flush_to_zero()) {
443                         MXCSR |= _MM_FLUSH_ZERO_ON;
444                 }
445                 break;
446
447         case DenormalDAZ:
448                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
449                 if (fpu.has_denormals_are_zero()) {
450                         MXCSR |= 0x40;
451                 }
452                 break;
453
454         case DenormalFTZDAZ:
455                 if (fpu.has_flush_to_zero()) {
456                         if (fpu.has_denormals_are_zero()) {
457                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
458                         } else {
459                                 MXCSR |= _MM_FLUSH_ZERO_ON;
460                         }
461                 }
462                 break;
463         }
464
465         _mm_setcsr (MXCSR);
466
467 #endif
468 }
469
470 /* this can be changed to modify the translation behaviour for
471    cases where the user has never expressed a preference.
472 */
473 static const bool translate_by_default = true;
474
475 string
476 ARDOUR::translation_enable_path ()
477 {
478         return Glib::build_filename (user_config_directory(), ".translate");
479 }
480
481 bool
482 ARDOUR::translations_are_enabled ()
483 {
484         int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
485
486         if (fd < 0) {
487                 return translate_by_default;
488         }
489
490         char c;
491         bool ret = false;
492
493         if (::read (fd, &c, 1) == 1 && c == '1') {
494                 ret = true;
495         }
496
497         ::close (fd);
498
499         return ret;
500 }
501
502 bool
503 ARDOUR::set_translations_enabled (bool yn)
504 {
505         string i18n_enabler = ARDOUR::translation_enable_path();
506         int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
507
508         if (fd < 0) {
509                 return false;
510         }
511         
512         char c;
513         
514         if (yn) {
515                 c = '1';
516         } else {
517                 c = '0';
518         }
519         
520         ::write (fd, &c, 1);
521         ::close (fd);
522
523         return true;
524 }
525
526
527 vector<SyncSource>
528 ARDOUR::get_available_sync_options ()
529 {
530         vector<SyncSource> ret;
531
532         ret.push_back (JACK);
533         ret.push_back (MTC);
534         ret.push_back (MIDIClock);
535         ret.push_back (LTC);
536
537         return ret;
538 }
539
540 /** Return a monotonic value for the number of microseconds that have elapsed
541  * since an arbitrary zero origin.
542  */
543  
544 microseconds_t
545 ARDOUR::get_microseconds ()
546 {
547         struct timespec ts;
548         if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
549                 /* EEEK! */
550                 return 0;
551         }
552         return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
553 }