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