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