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