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