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