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