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