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