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