Fix restoration of connections to control surface ports.
[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 #ifdef WAF_BUILD
20 #include "libardour-config.h"
21 #endif
22
23 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <sys/resource.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <errno.h>
31
32 #ifdef VST_SUPPORT
33 #include <fst.h>
34 #endif
35
36 #ifdef HAVE_AUDIOUNITS
37 #include "ardour/audio_unit.h"
38 #endif
39
40 #ifdef __SSE__
41 #include <xmmintrin.h>
42 #endif
43
44 #include <glibmm/fileutils.h>
45 #include <glibmm/miscutils.h>
46
47 #include <lrdf.h>
48
49 #include "pbd/error.h"
50 #include "pbd/id.h"
51 #include "pbd/strsplit.h"
52 #include "pbd/fpu.h"
53 #include "pbd/file_utils.h"
54 #include "pbd/enumwriter.h"
55
56 #include "midi++/port.h"
57 #include "midi++/manager.h"
58 #include "midi++/mmc.h"
59
60 #include "ardour/analyser.h"
61 #include "ardour/ardour.h"
62 #include "ardour/audio_library.h"
63 #include "ardour/audioengine.h"
64 #include "ardour/audioregion.h"
65 #include "ardour/audiosource.h"
66 #include "ardour/buffer_manager.h"
67 #include "ardour/control_protocol_manager.h"
68 #include "ardour/debug.h"
69 #include "ardour/filesystem_paths.h"
70 #include "ardour/midi_region.h"
71 #include "ardour/mix.h"
72 #include "ardour/audioplaylist.h"
73 #include "ardour/panner_manager.h"
74 #include "ardour/plugin_manager.h"
75 #include "ardour/process_thread.h"
76 #include "ardour/profile.h"
77 #include "ardour/region.h"
78 #include "ardour/rc_configuration.h"
79 #include "ardour/route_group.h"
80 #include "ardour/runtime_functions.h"
81 #include "ardour/session.h"
82 #include "ardour/session_event.h"
83 #include "ardour/source_factory.h"
84 #include "ardour/utils.h"
85
86 #include "audiographer/routines.h"
87
88 #if defined (__APPLE__)
89        #include <Carbon/Carbon.h> // For Gestalt
90 #endif
91
92 #include "i18n.h"
93
94 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
95 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
96 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
97
98 using namespace ARDOUR;
99 using namespace std;
100 using namespace PBD;
101
102 compute_peak_t          ARDOUR::compute_peak = 0;
103 find_peaks_t            ARDOUR::find_peaks = 0;
104 apply_gain_to_buffer_t  ARDOUR::apply_gain_to_buffer = 0;
105 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
106 mix_buffers_no_gain_t   ARDOUR::mix_buffers_no_gain = 0;
107
108 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
109
110 void ARDOUR::setup_enum_writer ();
111
112 /* this is useful for quite a few things that want to check
113    if any bounds-related property has changed
114 */
115 PBD::PropertyChange ARDOUR::bounds_change;
116
117 namespace ARDOUR { 
118         namespace Properties {
119
120                 /* the envelope and fades are not scalar items and so
121                    currently (2010/02) are not stored using Property.
122                    However, these descriptors enable us to notify
123                    about changes to them via PropertyChange. 
124
125                    Declared in ardour/audioregion.h ...
126                 */
127
128                 PBD::PropertyDescriptor<bool> fade_in;
129                 PBD::PropertyDescriptor<bool> fade_out;
130                 PBD::PropertyDescriptor<bool> envelope;
131         }
132 }
133
134 void
135 ARDOUR::make_property_quarks ()
136 {
137         Properties::fade_in.property_id = g_quark_from_static_string (X_("fade_in_FAKE"));
138         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_in_FAKE = %1\n",        Properties::fade_in.property_id));
139         Properties::fade_out.property_id = g_quark_from_static_string (X_("fade_out_FAKE"));
140         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for fade_out_FAKE = %1\n",       Properties::fade_out.property_id));
141         Properties::envelope.property_id = g_quark_from_static_string (X_("envelope_FAKE"));
142         DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for envelope_FAKE = %1\n",       Properties::envelope.property_id));
143 }
144
145 void
146 setup_hardware_optimization (bool try_optimization)
147 {
148         bool generic_mix_functions = true;
149
150         if (try_optimization) {
151
152                 FPU fpu;
153
154 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
155
156                 if (fpu.has_sse()) {
157
158                         info << "Using SSE optimized routines" << endmsg;
159
160                         // SSE SET
161                         compute_peak          = x86_sse_compute_peak;
162                         find_peaks            = x86_sse_find_peaks;
163                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
164                         mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
165                         mix_buffers_no_gain   = x86_sse_mix_buffers_no_gain;
166
167                         generic_mix_functions = false;
168
169                 }
170
171 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
172                 long sysVersion = 0;
173
174                 if (noErr != Gestalt(gestaltSystemVersion, &sysVersion))
175                         sysVersion = 0;
176
177                 if (sysVersion >= 0x00001040) { // Tiger at least
178                         compute_peak           = veclib_compute_peak;
179                         find_peaks             = veclib_find_peaks;
180                         apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
181                         mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
182                         mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
183
184                         generic_mix_functions = false;
185
186                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
187                 }
188 #endif
189
190                 /* consider FPU denormal handling to be "h/w optimization" */
191
192                 setup_fpu ();
193         }
194
195         if (generic_mix_functions) {
196
197                 compute_peak          = default_compute_peak;
198                 find_peaks            = default_find_peaks;
199                 apply_gain_to_buffer  = default_apply_gain_to_buffer;
200                 mix_buffers_with_gain = default_mix_buffers_with_gain;
201                 mix_buffers_no_gain   = default_mix_buffers_no_gain;
202
203                 info << "No H/W specific optimizations in use" << endmsg;
204         }
205         
206         AudioGrapher::Routines::override_compute_peak (compute_peak);
207         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
208 }
209
210 static void
211 lotsa_files_please ()
212 {
213         struct rlimit rl;
214
215         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
216
217                 rl.rlim_cur = rl.rlim_max;
218
219                 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
220                         if (rl.rlim_cur == RLIM_INFINITY) {
221                                 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
222                         } else {
223                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
224                         }
225                 } else {
226                         if (rl.rlim_cur == RLIM_INFINITY) {
227                                 info << _("Removed open file count limit. Excellent!") << endmsg;
228                         } else {
229                                 info << string_compose (_("%1 will be limited to %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
230                         }
231                 }
232         } else {
233                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
234         }
235 }
236
237 int
238 ARDOUR::init (bool use_vst, bool try_optimization)
239 {
240         if (!Glib::thread_supported()) {
241                 Glib::thread_init();
242         }
243
244         (void) bindtextdomain(PACKAGE, LOCALEDIR);
245
246         PBD::ID::init ();
247         SessionEvent::init_event_pool ();
248         
249         make_property_quarks ();
250         SessionObject::make_property_quarks ();
251         Region::make_property_quarks ();
252         MidiRegion::make_property_quarks ();
253         AudioRegion::make_property_quarks ();
254         RouteGroup::make_property_quarks ();
255         Playlist::make_property_quarks ();
256         AudioPlaylist::make_property_quarks ();
257
258         /* this is a useful ready to use PropertyChange that many
259            things need to check. This avoids having to compose
260            it every time we want to check for any of the relevant
261            property changes.
262         */
263
264         bounds_change.add (ARDOUR::Properties::start);
265         bounds_change.add (ARDOUR::Properties::position);
266         bounds_change.add (ARDOUR::Properties::length);
267
268         /* provide a state version for the few cases that need it and are not
269            driven by reading state from disk (e.g. undo/redo)
270         */
271
272         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
273
274         setup_enum_writer ();
275
276         // allow ardour the absolute maximum number of open files
277         lotsa_files_please ();
278
279         lrdf_init();
280         Library = new AudioLibrary;
281
282         BootMessage (_("Loading configuration"));
283
284         Config = new RCConfiguration;
285
286         if (Config->load_state ()) {
287                 return -1;
288         }
289         
290         Config->set_use_vst (use_vst);
291
292         Profile = new RuntimeProfile;
293
294
295 #ifdef VST_SUPPORT
296         if (Config->get_use_vst() && fst_init (0)) {
297                 return -1;
298         }
299 #endif
300
301 #ifdef HAVE_AUDIOUNITS
302         AUPluginInfo::load_cached_info ();
303 #endif
304
305         /* Make VAMP look in our library ahead of anything else */
306
307         char *p = getenv ("VAMP_PATH");
308         string vamppath = VAMP_DIR;
309         if (p) {
310                 vamppath += ':';
311                 vamppath += p;
312         }
313         setenv ("VAMP_PATH", vamppath.c_str(), 1);
314
315
316         setup_hardware_optimization (try_optimization);
317
318         SourceFactory::init ();
319         Analyser::init ();
320
321         /* singleton - first object is "it" */
322         new PluginManager ();
323
324         ProcessThread::init ();
325         BufferManager::init (10); // XX should be num_processors_for_dsp
326
327         PannerManager::instance().discover_panners();
328
329         return 0;
330 }
331
332 void
333 ARDOUR::init_post_engine ()
334 {
335         /* the MIDI Manager is needed by the ControlProtocolManager */
336         MIDI::Manager::create (AudioEngine::instance()->jack());
337
338         ControlProtocolManager::instance().discover_control_protocols ();
339
340         XMLNode* node;
341         if ((node = Config->control_protocol_state()) != 0) {
342                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
343         }
344 }
345
346 int
347 ARDOUR::cleanup ()
348 {
349         delete Library;
350         lrdf_cleanup ();
351         delete &ControlProtocolManager::instance();
352 #ifdef VST_SUPPORT
353         fst_exit ();
354 #endif
355         return 0;
356 }
357
358 string
359 ARDOUR::get_ardour_revision ()
360 {
361         return "$Rev$";
362 }
363
364 void
365 ARDOUR::find_bindings_files (map<string,string>& files)
366 {
367         vector<sys::path> found;
368         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
369
370         if (getenv ("ARDOUR_SAE")) {
371                 Glib::PatternSpec pattern("*SAE-*.bindings");
372                 find_matching_files_in_search_path (spath, pattern, found);
373         } else {
374                 Glib::PatternSpec pattern("*.bindings");
375                 find_matching_files_in_search_path (spath, pattern, found);
376         }
377
378         if (found.empty()) {
379                 return;
380         }
381
382         for (vector<sys::path>::iterator x = found.begin(); x != found.end(); ++x) {
383                 sys::path path = *x;
384                 pair<string,string> namepath;
385                 namepath.second = path.to_string();
386                 namepath.first = path.leaf().substr (0, path.leaf().find_first_of ('.'));
387                 files.insert (namepath);
388         }
389 }
390
391 bool
392 ARDOUR::no_auto_connect()
393 {
394         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
395 }
396
397 void
398 ARDOUR::setup_fpu ()
399 {
400
401         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
402                 // valgrind doesn't understand this assembler stuff
403                 // September 10th, 2007
404                 return;
405         }
406
407 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
408
409         int MXCSR;
410         FPU fpu;
411
412         /* XXX use real code to determine if the processor supports
413            DenormalsAreZero and FlushToZero
414         */
415
416         if (!fpu.has_flush_to_zero() && !fpu.has_denormals_are_zero()) {
417                 return;
418         }
419
420         MXCSR  = _mm_getcsr();
421
422         switch (Config->get_denormal_model()) {
423         case DenormalNone:
424                 MXCSR &= ~(_MM_FLUSH_ZERO_ON|0x8000);
425                 break;
426
427         case DenormalFTZ:
428                 if (fpu.has_flush_to_zero()) {
429                         MXCSR |= _MM_FLUSH_ZERO_ON;
430                 }
431                 break;
432
433         case DenormalDAZ:
434                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
435                 if (fpu.has_denormals_are_zero()) {
436                         MXCSR |= 0x8000;
437                 }
438                 break;
439
440         case DenormalFTZDAZ:
441                 if (fpu.has_flush_to_zero()) {
442                         if (fpu.has_denormals_are_zero()) {
443                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x8000;
444                         } else {
445                                 MXCSR |= _MM_FLUSH_ZERO_ON;
446                         }
447                 }
448                 break;
449         }
450
451         _mm_setcsr (MXCSR);
452
453 #endif
454 }
455
456 ARDOUR::OverlapType
457 ARDOUR::coverage (framepos_t sa, framepos_t ea,
458                   framepos_t sb, framepos_t eb)
459 {
460         /* OverlapType returned reflects how the second (B)
461            range overlaps the first (A).
462
463            The diagrams show various relative placements
464            of A and B for each OverlapType.
465
466            Notes:
467               Internal: the start points cannot coincide
468               External: the start and end points can coincide
469               Start: end points can coincide
470               End: start points can coincide
471
472            XXX Logically, Internal should disallow end
473            point equality.
474         */
475
476         /*
477              |--------------------|   A
478                   |------|            B
479                 |-----------------|   B
480
481
482              "B is internal to A"
483
484         */
485
486         if ((sb > sa) && (eb <= ea)) {
487                 return OverlapInternal;
488         }
489
490         /*
491              |--------------------|   A
492            ----|                      B
493            -----------------------|   B
494            --|                        B
495
496              "B overlaps the start of A"
497
498         */
499
500         if ((eb >= sa) && (eb <= ea)) {
501                 return OverlapStart;
502         }
503         /*
504              |---------------------|  A
505                    |----------------- B
506              |----------------------- B
507                                    |- B
508
509             "B overlaps the end of A"
510
511         */
512         if ((sb > sa) && (sb <= ea)) {
513                 return OverlapEnd;
514         }
515         /*
516              |--------------------|     A
517            --------------------------  B
518              |-----------------------  B
519             ----------------------|    B
520              |--------------------|    B
521
522
523            "B overlaps all of A"
524         */
525         if ((sa >= sb) && (sa <= eb) && (ea <= eb)) {
526                 return OverlapExternal;
527         }
528
529         return OverlapNone;
530 }
531
532 string
533 ARDOUR::translation_kill_path ()
534 {
535         return Glib::build_filename (user_config_directory().to_string(), ".love_is_the_language_of_audio");
536 }
537
538 bool
539 ARDOUR::translations_are_disabled ()
540 {
541         /* if file does not exist, we don't translate (bundled ardour only) */
542         return Glib::file_test (translation_kill_path(), Glib::FILE_TEST_EXISTS) == false;
543 }