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