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