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