change PropertyChange from a bitfield into a real object, with all the many widesprea...
[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/control_protocol_manager.h"
68 #include "ardour/debug.h"
69 #include "ardour/filesystem_paths.h"
70 #include "ardour/mix.h"
71 #include "ardour/plugin_manager.h"
72 #include "ardour/profile.h"
73 #include "ardour/region.h"
74 #include "ardour/rc_configuration.h"
75 #include "ardour/route_group.h"
76 #include "ardour/runtime_functions.h"
77 #include "ardour/session.h"
78 #include "ardour/session_event.h"
79 #include "ardour/source_factory.h"
80 #include "ardour/utils.h"
81
82 #include "audiographer/routines.h"
83
84 #if defined (__APPLE__)
85        #include <Carbon/Carbon.h> // For Gestalt
86 #endif
87
88 #include "i18n.h"
89
90 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
91 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
92 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
93
94 using namespace ARDOUR;
95 using namespace std;
96 using namespace PBD;
97
98 uint64_t ARDOUR::debug_bits = 0x0;
99
100 MIDI::Port *ARDOUR::default_mmc_port = 0;
101 MIDI::Port *ARDOUR::default_mtc_port = 0;
102 MIDI::Port *ARDOUR::default_midi_port = 0;
103 MIDI::Port *ARDOUR::default_midi_clock_port = 0;
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 void ARDOUR::setup_enum_writer ();
114
115 /* this is useful for quite a few things that want to check
116    if any bounds-related property has changed
117 */
118 PBD::PropertyChange ARDOUR::bounds_change;
119
120 namespace ARDOUR { 
121         namespace Properties {
122
123                 /* the envelope and fades are not scalar items and so
124                    currently (2010/02) are not stored using Property.
125                    However, these descriptors enable us to notify
126                    about changes to them via PropertyChange. 
127
128                    Declared in ardour/audioregion.h ...
129                 */
130
131                 PBD::PropertyDescriptor<bool> fade_in;
132                 PBD::PropertyDescriptor<bool> fade_out;
133                 PBD::PropertyDescriptor<bool> envelope;
134         }
135 }
136
137 void
138 ARDOUR::make_property_quarks ()
139 {
140         Properties::fade_in.id = g_quark_from_static_string (X_("fade_in_FAKE"));
141         Properties::fade_out.id = g_quark_from_static_string (X_("fade_out_FAKE"));
142         Properties::envelope.id = g_quark_from_static_string (X_("envelope_FAKE"));
143 }
144
145 int
146 ARDOUR::setup_midi ()
147 {
148         if (Config->midi_ports.size() == 0) {
149                 return 0;
150         }
151
152         BootMessage (_("Configuring MIDI ports"));
153
154         for (std::map<string,XMLNode>::iterator i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) {
155                 MIDI::Manager::instance()->add_port (i->second);
156         }
157
158         MIDI::Port* first;
159         const MIDI::Manager::PortList& ports = MIDI::Manager::instance()->get_midi_ports();
160
161         if (ports.size() > 1) {
162
163                 first = ports.front();
164
165                 /* More than one port, so try using specific names for each port */
166
167                 default_mmc_port =  MIDI::Manager::instance()->port (Config->get_mmc_port_name());
168                 default_mtc_port =  MIDI::Manager::instance()->port (Config->get_mtc_port_name());
169                 default_midi_port =  MIDI::Manager::instance()->port (Config->get_midi_port_name());
170                 default_midi_clock_port =  MIDI::Manager::instance()->port (Config->get_midi_clock_port_name());
171
172                 /* If that didn't work, just use the first listed port */
173
174                 if (default_mmc_port == 0) {
175                         default_mmc_port = first;
176                 }
177
178                 if (default_mtc_port == 0) {
179                         default_mtc_port = first;
180                 }
181
182                 if (default_midi_port == 0) {
183                         default_midi_port = first;
184                 }
185
186                 if (default_midi_clock_port == 0) {
187                         default_midi_clock_port = first;
188                 }
189
190         } else if (ports.size() == 1) {
191
192                 first = ports.front();
193
194                 /* Only one port described, so use it for both MTC and MMC */
195
196                 default_mmc_port = first;
197                 default_mtc_port = default_mmc_port;
198                 default_midi_port = default_mmc_port;
199                 default_midi_clock_port = default_mmc_port;
200         }
201
202         if (default_mmc_port == 0) {
203                 warning << string_compose (_("No MMC control (MIDI port \"%1\" not available)"), Config->get_mmc_port_name())
204                         << endmsg;
205         }
206
207
208         if (default_mtc_port == 0) {
209                 warning << string_compose (_("No MTC support (MIDI port \"%1\" not available)"), Config->get_mtc_port_name())
210                         << endmsg;
211         }
212
213         if (default_midi_port == 0) {
214                 warning << string_compose (_("No MIDI parameter support (MIDI port \"%1\" not available)"), Config->get_midi_port_name())
215                         << endmsg;
216         }
217
218         if (default_midi_clock_port == 0) {
219                 warning << string_compose (_("No MIDI Clock support (MIDI port \"%1\" not available)"), Config->get_midi_clock_port_name())
220                         << endmsg;
221         }
222
223         return 0;
224 }
225
226 void
227 setup_hardware_optimization (bool try_optimization)
228 {
229         bool generic_mix_functions = true;
230
231         if (try_optimization) {
232
233                 FPU fpu;
234
235 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
236
237                 if (fpu.has_sse()) {
238
239                         info << "Using SSE optimized routines" << endmsg;
240
241                         // SSE SET
242                         compute_peak          = x86_sse_compute_peak;
243                         find_peaks            = x86_sse_find_peaks;
244                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
245                         mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
246                         mix_buffers_no_gain   = x86_sse_mix_buffers_no_gain;
247
248                         generic_mix_functions = false;
249
250                 }
251
252 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
253                 long sysVersion = 0;
254
255                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
256                         sysVersion = 0;
257
258                 if (sysVersion >= 0x00001040) { // Tiger at least
259                         compute_peak           = veclib_compute_peak;
260                         find_peaks             = veclib_find_peaks;
261                         apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
262                         mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
263                         mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
264
265                         generic_mix_functions = false;
266
267                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
268                 }
269 #endif
270
271                 /* consider FPU denormal handling to be "h/w optimization" */
272
273                 setup_fpu ();
274         }
275
276         if (generic_mix_functions) {
277
278                 compute_peak          = default_compute_peak;
279                 find_peaks            = default_find_peaks;
280                 apply_gain_to_buffer  = default_apply_gain_to_buffer;
281                 mix_buffers_with_gain = default_mix_buffers_with_gain;
282                 mix_buffers_no_gain   = default_mix_buffers_no_gain;
283
284                 info << "No H/W specific optimizations in use" << endmsg;
285         }
286         
287         AudioGrapher::Routines::override_compute_peak (compute_peak);
288         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
289 }
290
291 static void
292 lotsa_files_please ()
293 {
294         struct rlimit rl;
295
296         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
297
298                 rl.rlim_cur = rl.rlim_max;
299
300                 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
301                         if (rl.rlim_cur == RLIM_INFINITY) {
302                                 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
303                         } else {
304                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
305                         }
306                 } else {
307                         if (rl.rlim_cur == RLIM_INFINITY) {
308                                 info << _("Removed open file count limit. Excellent!") << endmsg;
309                         } else {
310                                 info << string_compose (_("Ardour will be limited to %1 open files"), rl.rlim_cur) << endmsg;
311                         }
312                 }
313         } else {
314                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
315         }
316 }
317
318 int
319 ARDOUR::init (bool use_vst, bool try_optimization)
320 {
321         if (!Glib::thread_supported()) {
322                 Glib::thread_init();
323         }
324
325         (void) bindtextdomain(PACKAGE, LOCALEDIR);
326
327         PBD::ID::init ();
328         SessionEvent::init_event_pool ();
329         
330         make_property_quarks ();
331         SessionObject::make_property_quarks ();
332         Region::make_property_quarks ();
333         AudioRegion::make_property_quarks ();
334         RouteGroup::make_property_quarks ();
335
336         /* this is a useful ready to use PropertyChange that many
337            things need to check. This avoids having to compose
338            it every time we want to check for any of the relevant
339            property changes.
340         */
341
342         bounds_change.add (ARDOUR::Properties::start);
343         bounds_change.add (ARDOUR::Properties::position);
344         bounds_change.add (ARDOUR::Properties::length);
345
346         /* provide a state version for the few cases that need it and are not
347            driven by reading state from disk (e.g. undo/redo)
348         */
349
350         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
351
352         setup_enum_writer ();
353
354         // allow ardour the absolute maximum number of open files
355         lotsa_files_please ();
356
357         lrdf_init();
358         Library = new AudioLibrary;
359
360         BootMessage (_("Loading configuration"));
361
362         Config = new RCConfiguration;
363
364         if (Config->load_state ()) {
365                 return -1;
366         }
367
368         
369         Config->set_use_vst (use_vst);
370
371         cerr << "After config loaded, MTC port name = " << Config->get_mtc_port_name() << endl;
372
373         Profile = new RuntimeProfile;
374
375
376 #ifdef VST_SUPPORT
377         if (Config->get_use_vst() && fst_init (0)) {
378                 return -1;
379         }
380 #endif
381
382 #ifdef HAVE_AUDIOUNITS
383         AUPluginInfo::load_cached_info ();
384 #endif
385
386         /* Make VAMP look in our library ahead of anything else */
387
388         char *p = getenv ("VAMP_PATH");
389         string vamppath = VAMP_DIR;
390         if (p) {
391                 vamppath += ':';
392                 vamppath += p;
393         }
394         setenv ("VAMP_PATH", vamppath.c_str(), 1);
395
396
397         setup_hardware_optimization (try_optimization);
398
399         SourceFactory::init ();
400         Analyser::init ();
401
402         /* singleton - first object is "it" */
403         new PluginManager ();
404
405         return 0;
406 }
407
408 void
409 ARDOUR::init_post_engine ()
410 {
411         ControlProtocolManager::instance().discover_control_protocols ();
412
413         XMLNode* node;
414         if ((node = Config->control_protocol_state()) != 0) {
415                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
416         }
417 }
418
419 int
420 ARDOUR::cleanup ()
421 {
422         delete Library;
423         lrdf_cleanup ();
424         delete &ControlProtocolManager::instance();
425 #ifdef VST_SUPPORT
426         fst_exit ();
427 #endif
428         return 0;
429 }
430
431 string
432 ARDOUR::get_ardour_revision ()
433 {
434         return "$Rev$";
435 }
436
437 void
438 ARDOUR::find_bindings_files (map<string,string>& files)
439 {
440         vector<sys::path> found;
441         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
442
443         if (getenv ("ARDOUR_SAE")) {
444                 Glib::PatternSpec pattern("*SAE-*.bindings");
445                 find_matching_files_in_search_path (spath, pattern, found);
446         } else {
447                 Glib::PatternSpec pattern("*.bindings");
448                 find_matching_files_in_search_path (spath, pattern, found);
449         }
450
451         if (found.empty()) {
452                 return;
453         }
454
455         for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
456                 sys::path path = *x;
457                 pair<string,string> namepath;
458                 namepath.second = path.to_string();
459                 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
460                 files.insert (namepath);
461         }
462 }
463
464 bool
465 ARDOUR::no_auto_connect()
466 {
467         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
468 }
469
470 void
471 ARDOUR::setup_fpu ()
472 {
473
474         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
475                 // valgrind doesn't understand this assembler stuff
476                 // September 10th, 2007
477                 return;
478         }
479
480 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
481
482         int MXCSR;
483         FPU fpu;
484
485         /* XXX use real code to determine if the processor supports
486            DenormalsAreZero and FlushToZero
487         */
488
489         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
490                 return;
491         }
492
493         MXCSR  = _mm_getcsr();
494
495         switch (Config->get_denormal_model()) {
496         case DenormalNone:
497                 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
498                 break;
499
500         case DenormalFTZ:
501                 if (fpu.has_flush_to_zero()) {
502                         MXCSR |= _MM_FLUSH_ZERO_ON;
503                 }
504                 break;
505
506         case DenormalDAZ:
507                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
508                 if (fpu.has_denormals_are_zero()) {
509                         MXCSR |= 0x8000;
510                 }
511                 break;
512
513         case DenormalFTZDAZ:
514                 if (fpu.has_flush_to_zero()) {
515                         if (fpu.has_denormals_are_zero()) {
516                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
517                         } else {
518                                 MXCSR |= _MM_FLUSH_ZERO_ON;
519                         }
520                 }
521                 break;
522         }
523
524         _mm_setcsr (MXCSR);
525
526 #endif
527 }
528
529 ARDOUR::OverlapType
530 ARDOUR::coverage (nframes_t sa, nframes_t ea,
531                   nframes_t sb, nframes_t eb)
532 {
533         /* OverlapType returned reflects how the second (B)
534            range overlaps the first (A).
535
536            The diagrams show various relative placements
537            of A and B for each OverlapType.
538
539            Notes:
540               Internal: the start points cannot coincide
541               External: the start and end points can coincide
542               Start: end points can coincide
543               End: start points can coincide
544
545            XXX Logically, Internal should disallow end
546            point equality.
547         */
548
549         /*
550              |--------------------|   A
551                   |------|            B
552                 |-----------------|   B
553
554
555              "B is internal to A"
556
557         */
558 #ifdef OLD_COVERAGE
559         if ((sb >= sa) && (eb <= ea)) {
560 #else
561         if ((sb > sa) && (eb <= ea)) {
562 #endif
563                 return OverlapInternal;
564         }
565
566         /*
567              |--------------------|   A
568            ----|                      B
569            -----------------------|   B
570            --|                        B
571
572              "B overlaps the start of A"
573
574         */
575
576         if ((eb >= sa) && (eb <= ea)) {
577                 return OverlapStart;
578         }
579         /*
580              |---------------------|  A
581                    |----------------- B
582              |----------------------- B
583                                    |- B
584
585             "B overlaps the end of A"
586
587         */
588         if ((sb > sa) && (sb <= ea)) {
589                 return OverlapEnd;
590         }
591         /*
592              |--------------------|     A
593            --------------------------  B
594              |-----------------------  B
595             ----------------------|    B
596              |--------------------|    B
597
598
599            "B overlaps all of A"
600         */
601         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
602                 return OverlapExternal;
603         }
604
605         return OverlapNone;
606 }
607