add VCA::full_name() which returns "VCA %n" : VCA %n" by default and "VCA %n : user...
[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 #ifdef interface
24 #undef interface
25 #endif
26
27 #include <cstdio> // Needed so that libraptor (included in lrdf) won't complain
28 #include <cstdlib>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/time.h>
32 #ifndef PLATFORM_WINDOWS
33 #include <sys/resource.h>
34 #endif
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <time.h>
39
40 #include <glib.h>
41 #include "pbd/gstdio_compat.h"
42
43 #ifdef PLATFORM_WINDOWS
44 #include <stdio.h> // for _setmaxstdio
45 #include <windows.h> // for LARGE_INTEGER
46 #endif
47
48 #ifdef WINDOWS_VST_SUPPORT
49 #include <fst.h>
50 #endif
51
52 #ifdef LXVST_SUPPORT
53 #include "ardour/linux_vst_support.h"
54 #endif
55
56 #ifdef AUDIOUNIT_SUPPORT
57 #include "ardour/audio_unit.h"
58 #endif
59
60 #if defined(__SSE__) || defined(USE_XMMINTRIN)
61 #include <xmmintrin.h>
62 #endif
63
64 #ifdef check
65 #undef check /* stupid Apple and their un-namespaced, generic Carbon macros */
66 #endif
67
68 #include <glibmm/fileutils.h>
69 #include <glibmm/miscutils.h>
70
71 #ifdef HAVE_LRDF
72 #include <lrdf.h>
73 #endif
74
75 #include "pbd/cpus.h"
76 #include "pbd/error.h"
77 #include "pbd/id.h"
78 #include "pbd/pbd.h"
79 #include "pbd/strsplit.h"
80 #include "pbd/fpu.h"
81 #include "pbd/file_utils.h"
82 #include "pbd/enumwriter.h"
83
84 #include "midi++/port.h"
85 #include "midi++/mmc.h"
86
87 #include "ardour/analyser.h"
88 #include "ardour/audio_library.h"
89 #include "ardour/audio_backend.h"
90 #include "ardour/audioengine.h"
91 #include "ardour/audioplaylist.h"
92 #include "ardour/audioregion.h"
93 #include "ardour/buffer_manager.h"
94 #include "ardour/control_protocol_manager.h"
95 #include "ardour/directory_names.h"
96 #include "ardour/event_type_map.h"
97 #include "ardour/filesystem_paths.h"
98 #include "ardour/midi_region.h"
99 #include "ardour/midi_ui.h"
100 #include "ardour/midiport_manager.h"
101 #include "ardour/mix.h"
102 #include "ardour/operations.h"
103 #include "ardour/panner_manager.h"
104 #include "ardour/plugin_manager.h"
105 #include "ardour/presentation_info.h"
106 #include "ardour/process_thread.h"
107 #include "ardour/profile.h"
108 #include "ardour/rc_configuration.h"
109 #include "ardour/region.h"
110 #include "ardour/route_group.h"
111 #include "ardour/runtime_functions.h"
112 #include "ardour/session_event.h"
113 #include "ardour/source_factory.h"
114 #ifdef LV2_SUPPORT
115 #include "ardour/uri_map.h"
116 #endif
117 #include "audiographer/routines.h"
118
119 #if defined (__APPLE__)
120 #include <CoreFoundation/CoreFoundation.h>
121 #endif
122
123 #include "pbd/i18n.h"
124
125 ARDOUR::RCConfiguration* ARDOUR::Config = 0;
126 ARDOUR::RuntimeProfile* ARDOUR::Profile = 0;
127 ARDOUR::AudioLibrary* ARDOUR::Library = 0;
128
129 using namespace ARDOUR;
130 using namespace std;
131 using namespace PBD;
132
133 bool libardour_initialized = false;
134
135 compute_peak_t          ARDOUR::compute_peak = 0;
136 find_peaks_t            ARDOUR::find_peaks = 0;
137 apply_gain_to_buffer_t  ARDOUR::apply_gain_to_buffer = 0;
138 mix_buffers_with_gain_t ARDOUR::mix_buffers_with_gain = 0;
139 mix_buffers_no_gain_t   ARDOUR::mix_buffers_no_gain = 0;
140 copy_vector_t                   ARDOUR::copy_vector = 0;
141
142 PBD::Signal1<void,std::string> ARDOUR::BootMessage;
143 PBD::Signal3<void,std::string,std::string,bool> ARDOUR::PluginScanMessage;
144 PBD::Signal1<void,int> ARDOUR::PluginScanTimeout;
145 PBD::Signal0<void> ARDOUR::GUIIdle;
146 PBD::Signal3<bool,std::string,std::string,int> ARDOUR::CopyConfigurationFiles;
147
148 std::map<std::string, bool> ARDOUR::reserved_io_names;
149
150 static bool have_old_configuration_files = false;
151
152 namespace ARDOUR {
153 extern void setup_enum_writer ();
154 }
155
156 /* this is useful for quite a few things that want to check
157    if any bounds-related property has changed
158 */
159 PBD::PropertyChange ARDOUR::bounds_change;
160
161 void
162 setup_hardware_optimization (bool try_optimization)
163 {
164         bool generic_mix_functions = true;
165
166         if (try_optimization) {
167
168                 FPU* fpu = FPU::instance();
169
170 #if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
171
172 #ifdef PLATFORM_WINDOWS
173                 /* We have AVX-optimized code for Windows */
174
175                 if (fpu->has_avx()) {
176 #else
177                 /* AVX code doesn't compile on Linux yet */
178
179                 if (false) {
180 #endif
181                         info << "Using AVX optimized routines" << endmsg;
182
183                         // AVX SET
184                         compute_peak          = x86_sse_avx_compute_peak;
185                         find_peaks            = x86_sse_avx_find_peaks;
186                         apply_gain_to_buffer  = x86_sse_avx_apply_gain_to_buffer;
187                         mix_buffers_with_gain = x86_sse_avx_mix_buffers_with_gain;
188                         mix_buffers_no_gain   = x86_sse_avx_mix_buffers_no_gain;
189                         copy_vector           = x86_sse_avx_copy_vector;
190
191                         generic_mix_functions = false;
192
193                 } else if (fpu->has_sse()) {
194
195                         info << "Using SSE optimized routines" << endmsg;
196
197                         // SSE SET
198                         compute_peak          = x86_sse_compute_peak;
199                         find_peaks            = x86_sse_find_peaks;
200                         apply_gain_to_buffer  = x86_sse_apply_gain_to_buffer;
201                         mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
202                         mix_buffers_no_gain   = x86_sse_mix_buffers_no_gain;
203                         copy_vector           = default_copy_vector;
204
205                         generic_mix_functions = false;
206
207                 }
208
209 #elif defined (__APPLE__) && defined (BUILD_VECLIB_OPTIMIZATIONS)
210
211                 if (floor (kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_4) { /* at least Tiger */
212                         compute_peak           = veclib_compute_peak;
213                         find_peaks             = veclib_find_peaks;
214                         apply_gain_to_buffer   = veclib_apply_gain_to_buffer;
215                         mix_buffers_with_gain  = veclib_mix_buffers_with_gain;
216                         mix_buffers_no_gain    = veclib_mix_buffers_no_gain;
217                         copy_vector            = default_copy_vector;
218
219                         generic_mix_functions = false;
220
221                         info << "Apple VecLib H/W specific optimizations in use" << endmsg;
222                 }
223 #endif
224
225                 /* consider FPU denormal handling to be "h/w optimization" */
226
227                 setup_fpu ();
228         }
229
230         if (generic_mix_functions) {
231
232                 compute_peak          = default_compute_peak;
233                 find_peaks            = default_find_peaks;
234                 apply_gain_to_buffer  = default_apply_gain_to_buffer;
235                 mix_buffers_with_gain = default_mix_buffers_with_gain;
236                 mix_buffers_no_gain   = default_mix_buffers_no_gain;
237                 copy_vector           = default_copy_vector;
238
239                 info << "No H/W specific optimizations in use" << endmsg;
240         }
241
242         AudioGrapher::Routines::override_compute_peak (compute_peak);
243         AudioGrapher::Routines::override_apply_gain_to_buffer (apply_gain_to_buffer);
244 }
245
246 static void
247 lotsa_files_please ()
248 {
249 #ifndef PLATFORM_WINDOWS
250         struct rlimit rl;
251
252         if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
253
254 #ifdef __APPLE__
255                 /* See the COMPATIBILITY note on the Apple setrlimit() man page */
256                 rl.rlim_cur = min ((rlim_t) OPEN_MAX, rl.rlim_max);
257 #else
258                 rl.rlim_cur = rl.rlim_max;
259 #endif
260
261                 if (setrlimit (RLIMIT_NOFILE, &rl) != 0) {
262                         if (rl.rlim_cur == RLIM_INFINITY) {
263                                 error << _("Could not set system open files limit to \"unlimited\"") << endmsg;
264                         } else {
265                                 error << string_compose (_("Could not set system open files limit to %1"), rl.rlim_cur) << endmsg;
266                         }
267                 } else {
268                         if (rl.rlim_cur != RLIM_INFINITY) {
269                                 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, rl.rlim_cur) << endmsg;
270                         }
271                 }
272         } else {
273                 error << string_compose (_("Could not get system open files limit (%1)"), strerror (errno)) << endmsg;
274         }
275 #else
276         /* this only affects stdio. 2048 is the maxium possible (512 the default).
277          *
278          * If we want more, we'll have to replaces the POSIX I/O interfaces with
279          * Win32 API calls (CreateFile, WriteFile, etc) which allows for 16K.
280          *
281          * see http://stackoverflow.com/questions/870173/is-there-a-limit-on-number-of-open-files-in-windows
282          * and http://bugs.mysql.com/bug.php?id=24509
283          */
284         int newmax = _setmaxstdio (2048);
285         if (newmax > 0) {
286                 info << string_compose (_("Your system is configured to limit %1 to only %2 open files"), PROGRAM_NAME, newmax) << endmsg;
287         } else {
288                 error << string_compose (_("Could not set system open files limit. Current limit is %1 open files"), _getmaxstdio())  << endmsg;
289         }
290 #endif
291 }
292
293 static int
294 copy_configuration_files (string const & old_dir, string const & new_dir, int old_version)
295 {
296         string old_name;
297         string new_name;
298
299         /* ensure target directory exists */
300
301         if (g_mkdir_with_parents (new_dir.c_str(), 0755)) {
302                 return -1;
303         }
304
305         if (old_version >= 3) {
306
307                 old_name = Glib::build_filename (old_dir, X_("recent"));
308                 new_name = Glib::build_filename (new_dir, X_("recent"));
309
310                 copy_file (old_name, new_name);
311
312                 old_name = Glib::build_filename (old_dir, X_("sfdb"));
313                 new_name = Glib::build_filename (new_dir, X_("sfdb"));
314
315                 copy_file (old_name, new_name);
316
317                 /* can only copy ardour.rc/config - UI config is not compatible */
318
319                 /* users who have been using git/nightlies since the last
320                  * release of 3.5 will have $CONFIG/config rather than
321                  * $CONFIG/ardour.rc. Pick up the newer "old" config file,
322                  * to avoid confusion.
323                  */
324
325                 string old_name = Glib::build_filename (old_dir, X_("config"));
326
327                 if (!Glib::file_test (old_name, Glib::FILE_TEST_EXISTS)) {
328                         old_name = Glib::build_filename (old_dir, X_("ardour.rc"));
329                 }
330
331                 new_name = Glib::build_filename (new_dir, X_("config"));
332
333                 copy_file (old_name, new_name);
334
335                 /* copy templates and route templates */
336
337                 old_name = Glib::build_filename (old_dir, X_("templates"));
338                 new_name = Glib::build_filename (new_dir, X_("templates"));
339
340                 copy_recurse (old_name, new_name);
341
342                 old_name = Glib::build_filename (old_dir, X_("route_templates"));
343                 new_name = Glib::build_filename (new_dir, X_("route_templates"));
344
345                 copy_recurse (old_name, new_name);
346
347                 /* presets */
348
349                 old_name = Glib::build_filename (old_dir, X_("presets"));
350                 new_name = Glib::build_filename (new_dir, X_("presets"));
351
352                 copy_recurse (old_name, new_name);
353
354                 /* presets */
355
356                 old_name = Glib::build_filename (old_dir, X_("plugin_statuses"));
357                 new_name = Glib::build_filename (new_dir, X_("plugin_statuses"));
358
359                 copy_file (old_name, new_name);
360
361                 /* export formats */
362
363                 old_name = Glib::build_filename (old_dir, export_formats_dir_name);
364                 new_name = Glib::build_filename (new_dir, export_formats_dir_name);
365
366                 vector<string> export_formats;
367                 g_mkdir_with_parents (Glib::build_filename (new_dir, export_formats_dir_name).c_str(), 0755);
368                 find_files_matching_pattern (export_formats, old_name, X_("*.format"));
369                 for (vector<string>::iterator i = export_formats.begin(); i != export_formats.end(); ++i) {
370                         std::string from = *i;
371                         std::string to = Glib::build_filename (new_name, Glib::path_get_basename (*i));
372                         copy_file (from, to);
373                 }
374         }
375
376         return 0;
377 }
378
379 void
380 ARDOUR::check_for_old_configuration_files ()
381 {
382         int current_version = atoi (X_(PROGRAM_VERSION));
383
384         if (current_version <= 1) {
385                 return;
386         }
387
388         int old_version = current_version - 1;
389
390         string old_config_dir = user_config_directory (old_version);
391         /* pass in the current version explicitly to avoid creation */
392         string current_config_dir = user_config_directory (current_version);
393
394         if (!Glib::file_test (current_config_dir, Glib::FILE_TEST_IS_DIR)) {
395                 if (Glib::file_test (old_config_dir, Glib::FILE_TEST_IS_DIR)) {
396                         have_old_configuration_files = true;
397                 }
398         }
399 }
400
401 int
402 ARDOUR::handle_old_configuration_files (boost::function<bool (std::string const&, std::string const&, int)> ui_handler)
403 {
404         if (have_old_configuration_files) {
405                 int current_version = atoi (X_(PROGRAM_VERSION));
406                 assert (current_version > 1); // established in check_for_old_configuration_files ()
407                 int old_version = current_version - 1;
408                 string old_config_dir = user_config_directory (old_version);
409                 string current_config_dir = user_config_directory (current_version);
410
411                 if (ui_handler (old_config_dir, current_config_dir, old_version)) {
412                         copy_configuration_files (old_config_dir, current_config_dir, old_version);
413                         return 1;
414                 }
415         }
416         return 0;
417 }
418
419 bool
420 ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir)
421 {
422         if (libardour_initialized) {
423                 return true;
424         }
425
426         if (!PBD::init()) return false;
427
428 #ifdef ENABLE_NLS
429         (void) bindtextdomain(PACKAGE, localedir);
430         (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
431 #endif
432
433         SessionEvent::init_event_pool ();
434
435         Operations::make_operations_quarks ();
436         SessionObject::make_property_quarks ();
437         Region::make_property_quarks ();
438         MidiRegion::make_property_quarks ();
439         AudioRegion::make_property_quarks ();
440         RouteGroup::make_property_quarks ();
441         Playlist::make_property_quarks ();
442         AudioPlaylist::make_property_quarks ();
443         PresentationInfo::make_property_quarks ();
444
445         /* this is a useful ready to use PropertyChange that many
446            things need to check. This avoids having to compose
447            it every time we want to check for any of the relevant
448            property changes.
449         */
450
451         bounds_change.add (ARDOUR::Properties::start);
452         bounds_change.add (ARDOUR::Properties::position);
453         bounds_change.add (ARDOUR::Properties::length);
454
455         /* provide a state version for the few cases that need it and are not
456            driven by reading state from disk (e.g. undo/redo)
457         */
458
459         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
460
461         ARDOUR::setup_enum_writer ();
462
463         // allow ardour the absolute maximum number of open files
464         lotsa_files_please ();
465
466 #ifdef HAVE_LRDF
467         lrdf_init();
468 #endif
469         Library = new AudioLibrary;
470
471         BootMessage (_("Loading configuration"));
472
473         Config = new RCConfiguration;
474
475         if (Config->load_state ()) {
476                 return false;
477         }
478
479         Config->set_use_windows_vst (use_windows_vst);
480 #ifdef LXVST_SUPPORT
481         Config->set_use_lxvst(true);
482 #endif
483
484         Profile = new RuntimeProfile;
485
486
487 #ifdef WINDOWS_VST_SUPPORT
488         if (Config->get_use_windows_vst() && fst_init (0)) {
489                 return false;
490         }
491 #endif
492
493 #ifdef LXVST_SUPPORT
494         if (Config->get_use_lxvst() && vstfx_init (0)) {
495                 return false;
496         }
497 #endif
498
499 #ifdef AUDIOUNIT_SUPPORT
500         AUPluginInfo::load_cached_info ();
501 #endif
502
503         setup_hardware_optimization (try_optimization);
504
505         SourceFactory::init ();
506         Analyser::init ();
507
508         /* singletons - first object is "it" */
509         (void) PluginManager::instance();
510 #ifdef LV2_SUPPORT
511         (void) URIMap::instance();
512 #endif
513         (void) EventTypeMap::instance();
514
515         ControlProtocolManager::instance().discover_control_protocols ();
516
517         /* for each control protocol, check for a request buffer factory method
518            and if it exists, store it in the EventLoop list of such
519            methods. This allows the relevant threads to register themselves
520            with EventLoops so that signal emission can be RT-safe.
521         */
522
523         ControlProtocolManager::instance().register_request_buffer_factories ();
524         /* it would be nice if this could auto-register itself in the
525            constructor, since MidiControlUI is a singleton, but it can't be
526            created until after the engine is running. Therefore we have to
527            explicitly register it here.
528         */
529         EventLoop::register_request_buffer_factory (X_("midiUI"), MidiControlUI::request_factory);
530
531         ProcessThread::init ();
532         /* the + 4 is a bit of a handwave. i don't actually know
533            how many more per-thread buffer sets we need above
534            the h/w concurrency, but its definitely > 1 more.
535         */
536         BufferManager::init (hardware_concurrency() + 4);
537
538         PannerManager::instance().discover_panners();
539
540         ARDOUR::AudioEngine::create ();
541
542         /* it is unfortunate that we need to include reserved names here that
543            refer to control surfaces. But there's no way to ensure a complete
544            lack of collisions without doing this, since the control surface
545            support may not even be active. Without adding an API to control
546            surface support that would list their port names, we do have to
547            list them here.
548
549            We also need to know if the given I/O is an actual route.
550            For routes (e.g. "master"), bus creation needs to be allowed the first time,
551            while for pure I/O (e.g. "Click") track/bus creation must always fail.
552         */
553
554         reserved_io_names[_("Monitor")] = true;
555         reserved_io_names[_("Master")] = true;
556         reserved_io_names[_("Control")] = false;
557         reserved_io_names[_("Click")] = false;
558         reserved_io_names[_("Mackie")] = false;
559
560         libardour_initialized = true;
561
562         return true;
563 }
564
565 void
566 ARDOUR::init_post_engine ()
567 {
568         XMLNode* node;
569         if ((node = Config->control_protocol_state()) != 0) {
570                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
571         }
572
573         /* find plugins */
574
575         ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
576 }
577
578 void
579 ARDOUR::cleanup ()
580 {
581         if (!libardour_initialized) {
582                 return;
583         }
584
585         ARDOUR::AudioEngine::destroy ();
586
587         delete Library;
588 #ifdef HAVE_LRDF
589         lrdf_cleanup ();
590 #endif
591         delete &ControlProtocolManager::instance();
592 #ifdef WINDOWS_VST_SUPPORT
593         fst_exit ();
594 #endif
595
596 #ifdef LXVST_SUPPORT
597         vstfx_exit();
598 #endif
599         delete &PluginManager::instance();
600         delete Config;
601         PBD::cleanup ();
602
603         return;
604 }
605
606 bool
607 ARDOUR::no_auto_connect()
608 {
609         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
610 }
611
612 void
613 ARDOUR::setup_fpu ()
614 {
615         FPU* fpu = FPU::instance ();
616
617         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
618                 // valgrind doesn't understand this assembler stuff
619                 // September 10th, 2007
620                 return;
621         }
622
623 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
624
625         int MXCSR;
626
627         if (!fpu->has_flush_to_zero() && !fpu->has_denormals_are_zero()) {
628                 return;
629         }
630
631         MXCSR  = _mm_getcsr();
632
633 #ifdef DEBUG_DENORMAL_EXCEPTION
634         /* This will raise a FP exception if a denormal is detected */
635         MXCSR &= ~_MM_MASK_DENORM;
636 #endif
637
638         switch (Config->get_denormal_model()) {
639         case DenormalNone:
640                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
641                 break;
642
643         case DenormalFTZ:
644                 if (fpu->has_flush_to_zero()) {
645                         MXCSR |= _MM_FLUSH_ZERO_ON;
646                 }
647                 break;
648
649         case DenormalDAZ:
650                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
651                 if (fpu->has_denormals_are_zero()) {
652                         MXCSR |= 0x40;
653                 }
654                 break;
655
656         case DenormalFTZDAZ:
657                 if (fpu->has_flush_to_zero()) {
658                         if (fpu->has_denormals_are_zero()) {
659                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
660                         } else {
661                                 MXCSR |= _MM_FLUSH_ZERO_ON;
662                         }
663                 }
664                 break;
665         }
666
667         _mm_setcsr (MXCSR);
668
669 #endif
670 }
671
672 /* this can be changed to modify the translation behaviour for
673    cases where the user has never expressed a preference.
674 */
675 static const bool translate_by_default = true;
676
677 string
678 ARDOUR::translation_enable_path ()
679 {
680         return Glib::build_filename (user_config_directory(), ".translate");
681 }
682
683 bool
684 ARDOUR::translations_are_enabled ()
685 {
686         int fd = g_open (ARDOUR::translation_enable_path().c_str(), O_RDONLY, 0444);
687
688         if (fd < 0) {
689                 return translate_by_default;
690         }
691
692         char c;
693         bool ret = false;
694
695         if (::read (fd, &c, 1) == 1 && c == '1') {
696                 ret = true;
697         }
698
699         ::close (fd);
700
701         return ret;
702 }
703
704 bool
705 ARDOUR::set_translations_enabled (bool yn)
706 {
707         string i18n_enabler = ARDOUR::translation_enable_path();
708         int fd = g_open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
709
710         if (fd < 0) {
711                 return false;
712         }
713
714         char c;
715
716         if (yn) {
717                 c = '1';
718         } else {
719                 c = '0';
720         }
721
722         (void) ::write (fd, &c, 1);
723         (void) ::close (fd);
724
725         Config->ParameterChanged ("enable-translation");
726         return true;
727 }
728
729
730 vector<SyncSource>
731 ARDOUR::get_available_sync_options ()
732 {
733         vector<SyncSource> ret;
734
735         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
736         if (backend && backend->name() == "JACK") {
737                 ret.push_back (Engine);
738         }
739
740         ret.push_back (MTC);
741         ret.push_back (MIDIClock);
742         ret.push_back (LTC);
743
744         return ret;
745 }
746
747 /** Return a monotonic value for the number of microseconds that have elapsed
748  * since an arbitrary zero origin.
749  */
750
751 #ifdef __MACH__
752 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
753  */
754 #include <mach/mach_time.h>
755 #define CLOCK_REALTIME 0
756 #define CLOCK_MONOTONIC 0
757 int
758 clock_gettime (int /*clk_id*/, struct timespec *t)
759 {
760         static bool initialized = false;
761         static mach_timebase_info_data_t timebase;
762         if (!initialized) {
763                 mach_timebase_info(&timebase);
764                 initialized = true;
765         }
766         uint64_t time;
767         time = mach_absolute_time();
768         double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
769         double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
770         t->tv_sec = seconds;
771         t->tv_nsec = nseconds;
772         return 0;
773 }
774 #endif
775
776 microseconds_t
777 ARDOUR::get_microseconds ()
778 {
779 #ifdef PLATFORM_WINDOWS
780         microseconds_t ret = 0;
781         LARGE_INTEGER freq, time;
782
783         if (QueryPerformanceFrequency(&freq))
784                 if (QueryPerformanceCounter(&time))
785                         ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
786
787         return ret;
788 #else
789         struct timespec ts;
790         if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
791                 /* EEEK! */
792                 return 0;
793         }
794         return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
795 #endif
796 }
797
798 /** Return the number of bits per sample for a given sample format.
799  *
800  * This is closely related to sndfile_data_width() but does NOT
801  * return a "magic" value to differentiate between 32 bit integer
802  * and 32 bit floating point values.
803  */
804
805 int
806 ARDOUR::format_data_width (ARDOUR::SampleFormat format)
807 {
808
809
810
811         switch (format) {
812         case ARDOUR::FormatInt16:
813                 return 16;
814         case ARDOUR::FormatInt24:
815                 return 24;
816         default:
817                 return 32;
818         }
819 }