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