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