Call Gio::init from PBD::init instead of ARDOUR::init
[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 <glibmm/fileutils.h>
54 #include <glibmm/miscutils.h>
55
56 #include <lrdf.h>
57
58 #include "pbd/cpus.h"
59 #include "pbd/error.h"
60 #include "pbd/id.h"
61 #include "pbd/pbd.h"
62 #include "pbd/strsplit.h"
63 #include "pbd/fpu.h"
64 #include "pbd/file_utils.h"
65 #include "pbd/enumwriter.h"
66 #include "pbd/basename.h"
67
68 #include "midi++/port.h"
69 #include "midi++/manager.h"
70 #include "midi++/mmc.h"
71
72 #include "ardour/analyser.h"
73 #include "ardour/audio_library.h"
74 #include "ardour/audioengine.h"
75 #include "ardour/audioplaylist.h"
76 #include "ardour/audioregion.h"
77 #include "ardour/buffer_manager.h"
78 #include "ardour/control_protocol_manager.h"
79 #include "ardour/filesystem_paths.h"
80 #include "ardour/midi_region.h"
81 #include "ardour/mix.h"
82 #include "ardour/panner_manager.h"
83 #include "ardour/plugin_manager.h"
84 #include "ardour/process_thread.h"
85 #include "ardour/profile.h"
86 #include "ardour/rc_configuration.h"
87 #include "ardour/region.h"
88 #include "ardour/route_group.h"
89 #include "ardour/runtime_functions.h"
90 #include "ardour/session_event.h"
91 #include "ardour/source_factory.h"
92
93 #include "audiographer/routines.h"
94
95 #if defined (__APPLE__)
96        #include <Carbon/Carbon.h> // For Gestalt
97 #endif
98
99 #include "i18n.h"
100
101 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
102 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
103 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
104
105 using namespace ARDOUR;
106 using namespace std;
107 using namespace PBD;
108
109 bool libardour_initialized = false;
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 bool
220 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
221 {
222         if (libardour_initialized) {
223                 return true;
224         }
225
226         if (!PBD::init()) return false;
227
228 #ifdef ENABLE_NLS
229         (void) bindtextdomain(PACKAGE, localedir);
230 #endif
231
232         SessionEvent::init_event_pool ();
233
234         SessionObject::make_property_quarks ();
235         Region::make_property_quarks ();
236         MidiRegion::make_property_quarks ();
237         AudioRegion::make_property_quarks ();
238         RouteGroup::make_property_quarks ();
239         Playlist::make_property_quarks ();
240         AudioPlaylist::make_property_quarks ();
241
242         /* this is a useful ready to use PropertyChange that many
243            things need to check. This avoids having to compose
244            it every time we want to check for any of the relevant
245            property changes.
246         */
247
248         bounds_change.add (ARDOUR::Properties::start);
249         bounds_change.add (ARDOUR::Properties::position);
250         bounds_change.add (ARDOUR::Properties::length);
251
252         /* provide a state version for the few cases that need it and are not
253            driven by reading state from disk (e.g. undo/redo)
254         */
255
256         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
257
258         ARDOUR::setup_enum_writer ();
259
260         // allow ardour the absolute maximum number of open files
261         lotsa_files_please ();
262
263         lrdf_init();
264         Library = new AudioLibrary;
265
266         BootMessage (_("Loading configuration"));
267
268         Config = new RCConfiguration;
269
270         if (Config->load_state ()) {
271                 return false;
272         }
273
274         Config->set_use_windows_vst (use_windows_vst);
275 #ifdef LXVST_SUPPORT
276         Config->set_use_lxvst(true);
277 #endif
278
279         Profile = new RuntimeProfile;
280
281
282 #ifdef WINDOWS_VST_SUPPORT
283         if (Config->get_use_windows_vst() && fst_init (0)) {
284                 return false;
285         }
286 #endif
287
288 #ifdef LXVST_SUPPORT
289         if (Config->get_use_lxvst() && vstfx_init (0)) {
290                 return false;
291         }
292 #endif
293
294 #ifdef AUDIOUNIT_SUPPORT
295         AUPluginInfo::load_cached_info ();
296 #endif
297
298         setup_hardware_optimization (try_optimization);
299
300         SourceFactory::init ();
301         Analyser::init ();
302
303         /* singleton - first object is "it" */
304         (void) PluginManager::instance();
305
306         ProcessThread::init ();
307         /* the + 4 is a bit of a handwave. i don't actually know
308            how many more per-thread buffer sets we need above
309            the h/w concurrency, but its definitely > 1 more.
310         */
311         BufferManager::init (hardware_concurrency() + 4); 
312
313         PannerManager::instance().discover_panners();
314
315         // Initialize parameter metadata
316         EventTypeMap::instance().new_parameter(NullAutomation);
317         EventTypeMap::instance().new_parameter(GainAutomation);
318         EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
319         EventTypeMap::instance().new_parameter(PanElevationAutomation);
320         EventTypeMap::instance().new_parameter(PanWidthAutomation);
321         EventTypeMap::instance().new_parameter(PluginAutomation);
322         EventTypeMap::instance().new_parameter(SoloAutomation);
323         EventTypeMap::instance().new_parameter(MuteAutomation);
324         EventTypeMap::instance().new_parameter(MidiCCAutomation);
325         EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
326         EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
327         EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
328         EventTypeMap::instance().new_parameter(FadeInAutomation);
329         EventTypeMap::instance().new_parameter(FadeOutAutomation);
330         EventTypeMap::instance().new_parameter(EnvelopeAutomation);
331         EventTypeMap::instance().new_parameter(MidiCCAutomation);
332
333         libardour_initialized = true;
334
335         return true;
336 }
337
338 void
339 ARDOUR::init_post_engine ()
340 {
341         /* the MIDI Manager is needed by the ControlProtocolManager */
342         MIDI::Manager::create (AudioEngine::instance()->jack());
343
344         ControlProtocolManager::instance().discover_control_protocols ();
345
346         XMLNode* node;
347         if ((node = Config->control_protocol_state()) != 0) {
348                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
349         }
350
351         /* find plugins */
352
353         ARDOUR::PluginManager::instance().refresh ();
354 }
355
356 int
357 ARDOUR::cleanup ()
358 {
359         delete Library;
360         lrdf_cleanup ();
361         delete &ControlProtocolManager::instance();
362 #ifdef WINDOWS_VST_SUPPORT
363         fst_exit ();
364 #endif
365
366 #ifdef LXVST_SUPPORT
367         vstfx_exit();
368 #endif
369         PBD::cleanup ();
370         return 0;
371 }
372
373 void
374 ARDOUR::find_bindings_files (map<string,string>& files)
375 {
376         vector<std::string> found;
377         SearchPath spath = ardour_config_search_path();
378
379         if (getenv ("ARDOUR_SAE")) {
380                 Glib::PatternSpec pattern("*SAE-*.bindings");
381                 find_matching_files_in_search_path (spath, pattern, found);
382         } else {
383                 Glib::PatternSpec pattern("*.bindings");
384                 find_matching_files_in_search_path (spath, pattern, found);
385         }
386
387         if (found.empty()) {
388                 return;
389         }
390
391         for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
392                 std::string path(*x);
393                 pair<string,string> namepath;
394                 namepath.second = path;
395                 namepath.first = PBD::basename_nosuffix (path);
396                 files.insert (namepath);
397         }
398 }
399
400 bool
401 ARDOUR::no_auto_connect()
402 {
403         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
404 }
405
406 void
407 ARDOUR::setup_fpu ()
408 {
409
410         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
411                 // valgrind doesn't understand this assembler stuff
412                 // September 10th, 2007
413                 return;
414         }
415
416 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
417
418         int MXCSR;
419         FPU fpu;
420
421         /* XXX use real code to determine if the processor supports
422            DenormalsAreZero and FlushToZero
423         */
424
425         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
426                 return;
427         }
428
429         MXCSR  = _mm_getcsr();
430
431 #ifdef DEBUG_DENORMAL_EXCEPTION
432         /* This will raise a FP exception if a denormal is detected */
433         MXCSR &= ~_MM_MASK_DENORM;
434 #endif  
435
436         switch (Config->get_denormal_model()) {
437         case DenormalNone:
438                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
439                 break;
440
441         case DenormalFTZ:
442                 if (fpu.has_flush_to_zero()) {
443                         MXCSR |= _MM_FLUSH_ZERO_ON;
444                 }
445                 break;
446
447         case DenormalDAZ:
448                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
449                 if (fpu.has_denormals_are_zero()) {
450                         MXCSR |= 0x40;
451                 }
452                 break;
453
454         case DenormalFTZDAZ:
455                 if (fpu.has_flush_to_zero()) {
456                         if (fpu.has_denormals_are_zero()) {
457                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
458                         } else {
459                                 MXCSR |= _MM_FLUSH_ZERO_ON;
460                         }
461                 }
462                 break;
463         }
464
465         _mm_setcsr (MXCSR);
466
467 #endif
468 }
469
470 /* this can be changed to modify the translation behaviour for
471    cases where the user has never expressed a preference.
472 */
473 static const bool translate_by_default = true;
474
475 string
476 ARDOUR::translation_enable_path ()
477 {
478         return Glib::build_filename (user_config_directory(), ".translate");
479 }
480
481 bool
482 ARDOUR::translations_are_enabled ()
483 {
484         int fd = ::open (ARDOUR::translation_enable_path().c_str(), O_RDONLY);
485
486         if (fd < 0) {
487                 return translate_by_default;
488         }
489
490         char c;
491         bool ret = false;
492
493         if (::read (fd, &c, 1) == 1 && c == '1') {
494                 ret = true;
495         }
496
497         ::close (fd);
498
499         return ret;
500 }
501
502 bool
503 ARDOUR::set_translations_enabled (bool yn)
504 {
505         string i18n_enabler = ARDOUR::translation_enable_path();
506         int fd = ::open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
507
508         if (fd < 0) {
509                 return false;
510         }
511         
512         char c;
513         
514         if (yn) {
515                 c = '1';
516         } else {
517                 c = '0';
518         }
519         
520         ::write (fd, &c, 1);
521         ::close (fd);
522
523         return true;
524 }
525
526
527 vector<SyncSource>
528 ARDOUR::get_available_sync_options ()
529 {
530         vector<SyncSource> ret;
531
532         ret.push_back (JACK);
533         ret.push_back (MTC);
534         ret.push_back (MIDIClock);
535         ret.push_back (LTC);
536
537         return ret;
538 }