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