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