more work on RID and editor/mixer order matching; when a track/bus is hidden in the...
[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/cpus.h"
56 #include "pbd/error.h"
57 #include "pbd/id.h"
58 #include "pbd/strsplit.h"
59 #include "pbd/fpu.h"
60 #include "pbd/file_utils.h"
61 #include "pbd/enumwriter.h"
62 #include "pbd/basename.h"
63
64 #include "midi++/port.h"
65 #include "midi++/manager.h"
66 #include "midi++/mmc.h"
67
68 #include "ardour/analyser.h"
69 #include "ardour/audio_library.h"
70 #include "ardour/audioengine.h"
71 #include "ardour/audioplaylist.h"
72 #include "ardour/audioregion.h"
73 #include "ardour/buffer_manager.h"
74 #include "ardour/control_protocol_manager.h"
75 #include "ardour/filesystem_paths.h"
76 #include "ardour/midi_region.h"
77 #include "ardour/mix.h"
78 #include "ardour/panner_manager.h"
79 #include "ardour/plugin_manager.h"
80 #include "ardour/process_thread.h"
81 #include "ardour/profile.h"
82 #include "ardour/rc_configuration.h"
83 #include "ardour/region.h"
84 #include "ardour/route_group.h"
85 #include "ardour/runtime_functions.h"
86 #include "ardour/session_event.h"
87 #include "ardour/source_factory.h"
88
89 #include "audiographer/routines.h"
90
91 #if defined (__APPLE__)
92        #include <Carbon/Carbon.h> // For Gestalt
93 #endif
94
95 #include "i18n.h"
96
97 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
98 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
99 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
100
101 using namespace ARDOUR;
102 using namespace std;
103 using namespace PBD;
104
105 compute_peak_t          ARDOUR::compute_peak = 0;
106 find_peaks_t            ARDOUR::find_peaks = 0;
107 apply_gain_to_buffer_t  ARDOUR::apply_gain_to_buffer = 0;
108 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
109 mix_buffers_no_gain_t   ARDOUR::mix_buffers_no_gain = 0;
110
111 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
112
113 namespace ARDOUR {
114 extern void setup_enum_writer ();
115 }
116
117 /* this is useful for quite a few things that want to check
118    if any bounds-related property has changed
119 */
120 PBD::PropertyChange ARDOUR::bounds_change;
121
122 void
123 setup_hardware_optimization (bool try_optimization)
124 {
125         bool generic_mix_functions = true;
126
127         if (try_optimization) {
128
129                 FPU fpu;
130
131 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
132
133                 if (fpu.has_sse()) {
134
135                         info << "Using SSE optimized routines" << endmsg;
136
137                         // SSE SET
138                         compute_peak          = x86_sse_compute_peak;
139                         find_peaks            = x86_sse_find_peaks;
140                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
141                         mix_buffers_with_gain = x86_sse_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         /* the + 4 is a bit of a handwave. i don't actually know
303            how many more per-thread buffer sets we need above
304            the h/w concurrency, but its definitely > 1 more.
305         */
306         BufferManager::init (hardware_concurrency() + 4); 
307
308         PannerManager::instance().discover_panners();
309
310         // Initialize parameter metadata
311         EventTypeMap::instance().new_parameter(NullAutomation);
312         EventTypeMap::instance().new_parameter(GainAutomation);
313         EventTypeMap::instance().new_parameter(PanAzimuthAutomation);
314         EventTypeMap::instance().new_parameter(PanElevationAutomation);
315         EventTypeMap::instance().new_parameter(PanWidthAutomation);
316         EventTypeMap::instance().new_parameter(PluginAutomation);
317         EventTypeMap::instance().new_parameter(SoloAutomation);
318         EventTypeMap::instance().new_parameter(MuteAutomation);
319         EventTypeMap::instance().new_parameter(MidiCCAutomation);
320         EventTypeMap::instance().new_parameter(MidiPgmChangeAutomation);
321         EventTypeMap::instance().new_parameter(MidiPitchBenderAutomation);
322         EventTypeMap::instance().new_parameter(MidiChannelPressureAutomation);
323         EventTypeMap::instance().new_parameter(FadeInAutomation);
324         EventTypeMap::instance().new_parameter(FadeOutAutomation);
325         EventTypeMap::instance().new_parameter(EnvelopeAutomation);
326         EventTypeMap::instance().new_parameter(MidiCCAutomation);
327
328         return 0;
329 }
330
331 void
332 ARDOUR::init_post_engine ()
333 {
334         /* the MIDI Manager is needed by the ControlProtocolManager */
335         MIDI::Manager::create (AudioEngine::instance()->jack());
336
337         ControlProtocolManager::instance().discover_control_protocols ();
338
339         XMLNode* node;
340         if ((node = Config->control_protocol_state()) != 0) {
341                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
342         }
343
344         /* find plugins */
345
346         ARDOUR::PluginManager::instance().refresh ();
347 }
348
349 int
350 ARDOUR::cleanup ()
351 {
352         delete Library;
353         lrdf_cleanup ();
354         delete &ControlProtocolManager::instance();
355 #ifdef WINDOWS_VST_SUPPORT
356         fst_exit ();
357 #endif
358
359 #ifdef LXVST_SUPPORT
360         vstfx_exit();
361 #endif
362         EnumWriter::destroy ();
363         return 0;
364 }
365
366 void
367 ARDOUR::find_bindings_files (map<string,string>& files)
368 {
369         vector<std::string> found;
370         SearchPath spath = ardour_config_search_path();
371
372         if (getenv ("ARDOUR_SAE")) {
373                 Glib::PatternSpec pattern("*SAE-*.bindings");
374                 find_matching_files_in_search_path (spath, pattern, found);
375         } else {
376                 Glib::PatternSpec pattern("*.bindings");
377                 find_matching_files_in_search_path (spath, pattern, found);
378         }
379
380         if (found.empty()) {
381                 return;
382         }
383
384         for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
385                 std::string path(*x);
386                 pair<string,string> namepath;
387                 namepath.second = path;
388                 namepath.first = PBD::basename_nosuffix (path);
389                 files.insert (namepath);
390         }
391 }
392
393 bool
394 ARDOUR::no_auto_connect()
395 {
396         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
397 }
398
399 void
400 ARDOUR::setup_fpu ()
401 {
402
403         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
404                 // valgrind doesn't understand this assembler stuff
405                 // September 10th, 2007
406                 return;
407         }
408
409 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
410
411         int MXCSR;
412         FPU fpu;
413
414         /* XXX use real code to determine if the processor supports
415            DenormalsAreZero and FlushToZero
416         */
417
418         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
419                 return;
420         }
421
422         MXCSR  = _mm_getcsr();
423
424 #ifdef DEBUG_DENORMAL_EXCEPTION
425         /* This will raise a FP exception if a denormal is detected */
426         MXCSR &= ~_MM_MASK_DENORM;
427 #endif  
428
429         switch (Config->get_denormal_model()) {
430         case DenormalNone:
431                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
432                 break;
433
434         case DenormalFTZ:
435                 if (fpu.has_flush_to_zero()) {
436                         MXCSR |= _MM_FLUSH_ZERO_ON;
437                 }
438                 break;
439
440         case DenormalDAZ:
441                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
442                 if (fpu.has_denormals_are_zero()) {
443                         MXCSR |= 0x40;
444                 }
445                 break;
446
447         case DenormalFTZDAZ:
448                 if (fpu.has_flush_to_zero()) {
449                         if (fpu.has_denormals_are_zero()) {
450                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
451                         } else {
452                                 MXCSR |= _MM_FLUSH_ZERO_ON;
453                         }
454                 }
455                 break;
456         }
457
458         _mm_setcsr (MXCSR);
459
460 #endif
461 }
462
463 string
464 ARDOUR::translation_kill_path ()
465 {
466         return Glib::build_filename (user_config_directory(), ".love_is_the_language_of_audio");
467 }
468
469 bool
470 ARDOUR::translations_are_disabled ()
471 {
472         /* if file does not exist, we don't translate (bundled ardour only) */
473         return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;
474 }