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