plug some leaks
[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         (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
245 #endif
246
247         SessionEvent::init_event_pool ();
248
249         SessionObject::make_property_quarks ();
250         Region::make_property_quarks ();
251         MidiRegion::make_property_quarks ();
252         AudioRegion::make_property_quarks ();
253         RouteGroup::make_property_quarks ();
254         Playlist::make_property_quarks ();
255         AudioPlaylist::make_property_quarks ();
256
257         /* this is a useful ready to use PropertyChange that many
258            things need to check. This avoids having to compose
259            it every time we want to check for any of the relevant
260            property changes.
261         */
262
263         bounds_change.add (ARDOUR::Properties::start);
264         bounds_change.add (ARDOUR::Properties::position);
265         bounds_change.add (ARDOUR::Properties::length);
266
267         /* provide a state version for the few cases that need it and are not
268            driven by reading state from disk (e.g. undo/redo)
269         */
270
271         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
272
273         ARDOUR::setup_enum_writer ();
274
275         // allow ardour the absolute maximum number of open files
276         lotsa_files_please ();
277
278 #ifdef HAVE_LRDF
279         lrdf_init();
280 #endif
281         Library = new AudioLibrary;
282
283         BootMessage (_("Loading configuration"));
284
285         Config = new RCConfiguration;
286
287         if (Config->load_state ()) {
288                 return false;
289         }
290
291         Config->set_use_windows_vst (use_windows_vst);
292 #ifdef LXVST_SUPPORT
293         Config->set_use_lxvst(true);
294 #endif
295
296         Profile = new RuntimeProfile;
297
298
299 #ifdef WINDOWS_VST_SUPPORT
300         if (Config->get_use_windows_vst() && fst_init (0)) {
301                 return false;
302         }
303 #endif
304
305 #ifdef LXVST_SUPPORT
306         if (Config->get_use_lxvst() && vstfx_init (0)) {
307                 return false;
308         }
309 #endif
310
311 #ifdef AUDIOUNIT_SUPPORT
312         AUPluginInfo::load_cached_info ();
313 #endif
314
315         setup_hardware_optimization (try_optimization);
316
317         SourceFactory::init ();
318         Analyser::init ();
319
320         /* singleton - first object is "it" */
321         (void) PluginManager::instance();
322
323         ProcessThread::init ();
324         /* the + 4 is a bit of a handwave. i don't actually know
325            how many more per-thread buffer sets we need above
326            the h/w concurrency, but its definitely > 1 more.
327         */
328         BufferManager::init (hardware_concurrency() + 4); 
329
330         PannerManager::instance().discover_panners();
331
332         // Initialize parameter metadata
333         EventTypeMap::instance().new_parameter(NullAutomation);
334         EventTypeMap::instance().new_parameter(GainAutomation);
335         EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
336         EventTypeMap::instance().new_parameter(PanElevationAutomation);
337         EventTypeMap::instance().new_parameter(PanWidthAutomation);
338         EventTypeMap::instance().new_parameter(PluginAutomation);
339         EventTypeMap::instance().new_parameter(SoloAutomation);
340         EventTypeMap::instance().new_parameter(MuteAutomation);
341         EventTypeMap::instance().new_parameter(MidiCCAutomation);
342         EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
343         EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
344         EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
345         EventTypeMap::instance().new_parameter(FadeInAutomation);
346         EventTypeMap::instance().new_parameter(FadeOutAutomation);
347         EventTypeMap::instance().new_parameter(EnvelopeAutomation);
348         EventTypeMap::instance().new_parameter(MidiCCAutomation);
349
350         ARDOUR::AudioEngine::create ();
351
352         libardour_initialized = true;
353
354         return true;
355 }
356
357 void
358 ARDOUR::init_post_engine ()
359 {
360         ControlProtocolManager::instance().discover_control_protocols ();
361
362         XMLNode* node;
363         if ((node = Config->control_protocol_state()) != 0) {
364                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
365         }
366
367         /* find plugins */
368
369         ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
370 }
371
372 void
373 ARDOUR::cleanup () 
374 {
375         if (!libardour_initialized) {
376                 return;
377         }
378
379         ARDOUR::AudioEngine::destroy ();
380
381         delete Library;
382 #ifdef HAVE_LRDF
383         lrdf_cleanup ();
384 #endif
385         delete &ControlProtocolManager::instance();
386 #ifdef WINDOWS_VST_SUPPORT
387         fst_exit ();
388 #endif
389
390 #ifdef LXVST_SUPPORT
391         vstfx_exit();
392 #endif
393         delete &PluginManager::instance();
394         delete Config;
395         PBD::cleanup ();
396
397         return;
398 }
399
400 void
401 ARDOUR::find_bindings_files (map<string,string>& files)
402 {
403         vector<std::string> found;
404         Searchpath spath = ardour_config_search_path();
405
406         if (getenv ("ARDOUR_SAE")) {
407                 Glib::PatternSpec pattern("*SAE-*.bindings");
408                 find_matching_files_in_search_path (spath, pattern, found);
409         } else {
410                 Glib::PatternSpec pattern("*.bindings");
411                 find_matching_files_in_search_path (spath, pattern, found);
412         }
413
414         if (found.empty()) {
415                 return;
416         }
417
418         for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
419                 std::string path(*x);
420                 pair<string,string> namepath;
421                 namepath.second = path;
422                 namepath.first = PBD::basename_nosuffix (path);
423                 files.insert (namepath);
424         }
425 }
426
427 bool
428 ARDOUR::no_auto_connect()
429 {
430         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
431 }
432
433 void
434 ARDOUR::setup_fpu ()
435 {
436
437         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
438                 // valgrind doesn't understand this assembler stuff
439                 // September 10th, 2007
440                 return;
441         }
442
443 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
444
445         int MXCSR;
446         FPU fpu;
447
448         /* XXX use real code to determine if the processor supports
449            DenormalsAreZero and FlushToZero
450         */
451
452         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
453                 return;
454         }
455
456         MXCSR  = _mm_getcsr();
457
458 #ifdef DEBUG_DENORMAL_EXCEPTION
459         /* This will raise a FP exception if a denormal is detected */
460         MXCSR &= ~_MM_MASK_DENORM;
461 #endif  
462
463         switch (Config->get_denormal_model()) {
464         case DenormalNone:
465                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
466                 break;
467
468         case DenormalFTZ:
469                 if (fpu.has_flush_to_zero()) {
470                         MXCSR |= _MM_FLUSH_ZERO_ON;
471                 }
472                 break;
473
474         case DenormalDAZ:
475                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
476                 if (fpu.has_denormals_are_zero()) {
477                         MXCSR |= 0x40;
478                 }
479                 break;
480
481         case DenormalFTZDAZ:
482                 if (fpu.has_flush_to_zero()) {
483                         if (fpu.has_denormals_are_zero()) {
484                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
485                         } else {
486                                 MXCSR |= _MM_FLUSH_ZERO_ON;
487                         }
488                 }
489                 break;
490         }
491
492         _mm_setcsr (MXCSR);
493
494 #endif
495 }
496
497 /* this can be changed to modify the translation behaviour for
498    cases where the user has never expressed a preference.
499 */
500 static const bool translate_by_default = true;
501
502 string
503 ARDOUR::translation_enable_path ()
504 {
505         return Glib::build_filename (user_config_directory(), ".translate");
506 }
507
508 bool
509 ARDOUR::translations_are_enabled ()
510 {
511         int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
512
513         if (fd < 0) {
514                 return translate_by_default;
515         }
516
517         char c;
518         bool ret = false;
519
520         if (::read (fd, &c, 1) == 1 && c == '1') {
521                 ret = true;
522         }
523
524         ::close (fd);
525
526         return ret;
527 }
528
529 bool
530 ARDOUR::set_translations_enabled (bool yn)
531 {
532         string i18n_enabler = ARDOUR::translation_enable_path();
533         int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
534
535         if (fd < 0) {
536                 return false;
537         }
538         
539         char c;
540         
541         if (yn) {
542                 c = '1';
543         } else {
544                 c = '0';
545         }
546         
547         (void) ::write (fd, &c, 1);
548         (void) ::close (fd);
549
550         return true;
551 }
552
553
554 vector<SyncSource>
555 ARDOUR::get_available_sync_options ()
556 {
557         vector<SyncSource> ret;
558
559         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
560         if (backend && backend->name() == "JACK") {
561                 ret.push_back (Engine);
562         }
563
564         ret.push_back (MTC);
565         ret.push_back (MIDIClock);
566         ret.push_back (LTC);
567
568         return ret;
569 }
570
571 /** Return a monotonic value for the number of microseconds that have elapsed
572  * since an arbitrary zero origin.
573  */
574
575 #ifdef __MACH__
576 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
577  */
578 #include <mach/mach_time.h>
579 #define CLOCK_REALTIME 0
580 #define CLOCK_MONOTONIC 0
581 int 
582 clock_gettime (int /*clk_id*/, struct timespec *t)
583 {
584         static bool initialized = false;
585         static mach_timebase_info_data_t timebase;
586         if (!initialized) {
587                 mach_timebase_info(&timebase);
588                 initialized = true;
589         }
590         uint64_t time;
591         time = mach_absolute_time();
592         double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
593         double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
594         t->tv_sec = seconds;
595         t->tv_nsec = nseconds;
596         return 0;
597 }
598 #endif
599  
600 microseconds_t
601 ARDOUR::get_microseconds ()
602 {
603 #ifdef PLATFORM_WINDOWS
604         microseconds_t ret = 0;
605         LARGE_INTEGER freq, time;
606
607         if (QueryPerformanceFrequency(&freq))
608                 if (QueryPerformanceCounter(&time))
609                         ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
610
611         return ret;
612 #else
613         struct timespec ts;
614         if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
615                 /* EEEK! */
616                 return 0;
617         }
618         return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
619 #endif
620 }