Move MIDI control port ownership into the MIDI Manager, since control port state...
[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         
288         Config->set_use_vst (use_vst);
289
290         Profile = new RuntimeProfile;
291
292
293 #ifdef VST_SUPPORT
294         if (Config->get_use_vst() && fst_init (0)) {
295                 return -1;
296         }
297 #endif
298
299 #ifdef HAVE_AUDIOUNITS
300         AUPluginInfo::load_cached_info ();
301 #endif
302
303         /* Make VAMP look in our library ahead of anything else */
304
305         char *p = getenv ("VAMP_PATH");
306         string vamppath = VAMP_DIR;
307         if (p) {
308                 vamppath += ':';
309                 vamppath += p;
310         }
311         setenv ("VAMP_PATH", vamppath.c_str(), 1);
312
313
314         setup_hardware_optimization (try_optimization);
315
316         SourceFactory::init ();
317         Analyser::init ();
318
319         /* singleton - first object is "it" */
320         new PluginManager ();
321
322         ProcessThread::init ();
323         BufferManager::init (10); // XX should be num_processors_for_dsp
324
325         return 0;
326 }
327
328 void
329 ARDOUR::init_post_engine ()
330 {
331         /* the MIDI Manager is needed by the ControlProtocolManager */
332         MIDI::Manager::create (AudioEngine::instance()->jack());
333
334         ControlProtocolManager::instance().discover_control_protocols ();
335
336         XMLNode* node;
337         if ((node = Config->control_protocol_state()) != 0) {
338                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
339         }
340
341         MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
342 }
343
344 int
345 ARDOUR::cleanup ()
346 {
347         delete Library;
348         lrdf_cleanup ();
349         delete &ControlProtocolManager::instance();
350 #ifdef VST_SUPPORT
351         fst_exit ();
352 #endif
353         return 0;
354 }
355
356 string
357 ARDOUR::get_ardour_revision ()
358 {
359         return "$Rev$";
360 }
361
362 void
363 ARDOUR::find_bindings_files (map<string,string>& files)
364 {
365         vector<sys::path> found;
366         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
367
368         if (getenv ("ARDOUR_SAE")) {
369                 Glib::PatternSpec pattern("*SAE-*.bindings");
370                 find_matching_files_in_search_path (spath, pattern, found);
371         } else {
372                 Glib::PatternSpec pattern("*.bindings");
373                 find_matching_files_in_search_path (spath, pattern, found);
374         }
375
376         if (found.empty()) {
377                 return;
378         }
379
380         for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
381                 sys::path path = *x;
382                 pair<string,string> namepath;
383                 namepath.second = path.to_string();
384                 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
385                 files.insert (namepath);
386         }
387 }
388
389 bool
390 ARDOUR::no_auto_connect()
391 {
392         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
393 }
394
395 void
396 ARDOUR::setup_fpu ()
397 {
398
399         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
400                 // valgrind doesn't understand this assembler stuff
401                 // September 10th, 2007
402                 return;
403         }
404
405 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
406
407         int MXCSR;
408         FPU fpu;
409
410         /* XXX use real code to determine if the processor supports
411            DenormalsAreZero and FlushToZero
412         */
413
414         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
415                 return;
416         }
417
418         MXCSR  = _mm_getcsr();
419
420         switch (Config->get_denormal_model()) {
421         case DenormalNone:
422                 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
423                 break;
424
425         case DenormalFTZ:
426                 if (fpu.has_flush_to_zero()) {
427                         MXCSR |= _MM_FLUSH_ZERO_ON;
428                 }
429                 break;
430
431         case DenormalDAZ:
432                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
433                 if (fpu.has_denormals_are_zero()) {
434                         MXCSR |= 0x8000;
435                 }
436                 break;
437
438         case DenormalFTZDAZ:
439                 if (fpu.has_flush_to_zero()) {
440                         if (fpu.has_denormals_are_zero()) {
441                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
442                         } else {
443                                 MXCSR |= _MM_FLUSH_ZERO_ON;
444                         }
445                 }
446                 break;
447         }
448
449         _mm_setcsr (MXCSR);
450
451 #endif
452 }
453
454 ARDOUR::OverlapType
455 ARDOUR::coverage (framepos_t sa, framepos_t ea,
456                   framepos_t sb, framepos_t eb)
457 {
458         /* OverlapType returned reflects how the second (B)
459            range overlaps the first (A).
460
461            The diagrams show various relative placements
462            of A and B for each OverlapType.
463
464            Notes:
465               Internal: the start points cannot coincide
466               External: the start and end points can coincide
467               Start: end points can coincide
468               End: start points can coincide
469
470            XXX Logically, Internal should disallow end
471            point equality.
472         */
473
474         /*
475              |--------------------|   A
476                   |------|            B
477                 |-----------------|   B
478
479
480              "B is internal to A"
481
482         */
483
484         if ((sb > sa) && (eb <= ea)) {
485                 return OverlapInternal;
486         }
487
488         /*
489              |--------------------|   A
490            ----|                      B
491            -----------------------|   B
492            --|                        B
493
494              "B overlaps the start of A"
495
496         */
497
498         if ((eb >= sa) && (eb <= ea)) {
499                 return OverlapStart;
500         }
501         /*
502              |---------------------|  A
503                    |----------------- B
504              |----------------------- B
505                                    |- B
506
507             "B overlaps the end of A"
508
509         */
510         if ((sb > sa) && (sb <= ea)) {
511                 return OverlapEnd;
512         }
513         /*
514              |--------------------|     A
515            --------------------------  B
516              |-----------------------  B
517             ----------------------|    B
518              |--------------------|    B
519
520
521            "B overlaps all of A"
522         */
523         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
524                 return OverlapExternal;
525         }
526
527         return OverlapNone;
528 }
529