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