redesign cross-thread registration/signalling system
[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/midi_ui.h"
101 #include "ardour/midiport_manager.h"
102 #include "ardour/mix.h"
103 #include "ardour/operations.h"
104 #include "ardour/panner_manager.h"
105 #include "ardour/plugin_manager.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 "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
447         /* this is a useful ready to use PropertyChange that many
448            things need to check. This avoids having to compose
449            it every time we want to check for any of the relevant
450            property changes.
451         */
452
453         bounds_change.add (ARDOUR::Properties::start);
454         bounds_change.add (ARDOUR::Properties::position);
455         bounds_change.add (ARDOUR::Properties::length);
456
457         /* provide a state version for the few cases that need it and are not
458            driven by reading state from disk (e.g. undo/redo)
459         */
460
461         Stateful::current_state_version = CURRENT_SESSION_FILE_VERSION;
462
463         ARDOUR::setup_enum_writer ();
464
465         // allow ardour the absolute maximum number of open files
466         lotsa_files_please ();
467
468 #ifdef HAVE_LRDF
469         lrdf_init();
470 #endif
471         Library = new AudioLibrary;
472
473         BootMessage (_("Loading configuration"));
474
475         Config = new RCConfiguration;
476
477         if (Config->load_state ()) {
478                 return false;
479         }
480
481         Config->set_use_windows_vst (use_windows_vst);
482 #ifdef LXVST_SUPPORT
483         Config->set_use_lxvst(true);
484 #endif
485
486         Profile = new RuntimeProfile;
487
488
489 #ifdef WINDOWS_VST_SUPPORT
490         if (Config->get_use_windows_vst() && fst_init (0)) {
491                 return false;
492         }
493 #endif
494
495 #ifdef LXVST_SUPPORT
496         if (Config->get_use_lxvst() && vstfx_init (0)) {
497                 return false;
498         }
499 #endif
500
501 #ifdef AUDIOUNIT_SUPPORT
502         AUPluginInfo::load_cached_info ();
503 #endif
504
505         setup_hardware_optimization (try_optimization);
506
507         SourceFactory::init ();
508         Analyser::init ();
509
510         /* singletons - first object is "it" */
511         (void) PluginManager::instance();
512 #ifdef LV2_SUPPORT
513         (void) URIMap::instance();
514 #endif
515         (void) EventTypeMap::instance();
516
517         ControlProtocolManager::instance().discover_control_protocols ();
518
519         /* for each control protocol, check for a request buffer factory method
520            and if it exists, store it in the EventLoop list of such
521            methods. This allows the relevant threads to register themselves
522            with EventLoops so that signal emission can be RT-safe.
523         */
524
525         ControlProtocolManager::instance().register_request_buffer_factories ();
526         /* it would be nice if this could auto-register itself in the
527            constructor, since MidiControlUI is a singleton, but it can't be
528            created until after the engine is running. Therefore we have to
529            explicitly register it here.
530         */
531         EventLoop::register_request_buffer_factory (X_("midiUI"), MidiControlUI::request_factory);
532
533         ProcessThread::init ();
534         /* the + 4 is a bit of a handwave. i don't actually know
535            how many more per-thread buffer sets we need above
536            the h/w concurrency, but its definitely > 1 more.
537         */
538         BufferManager::init (hardware_concurrency() + 4);
539
540         PannerManager::instance().discover_panners();
541
542         ARDOUR::AudioEngine::create ();
543
544         /* it is unfortunate that we need to include reserved names here that
545            refer to control surfaces. But there's no way to ensure a complete
546            lack of collisions without doing this, since the control surface
547            support may not even be active. Without adding an API to control
548            surface support that would list their port names, we do have to
549            list them here.
550         */
551
552         char const * const reserved[] = {
553                 _("Monitor"),
554                 _("Master"),
555                 _("Control"),
556                 _("Click"),
557                 _("Mackie"),
558                 0
559         };
560
561         for (int n = 0; reserved[n]; ++n) {
562                 reserved_io_names.push_back (reserved[n]);
563         }
564
565         libardour_initialized = true;
566
567         return true;
568 }
569
570 void
571 ARDOUR::init_post_engine ()
572 {
573         XMLNode* node;
574         if ((node = Config->control_protocol_state()) != 0) {
575                 ControlProtocolManager::instance().set_state (*node, Stateful::loading_state_version);
576         }
577
578         /* find plugins */
579
580         ARDOUR::PluginManager::instance().refresh (!Config->get_discover_vst_on_start());
581 }
582
583 void
584 ARDOUR::cleanup ()
585 {
586         if (!libardour_initialized) {
587                 return;
588         }
589
590         ARDOUR::AudioEngine::destroy ();
591
592         delete Library;
593 #ifdef HAVE_LRDF
594         lrdf_cleanup ();
595 #endif
596         delete &ControlProtocolManager::instance();
597 #ifdef WINDOWS_VST_SUPPORT
598         fst_exit ();
599 #endif
600
601 #ifdef LXVST_SUPPORT
602         vstfx_exit();
603 #endif
604         delete &PluginManager::instance();
605         delete Config;
606         PBD::cleanup ();
607
608         return;
609 }
610
611 void
612 ARDOUR::find_bindings_files (map<string,string>& files)
613 {
614         vector<std::string> found;
615         Searchpath spath = ardour_config_search_path();
616
617         if (getenv ("ARDOUR_SAE")) {
618                 find_files_matching_pattern (found, spath, "*SAE-*.bindings");
619         } else {
620                 find_files_matching_pattern (found, spath, "*.bindings");
621         }
622
623         if (found.empty()) {
624                 return;
625         }
626
627         for (vector<std::string>::iterator x = found.begin(); x != found.end(); ++x) {
628                 std::string path(*x);
629                 pair<string,string> namepath;
630                 namepath.second = path;
631                 namepath.first = PBD::basename_nosuffix (path);
632                 files.insert (namepath);
633         }
634 }
635
636 bool
637 ARDOUR::no_auto_connect()
638 {
639         return getenv ("ARDOUR_NO_AUTOCONNECT") != 0;
640 }
641
642 void
643 ARDOUR::setup_fpu ()
644 {
645         FPU* fpu = FPU::instance ();
646
647         if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
648                 // valgrind doesn't understand this assembler stuff
649                 // September 10th, 2007
650                 return;
651         }
652
653 #if defined(ARCH_X86) && defined(USE_XMMINTRIN)
654
655         int MXCSR;
656
657         if (!fpu->has_flush_to_zero() && !fpu->has_denormals_are_zero()) {
658                 return;
659         }
660
661         MXCSR  = _mm_getcsr();
662
663 #ifdef DEBUG_DENORMAL_EXCEPTION
664         /* This will raise a FP exception if a denormal is detected */
665         MXCSR &= ~_MM_MASK_DENORM;
666 #endif
667
668         switch (Config->get_denormal_model()) {
669         case DenormalNone:
670                 MXCSR &= ~(_MM_FLUSH_ZERO_ON | 0x40);
671                 break;
672
673         case DenormalFTZ:
674                 if (fpu->has_flush_to_zero()) {
675                         MXCSR |= _MM_FLUSH_ZERO_ON;
676                 }
677                 break;
678
679         case DenormalDAZ:
680                 MXCSR &= ~_MM_FLUSH_ZERO_ON;
681                 if (fpu->has_denormals_are_zero()) {
682                         MXCSR |= 0x40;
683                 }
684                 break;
685
686         case DenormalFTZDAZ:
687                 if (fpu->has_flush_to_zero()) {
688                         if (fpu->has_denormals_are_zero()) {
689                                 MXCSR |= _MM_FLUSH_ZERO_ON | 0x40;
690                         } else {
691                                 MXCSR |= _MM_FLUSH_ZERO_ON;
692                         }
693                 }
694                 break;
695         }
696
697         _mm_setcsr (MXCSR);
698
699 #endif
700 }
701
702 /* this can be changed to modify the translation behaviour for
703    cases where the user has never expressed a preference.
704 */
705 static const bool translate_by_default = true;
706
707 string
708 ARDOUR::translation_enable_path ()
709 {
710         return Glib::build_filename (user_config_directory(), ".translate");
711 }
712
713 bool
714 ARDOUR::translations_are_enabled ()
715 {
716         int fd = g_open (ARDOUR::translation_enable_path().c_str(), O_RDONLY, 0444);
717
718         if (fd < 0) {
719                 return translate_by_default;
720         }
721
722         char c;
723         bool ret = false;
724
725         if (::read (fd, &c, 1) == 1 && c == '1') {
726                 ret = true;
727         }
728
729         ::close (fd);
730
731         return ret;
732 }
733
734 bool
735 ARDOUR::set_translations_enabled (bool yn)
736 {
737         string i18n_enabler = ARDOUR::translation_enable_path();
738         int fd = g_open (i18n_enabler.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
739
740         if (fd < 0) {
741                 return false;
742         }
743
744         char c;
745
746         if (yn) {
747                 c = '1';
748         } else {
749                 c = '0';
750         }
751
752         (void) ::write (fd, &c, 1);
753         (void) ::close (fd);
754
755         return true;
756 }
757
758
759 vector<SyncSource>
760 ARDOUR::get_available_sync_options ()
761 {
762         vector<SyncSource> ret;
763
764         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
765         if (backend && backend->name() == "JACK") {
766                 ret.push_back (Engine);
767         }
768
769         ret.push_back (MTC);
770         ret.push_back (MIDIClock);
771         ret.push_back (LTC);
772
773         return ret;
774 }
775
776 /** Return a monotonic value for the number of microseconds that have elapsed
777  * since an arbitrary zero origin.
778  */
779
780 #ifdef __MACH__
781 /* Thanks Apple for not implementing this basic SUSv2, POSIX.1-2001 function
782  */
783 #include <mach/mach_time.h>
784 #define CLOCK_REALTIME 0
785 #define CLOCK_MONOTONIC 0
786 int
787 clock_gettime (int /*clk_id*/, struct timespec *t)
788 {
789         static bool initialized = false;
790         static mach_timebase_info_data_t timebase;
791         if (!initialized) {
792                 mach_timebase_info(&timebase);
793                 initialized = true;
794         }
795         uint64_t time;
796         time = mach_absolute_time();
797         double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
798         double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
799         t->tv_sec = seconds;
800         t->tv_nsec = nseconds;
801         return 0;
802 }
803 #endif
804
805 microseconds_t
806 ARDOUR::get_microseconds ()
807 {
808 #ifdef PLATFORM_WINDOWS
809         microseconds_t ret = 0;
810         LARGE_INTEGER freq, time;
811
812         if (QueryPerformanceFrequency(&freq))
813                 if (QueryPerformanceCounter(&time))
814                         ret = (microseconds_t)((time.QuadPart * 1000000) / freq.QuadPart);
815
816         return ret;
817 #else
818         struct timespec ts;
819         if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) {
820                 /* EEEK! */
821                 return 0;
822         }
823         return (microseconds_t) ts.tv_sec * 1000000 + (ts.tv_nsec/1000);
824 #endif
825 }
826
827 /** Return the number of bits per sample for a given sample format.
828  *
829  * This is closely related to sndfile_data_width() but does NOT
830  * return a "magic" value to differentiate between 32 bit integer
831  * and 32 bit floating point values.
832  */
833
834 int
835 ARDOUR::format_data_width (ARDOUR::SampleFormat format)
836 {
837
838
839
840         switch (format) {
841         case ARDOUR::FormatInt16:
842                 return 16;
843         case ARDOUR::FormatInt24:
844                 return 24;
845         default:
846                 return 32;
847         }
848 }