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