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