merge with master and fix 4 conflicts by hand
[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         PBD::cleanup ();
394
395         return;
396 }
397
398 void
399 ARDOUR::find_bindings_files (map<string,string>& files)
400 {
401         vector<std::string> found;
402         Searchpath spath = ardour_config_search_path();
403
404         if (getenv ("ARDOUR_SAE")) {
405                 Glib::PatternSpec pattern("*SAE-*.bindings");
406                 find_matching_files_in_search_path (spath, pattern, found);
407         } else {
408                 Glib::PatternSpec pattern("*.bindings");
409                 find_matching_files_in_search_path (spath, pattern, found);
410         }
411
412         if (found.empty()) {
413                 return;
414         }
415
416         for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
417                 std::string path(*x);
418                 pair<string,string> namepath;
419                 namepath.second = path;
420                 namepath.first = PBD::basename_nosuffix (path);
421                 files.insert (namepath);
422         }
423 }
424
425 bool
426 ARDOUR::no_auto_connect()
427 {
428         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
429 }
430
431 void
432 ARDOUR::setup_fpu ()
433 {
434
435         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
436                 // valgrind doesn't understand this assembler stuff
437                 // September 10th, 2007
438                 return;
439         }
440
441 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
442
443         int MXCSR;
444         FPU fpu;
445
446         /* XXX use real code to determine if the processor supports
447            DenormalsAreZero and FlushToZero
448         */
449
450         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
451                 return;
452         }
453
454         MXCSR  = _mm_getcsr();
455
456 #ifdef DEBUG_DENORMAL_EXCEPTION
457         /* This will raise a FP exception if a denormal is detected */
458         MXCSR &= ~_MM_MASK_DENORM;
459 #endif  
460
461         switch (Config->get_denormal_model()) {
462         case DenormalNone:
463                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
464                 break;
465
466         case DenormalFTZ:
467                 if (fpu.has_flush_to_zero()) {
468                         MXCSR |= _MM_FLUSH_ZERO_ON;
469                 }
470                 break;
471
472         case DenormalDAZ:
473                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
474                 if (fpu.has_denormals_are_zero()) {
475                         MXCSR |= 0x40;
476                 }
477                 break;
478
479         case DenormalFTZDAZ:
480                 if (fpu.has_flush_to_zero()) {
481                         if (fpu.has_denormals_are_zero()) {
482                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
483                         } else {
484                                 MXCSR |= _MM_FLUSH_ZERO_ON;
485                         }
486                 }
487                 break;
488         }
489
490         _mm_setcsr (MXCSR);
491
492 #endif
493 }
494
495 /* this can be changed to modify the translation behaviour for
496    cases where the user has never expressed a preference.
497 */
498 static const bool translate_by_default = true;
499
500 string
501 ARDOUR::translation_enable_path ()
502 {
503         return Glib::build_filename (user_config_directory(), ".translate");
504 }
505
506 bool
507 ARDOUR::translations_are_enabled ()
508 {
509         int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
510
511         if (fd < 0) {
512                 return translate_by_default;
513         }
514
515         char c;
516         bool ret = false;
517
518         if (::read (fd, &c, 1) == 1 && c == '1') {
519                 ret = true;
520         }
521
522         ::close (fd);
523
524         return ret;
525 }
526
527 bool
528 ARDOUR::set_translations_enabled (bool yn)
529 {
530         string i18n_enabler = ARDOUR::translation_enable_path();
531         int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
532
533         if (fd < 0) {
534                 return false;
535         }
536         
537         char c;
538         
539         if (yn) {
540                 c = '1';
541         } else {
542                 c = '0';
543         }
544         
545         (void) ::write (fd, &c, 1);
546         (void) ::close (fd);
547
548         return true;
549 }
550
551
552 vector<SyncSource>
553 ARDOUR::get_available_sync_options ()
554 {
555         vector<SyncSource> ret;
556
557         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
558         if (backend && backend->name() == "JACK") {
559                 ret.push_back (Engine);
560         }
561
562         ret.push_back (MTC);
563         ret.push_back (MIDIClock);
564         ret.push_back (LTC);
565
566         return ret;
567 }
568
569 /** Return a monotonic value for the number of microseconds that have elapsed
570  * since an arbitrary zero origin.
571  */
572
573 #ifdef __MACH__
574 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
575  */
576 #include <mach/mach_time.h>
577 #define CLOCK_REALTIME 0
578 #define CLOCK_MONOTONIC 0
579 int 
580 clock_gettime (int /*clk_id*/, struct timespec *t)
581 {
582         static bool initialized = false;
583         static mach_timebase_info_data_t timebase;
584         if (!initialized) {
585                 mach_timebase_info(&timebase);
586                 initialized = true;
587         }
588         uint64_t time;
589         time = mach_absolute_time();
590         double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
591         double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
592         t->tv_sec = seconds;
593         t->tv_nsec = nseconds;
594         return 0;
595 }
596 #endif
597  
598 microseconds_t
599 ARDOUR::get_microseconds ()
600 {
601 #ifdef PLATFORM_WINDOWS
602         microseconds_t ret = 0;
603         LARGE_INTEGER freq, time;
604
605         if (QueryPerformanceFrequency(&freq))
606                 if (QueryPerformanceCounter(&time))
607                         ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
608
609         return ret;
610 #else
611         struct timespec ts;
612         if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
613                 /* EEEK! */
614                 return 0;
615         }
616         return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
617 #endif
618 }