start code reorganization needed to deal with backend choices. compiles, links and...
[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 <cstdlib>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <sys/resource.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32
33 #ifdef WINDOWS_VST_SUPPORT
34 #include <fst.h>
35 #endif
36
37 #ifdef LXVST_SUPPORT
38 #include "ardour/linux_vst_support.h"
39 #endif
40
41 #ifdef AUDIOUNIT_SUPPORT
42 #include "ardour/audio_unit.h"
43 #endif
44
45 #ifdef __SSE__
46 #include <xmmintrin.h>
47 #endif
48
49 #ifdef check
50 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
51 #endif 
52
53 #include <giomm.h>
54
55 #include <glibmm/fileutils.h>
56 #include <glibmm/miscutils.h>
57
58 #include <lrdf.h>
59
60 #include "pbd/cpus.h"
61 #include "pbd/error.h"
62 #include "pbd/id.h"
63 #include "pbd/strsplit.h"
64 #include "pbd/fpu.h"
65 #include "pbd/file_utils.h"
66 #include "pbd/enumwriter.h"
67 #include "pbd/basename.h"
68
69 #include "midi++/port.h"
70 #include "midi++/manager.h"
71 #include "midi++/mmc.h"
72
73 #include "ardour/analyser.h"
74 #include "ardour/audio_library.h"
75 #include "ardour/audioengine.h"
76 #include "ardour/audioplaylist.h"
77 #include "ardour/audioregion.h"
78 #include "ardour/buffer_manager.h"
79 #include "ardour/control_protocol_manager.h"
80 #include "ardour/filesystem_paths.h"
81 #include "ardour/midi_region.h"
82 #include "ardour/mix.h"
83 #include "ardour/panner_manager.h"
84 #include "ardour/plugin_manager.h"
85 #include "ardour/process_thread.h"
86 #include "ardour/profile.h"
87 #include "ardour/rc_configuration.h"
88 #include "ardour/region.h"
89 #include "ardour/route_group.h"
90 #include "ardour/runtime_functions.h"
91 #include "ardour/session_event.h"
92 #include "ardour/source_factory.h"
93
94 #include "audiographer/routines.h"
95
96 #if defined (__APPLE__)
97        #include <Carbon/Carbon.h> // For Gestalt
98 #endif
99
100 #include "i18n.h"
101
102 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
103 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
104 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
105
106 using namespace ARDOUR;
107 using namespace std;
108 using namespace PBD;
109
110 compute_peak_t          ARDOUR::compute_peak = 0;
111 find_peaks_t            ARDOUR::find_peaks = 0;
112 apply_gain_to_buffer_t  ARDOUR::apply_gain_to_buffer = 0;
113 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
114 mix_buffers_no_gain_t   ARDOUR::mix_buffers_no_gain = 0;
115
116 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
117 PBD::Signal0<void> ARDOUR::GUIIdle;
118
119 namespace ARDOUR {
120 extern void setup_enum_writer ();
121 }
122
123 /* this is useful for quite a few things that want to check
124    if any bounds-related property has changed
125 */
126 PBD::PropertyChange ARDOUR::bounds_change;
127
128 void
129 setup_hardware_optimization (bool try_optimization)
130 {
131         bool generic_mix_functions = true;
132
133         if (try_optimization) {
134
135                 FPU fpu;
136
137 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
138
139                 if (fpu.has_sse()) {
140
141                         info << "Using SSE optimized routines" << endmsg;
142
143                         // SSE SET
144                         compute_peak          = x86_sse_compute_peak;
145                         find_peaks            = x86_sse_find_peaks;
146                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
147                         mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
148                         mix_buffers_no_gain   = x86_sse_mix_buffers_no_gain;
149
150                         generic_mix_functions = false;
151
152                 }
153
154 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
155                 SInt32 sysVersion = 0;
156
157                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
158                         sysVersion = 0;
159
160                 if (sysVersion >= 0x00001040) { // Tiger at least
161                         compute_peak           = veclib_compute_peak;
162                         find_peaks             = veclib_find_peaks;
163                         apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
164                         mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
165                         mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
166
167                         generic_mix_functions = false;
168
169                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
170                 }
171 #endif
172
173                 /* consider FPU denormal handling to be "h/w optimization" */
174
175                 setup_fpu ();
176         }
177
178         if (generic_mix_functions) {
179
180                 compute_peak          = default_compute_peak;
181                 find_peaks            = default_find_peaks;
182                 apply_gain_to_buffer  = default_apply_gain_to_buffer;
183                 mix_buffers_with_gain = default_mix_buffers_with_gain;
184                 mix_buffers_no_gain   = default_mix_buffers_no_gain;
185
186                 info << "No H/W specific optimizations in use" << endmsg;
187         }
188
189         AudioGrapher::Routines::override_compute_peak (compute_peak);
190         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
191 }
192
193 static void
194 lotsa_files_please ()
195 {
196         struct rlimit rl;
197
198         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
199
200                 rl.rlim_cur = rl.rlim_max;
201
202                 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
203                         if (rl.rlim_cur == RLIM_INFINITY) {
204                                 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
205                         } else {
206                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
207                         }
208                 } else {
209                         if (rl.rlim_cur != RLIM_INFINITY) {
210                                 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
211                         }
212                 }
213         } else {
214                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
215         }
216 }
217
218 int
219 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
220 {
221         if (!Glib::thread_supported()) {
222                 Glib::thread_init();
223         }
224
225         // this really should be in PBD::init..if there was one
226         Gio::init ();
227
228 #ifdef ENABLE_NLS
229         (void) bindtextdomain(PACKAGE, localedir);
230 #endif
231
232         PBD::ID::init ();
233         SessionEvent::init_event_pool ();
234
235         SessionObject::make_property_quarks ();
236         Region::make_property_quarks ();
237         MidiRegion::make_property_quarks ();
238         AudioRegion::make_property_quarks ();
239         RouteGroup::make_property_quarks ();
240         Playlist::make_property_quarks ();
241         AudioPlaylist::make_property_quarks ();
242
243         /* this is a useful ready to use PropertyChange that many
244            things need to check. This avoids having to compose
245            it every time we want to check for any of the relevant
246            property changes.
247         */
248
249         bounds_change.add (ARDOUR::Properties::start);
250         bounds_change.add (ARDOUR::Properties::position);
251         bounds_change.add (ARDOUR::Properties::length);
252
253         /* provide a state version for the few cases that need it and are not
254            driven by reading state from disk (e.g. undo/redo)
255         */
256
257         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
258
259         ARDOUR::setup_enum_writer ();
260
261         // allow ardour the absolute maximum number of open files
262         lotsa_files_please ();
263
264         lrdf_init();
265         Library = new AudioLibrary;
266
267         BootMessage (_("Loading configuration"));
268
269         Config = new RCConfiguration;
270
271         if (Config->load_state ()) {
272                 return -1;
273         }
274
275         Config->set_use_windows_vst (use_windows_vst);
276 #ifdef LXVST_SUPPORT
277         Config->set_use_lxvst(true);
278 #endif
279
280         Profile = new RuntimeProfile;
281
282
283 #ifdef WINDOWS_VST_SUPPORT
284         if (Config->get_use_windows_vst() && fst_init (0)) {
285                 return -1;
286         }
287 #endif
288
289 #ifdef LXVST_SUPPORT
290         if (Config->get_use_lxvst() && vstfx_init (0)) {
291                 return -1;
292         }
293 #endif
294
295 #ifdef AUDIOUNIT_SUPPORT
296         AUPluginInfo::load_cached_info ();
297 #endif
298
299         setup_hardware_optimization (try_optimization);
300
301         SourceFactory::init ();
302         Analyser::init ();
303
304         /* singleton - first object is "it" */
305         (void) PluginManager::instance();
306
307         ProcessThread::init ();
308         /* the + 4 is a bit of a handwave. i don't actually know
309            how many more per-thread buffer sets we need above
310            the h/w concurrency, but its definitely > 1 more.
311         */
312         BufferManager::init (hardware_concurrency() + 4); 
313
314         PannerManager::instance().discover_panners();
315
316         // Initialize parameter metadata
317         EventTypeMap::instance().new_parameter(NullAutomation);
318         EventTypeMap::instance().new_parameter(GainAutomation);
319         EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
320         EventTypeMap::instance().new_parameter(PanElevationAutomation);
321         EventTypeMap::instance().new_parameter(PanWidthAutomation);
322         EventTypeMap::instance().new_parameter(PluginAutomation);
323         EventTypeMap::instance().new_parameter(SoloAutomation);
324         EventTypeMap::instance().new_parameter(MuteAutomation);
325         EventTypeMap::instance().new_parameter(MidiCCAutomation);
326         EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
327         EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
328         EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
329         EventTypeMap::instance().new_parameter(FadeInAutomation);
330         EventTypeMap::instance().new_parameter(FadeOutAutomation);
331         EventTypeMap::instance().new_parameter(EnvelopeAutomation);
332         EventTypeMap::instance().new_parameter(MidiCCAutomation);
333
334         ARDOUR::AudioEngine::create ();
335
336         uint32_t backend_cnt;
337
338         if ((backend_cnt = AudioEngine::instance()->available_backends().size()) == 0) {
339                 error << _("No audio/MIDI backends are available") << endmsg;
340                 return -1;
341         }
342
343         cerr << "We have " << backend_cnt << endl;
344
345         return 0;
346 }
347
348 void
349 ARDOUR::init_post_engine ()
350 {
351         /* the MIDI Manager is needed by the ControlProtocolManager */
352         MIDI::Manager::create (AudioEngine::instance()->port_engine());
353
354         ControlProtocolManager::instance().discover_control_protocols ();
355
356         XMLNode* node;
357         if ((node = Config->control_protocol_state()) != 0) {
358                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
359         }
360
361         /* find plugins */
362
363         ARDOUR::PluginManager::instance().refresh ();
364 }
365
366 int
367 ARDOUR::cleanup ()
368 {
369         delete Library;
370         lrdf_cleanup ();
371         delete &ControlProtocolManager::instance();
372 #ifdef WINDOWS_VST_SUPPORT
373         fst_exit ();
374 #endif
375
376 #ifdef LXVST_SUPPORT
377         vstfx_exit();
378 #endif
379         EnumWriter::destroy ();
380         return 0;
381 }
382
383 void
384 ARDOUR::find_bindings_files (map<string,string>& files)
385 {
386         vector<std::string> found;
387         SearchPath spath = ardour_config_search_path();
388
389         if (getenv ("ARDOUR_SAE")) {
390                 Glib::PatternSpec pattern("*SAE-*.bindings");
391                 find_matching_files_in_search_path (spath, pattern, found);
392         } else {
393                 Glib::PatternSpec pattern("*.bindings");
394                 find_matching_files_in_search_path (spath, pattern, found);
395         }
396
397         if (found.empty()) {
398                 return;
399         }
400
401         for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
402                 std::string path(*x);
403                 pair<string,string> namepath;
404                 namepath.second = path;
405                 namepath.first = PBD::basename_nosuffix (path);
406                 files.insert (namepath);
407         }
408 }
409
410 bool
411 ARDOUR::no_auto_connect()
412 {
413         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
414 }
415
416 void
417 ARDOUR::setup_fpu ()
418 {
419
420         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
421                 // valgrind doesn't understand this assembler stuff
422                 // September 10th, 2007
423                 return;
424         }
425
426 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
427
428         int MXCSR;
429         FPU fpu;
430
431         /* XXX use real code to determine if the processor supports
432            DenormalsAreZero and FlushToZero
433         */
434
435         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
436                 return;
437         }
438
439         MXCSR  = _mm_getcsr();
440
441 #ifdef DEBUG_DENORMAL_EXCEPTION
442         /* This will raise a FP exception if a denormal is detected */
443         MXCSR &= ~_MM_MASK_DENORM;
444 #endif  
445
446         switch (Config->get_denormal_model()) {
447         case DenormalNone:
448                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
449                 break;
450
451         case DenormalFTZ:
452                 if (fpu.has_flush_to_zero()) {
453                         MXCSR |= _MM_FLUSH_ZERO_ON;
454                 }
455                 break;
456
457         case DenormalDAZ:
458                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
459                 if (fpu.has_denormals_are_zero()) {
460                         MXCSR |= 0x40;
461                 }
462                 break;
463
464         case DenormalFTZDAZ:
465                 if (fpu.has_flush_to_zero()) {
466                         if (fpu.has_denormals_are_zero()) {
467                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
468                         } else {
469                                 MXCSR |= _MM_FLUSH_ZERO_ON;
470                         }
471                 }
472                 break;
473         }
474
475         _mm_setcsr (MXCSR);
476
477 #endif
478 }
479
480 /* this can be changed to modify the translation behaviour for
481    cases where the user has never expressed a preference.
482 */
483 static const bool translate_by_default = true;
484
485 string
486 ARDOUR::translation_enable_path ()
487 {
488         return Glib::build_filename (user_config_directory(), ".translate");
489 }
490
491 bool
492 ARDOUR::translations_are_enabled ()
493 {
494         int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
495
496         if (fd < 0) {
497                 return translate_by_default;
498         }
499
500         char c;
501         bool ret = false;
502
503         if (::read (fd, &c, 1) == 1 && c == '1') {
504                 ret = true;
505         }
506
507         ::close (fd);
508
509         return ret;
510 }
511
512 bool
513 ARDOUR::set_translations_enabled (bool yn)
514 {
515         string i18n_enabler = ARDOUR::translation_enable_path();
516         int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
517
518         if (fd < 0) {
519                 return false;
520         }
521         
522         char c;
523         
524         if (yn) {
525                 c = '1';
526         } else {
527                 c = '0';
528         }
529         
530         ::write (fd, &c, 1);
531         ::close (fd);
532
533         return true;
534 }
535
536
537 vector<SyncSource>
538 ARDOUR::get_available_sync_options ()
539 {
540         vector<SyncSource> ret;
541
542         ret.push_back (JACK);
543         ret.push_back (MTC);
544         ret.push_back (MIDIClock);
545         ret.push_back (LTC);
546
547         return ret;
548 }