add note IDs and use them for looking up notes during a history rebuild. NOTE: INVALI...
[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
20 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
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 VST_SUPPORT
34 #include <fst.h>
35 #endif
36
37 #ifdef HAVE_AUDIOUNITS
38 #include "ardour/audio_unit.h"
39 #endif
40
41 #ifdef __SSE__
42 #include <xmmintrin.h>
43 #endif
44
45 #include <glibmm/fileutils.h>
46 #include <glibmm/miscutils.h>
47
48 #include <lrdf.h>
49
50 #include "pbd/error.h"
51 #include "pbd/id.h"
52 #include "pbd/strsplit.h"
53 #include "pbd/fpu.h"
54 #include "pbd/file_utils.h"
55 #include "pbd/enumwriter.h"
56
57 #include "midi++/port.h"
58 #include "midi++/manager.h"
59 #include "midi++/mmc.h"
60
61 #include "ardour/analyser.h"
62 #include "ardour/ardour.h"
63 #include "ardour/audio_library.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/audioregion.h"
66 #include "ardour/audiosource.h"
67 #include "ardour/buffer_manager.h"
68 #include "ardour/control_protocol_manager.h"
69 #include "ardour/debug.h"
70 #include "ardour/filesystem_paths.h"
71 #include "ardour/mix.h"
72 #include "ardour/playlist.h"
73 #include "ardour/plugin_manager.h"
74 #include "ardour/process_thread.h"
75 #include "ardour/profile.h"
76 #include "ardour/region.h"
77 #include "ardour/rc_configuration.h"
78 #include "ardour/route_group.h"
79 #include "ardour/runtime_functions.h"
80 #include "ardour/session.h"
81 #include "ardour/session_event.h"
82 #include "ardour/source_factory.h"
83 #include "ardour/utils.h"
84
85 #include "audiographer/routines.h"
86
87 #if defined (__APPLE__)
88        #include <Carbon/Carbon.h> // For Gestalt
89 #endif
90
91 #include "i18n.h"
92
93 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
94 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
95 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
96
97 using namespace ARDOUR;
98 using namespace std;
99 using namespace PBD;
100
101 compute_peak_t          ARDOUR::compute_peak = 0;
102 find_peaks_t            ARDOUR::find_peaks = 0;
103 apply_gain_to_buffer_t  ARDOUR::apply_gain_to_buffer = 0;
104 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
105 mix_buffers_no_gain_t   ARDOUR::mix_buffers_no_gain = 0;
106
107 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
108
109 void ARDOUR::setup_enum_writer ();
110
111 /* this is useful for quite a few things that want to check
112    if any bounds-related property has changed
113 */
114 PBD::PropertyChange ARDOUR::bounds_change;
115
116 namespace ARDOUR { 
117         namespace Properties {
118
119                 /* the envelope and fades are not scalar items and so
120                    currently (2010/02) are not stored using Property.
121                    However, these descriptors enable us to notify
122                    about changes to them via PropertyChange. 
123
124                    Declared in ardour/audioregion.h ...
125                 */
126
127                 PBD::PropertyDescriptor<bool> fade_in;
128                 PBD::PropertyDescriptor<bool> fade_out;
129                 PBD::PropertyDescriptor<bool> envelope;
130         }
131 }
132
133 void
134 ARDOUR::make_property_quarks ()
135 {
136         Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
137         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n",        Properties::fade_in.property_id));
138         Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
139         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n",       Properties::fade_out.property_id));
140         Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
141         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n",       Properties::envelope.property_id));
142 }
143
144 void
145 setup_hardware_optimization (bool try_optimization)
146 {
147         bool generic_mix_functions = true;
148
149         if (try_optimization) {
150
151                 FPU fpu;
152
153 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
154
155                 if (fpu.has_sse()) {
156
157                         info << "Using SSE optimized routines" << endmsg;
158
159                         // SSE SET
160                         compute_peak          = x86_sse_compute_peak;
161                         find_peaks            = x86_sse_find_peaks;
162                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
163                         mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
164                         mix_buffers_no_gain   = x86_sse_mix_buffers_no_gain;
165
166                         generic_mix_functions = false;
167
168                 }
169
170 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
171                 long sysVersion = 0;
172
173                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
174                         sysVersion = 0;
175
176                 if (sysVersion >= 0x00001040) { // Tiger at least
177                         compute_peak           = veclib_compute_peak;
178                         find_peaks             = veclib_find_peaks;
179                         apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
180                         mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
181                         mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
182
183                         generic_mix_functions = false;
184
185                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
186                 }
187 #endif
188
189                 /* consider FPU denormal handling to be "h/w optimization" */
190
191                 setup_fpu ();
192         }
193
194         if (generic_mix_functions) {
195
196                 compute_peak          = default_compute_peak;
197                 find_peaks            = default_find_peaks;
198                 apply_gain_to_buffer  = default_apply_gain_to_buffer;
199                 mix_buffers_with_gain = default_mix_buffers_with_gain;
200                 mix_buffers_no_gain   = default_mix_buffers_no_gain;
201
202                 info << "No H/W specific optimizations in use" << endmsg;
203         }
204         
205         AudioGrapher::Routines::override_compute_peak (compute_peak);
206         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
207 }
208
209 static void
210 lotsa_files_please ()
211 {
212         struct rlimit rl;
213
214         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
215
216                 rl.rlim_cur = rl.rlim_max;
217
218                 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
219                         if (rl.rlim_cur == RLIM_INFINITY) {
220                                 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
221                         } else {
222                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
223                         }
224                 } else {
225                         if (rl.rlim_cur == RLIM_INFINITY) {
226                                 info << _("Removed open file count limit. Excellent!") << endmsg;
227                         } else {
228                                 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
229                         }
230                 }
231         } else {
232                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
233         }
234 }
235
236 int
237 ARDOUR::init (bool use_vst, bool try_optimization)
238 {
239         if (!Glib::thread_supported()) {
240                 Glib::thread_init();
241         }
242
243         (void) bindtextdomain(PACKAGE, LOCALEDIR);
244
245         PBD::ID::init ();
246         SessionEvent::init_event_pool ();
247         
248         make_property_quarks ();
249         SessionObject::make_property_quarks ();
250         Region::make_property_quarks ();
251         AudioRegion::make_property_quarks ();
252         RouteGroup::make_property_quarks ();
253         Playlist::make_property_quarks ();
254
255         /* this is a useful ready to use PropertyChange that many
256            things need to check. This avoids having to compose
257            it every time we want to check for any of the relevant
258            property changes.
259         */
260
261         bounds_change.add (ARDOUR::Properties::start);
262         bounds_change.add (ARDOUR::Properties::position);
263         bounds_change.add (ARDOUR::Properties::length);
264
265         /* provide a state version for the few cases that need it and are not
266            driven by reading state from disk (e.g. undo/redo)
267         */
268
269         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
270
271         setup_enum_writer ();
272
273         // allow ardour the absolute maximum number of open files
274         lotsa_files_please ();
275
276         lrdf_init();
277         Library = new AudioLibrary;
278
279         BootMessage (_("Loading configuration"));
280
281         Config = new RCConfiguration;
282
283         if (Config->load_state ()) {
284                 return -1;
285         }
286         
287         Config->set_use_vst (use_vst);
288
289         Profile = new RuntimeProfile;
290
291
292 #ifdef VST_SUPPORT
293         if (Config->get_use_vst() && fst_init (0)) {
294                 return -1;
295         }
296 #endif
297
298 #ifdef HAVE_AUDIOUNITS
299         AUPluginInfo::load_cached_info ();
300 #endif
301
302         /* Make VAMP look in our library ahead of anything else */
303
304         char *p = getenv ("VAMP_PATH");
305         string vamppath = VAMP_DIR;
306         if (p) {
307                 vamppath += ':';
308                 vamppath += p;
309         }
310         setenv ("VAMP_PATH", vamppath.c_str(), 1);
311
312
313         setup_hardware_optimization (try_optimization);
314
315         SourceFactory::init ();
316         Analyser::init ();
317
318         /* singleton - first object is "it" */
319         new PluginManager ();
320
321         ProcessThread::init ();
322         BufferManager::init (10); // XX should be num_processors_for_dsp
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         MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
341 }
342
343 int
344 ARDOUR::cleanup ()
345 {
346         delete Library;
347         lrdf_cleanup ();
348         delete &ControlProtocolManager::instance();
349 #ifdef VST_SUPPORT
350         fst_exit ();
351 #endif
352         return 0;
353 }
354
355 string
356 ARDOUR::get_ardour_revision ()
357 {
358         return "$Rev$";
359 }
360
361 void
362 ARDOUR::find_bindings_files (map<string,string>& files)
363 {
364         vector<sys::path> found;
365         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
366
367         if (getenv ("ARDOUR_SAE")) {
368                 Glib::PatternSpec pattern("*SAE-*.bindings");
369                 find_matching_files_in_search_path (spath, pattern, found);
370         } else {
371                 Glib::PatternSpec pattern("*.bindings");
372                 find_matching_files_in_search_path (spath, pattern, found);
373         }
374
375         if (found.empty()) {
376                 return;
377         }
378
379         for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
380                 sys::path path = *x;
381                 pair<string,string> namepath;
382                 namepath.second = path.to_string();
383                 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
384                 files.insert (namepath);
385         }
386 }
387
388 bool
389 ARDOUR::no_auto_connect()
390 {
391         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
392 }
393
394 void
395 ARDOUR::setup_fpu ()
396 {
397
398         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
399                 // valgrind doesn't understand this assembler stuff
400                 // September 10th, 2007
401                 return;
402         }
403
404 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
405
406         int MXCSR;
407         FPU fpu;
408
409         /* XXX use real code to determine if the processor supports
410            DenormalsAreZero and FlushToZero
411         */
412
413         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
414                 return;
415         }
416
417         MXCSR  = _mm_getcsr();
418
419         switch (Config->get_denormal_model()) {
420         case DenormalNone:
421                 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
422                 break;
423
424         case DenormalFTZ:
425                 if (fpu.has_flush_to_zero()) {
426                         MXCSR |= _MM_FLUSH_ZERO_ON;
427                 }
428                 break;
429
430         case DenormalDAZ:
431                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
432                 if (fpu.has_denormals_are_zero()) {
433                         MXCSR |= 0x8000;
434                 }
435                 break;
436
437         case DenormalFTZDAZ:
438                 if (fpu.has_flush_to_zero()) {
439                         if (fpu.has_denormals_are_zero()) {
440                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
441                         } else {
442                                 MXCSR |= _MM_FLUSH_ZERO_ON;
443                         }
444                 }
445                 break;
446         }
447
448         _mm_setcsr (MXCSR);
449
450 #endif
451 }
452
453 ARDOUR::OverlapType
454 ARDOUR::coverage (framepos_t sa, framepos_t ea,
455                   framepos_t sb, framepos_t eb)
456 {
457         /* OverlapType returned reflects how the second (B)
458            range overlaps the first (A).
459
460            The diagrams show various relative placements
461            of A and B for each OverlapType.
462
463            Notes:
464               Internal: the start points cannot coincide
465               External: the start and end points can coincide
466               Start: end points can coincide
467               End: start points can coincide
468
469            XXX Logically, Internal should disallow end
470            point equality.
471         */
472
473         /*
474              |--------------------|   A
475                   |------|            B
476                 |-----------------|   B
477
478
479              "B is internal to A"
480
481         */
482
483         if ((sb > sa) && (eb <= ea)) {
484                 return OverlapInternal;
485         }
486
487         /*
488              |--------------------|   A
489            ----|                      B
490            -----------------------|   B
491            --|                        B
492
493              "B overlaps the start of A"
494
495         */
496
497         if ((eb >= sa) && (eb <= ea)) {
498                 return OverlapStart;
499         }
500         /*
501              |---------------------|  A
502                    |----------------- B
503              |----------------------- B
504                                    |- B
505
506             "B overlaps the end of A"
507
508         */
509         if ((sb > sa) && (sb <= ea)) {
510                 return OverlapEnd;
511         }
512         /*
513              |--------------------|     A
514            --------------------------  B
515              |-----------------------  B
516             ----------------------|    B
517              |--------------------|    B
518
519
520            "B overlaps all of A"
521         */
522         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
523                 return OverlapExternal;
524         }
525
526         return OverlapNone;
527 }
528