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