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