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