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