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