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