1 #ifndef _CUBEB_MEDIA_LIBRARY_H_
2 #define _CUBEB_MEDIA_LIBRARY_H_
3 
4 struct media_lib {
5   void * libmedia;
6   int32_t (* get_output_latency)(uint32_t * latency, int stream_type);
7 };
8 
9 typedef struct media_lib media_lib;
10 
11 media_lib *
cubeb_load_media_library()12 cubeb_load_media_library()
13 {
14   media_lib ml = {0};
15   ml.libmedia = dlopen("libmedia.so", RTLD_LAZY);
16   if (!ml.libmedia) {
17     return NULL;
18   }
19 
20   // Get the latency, in ms, from AudioFlinger. First, try the most recent signature.
21   // status_t AudioSystem::getOutputLatency(uint32_t* latency, audio_stream_type_t streamType)
22   ml.get_output_latency =
23     dlsym(ml.libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t");
24   if (!ml.get_output_latency) {
25     // In case of failure, try the signature from legacy version.
26     // status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
27     ml.get_output_latency =
28       dlsym(ml.libmedia, "_ZN7android11AudioSystem16getOutputLatencyEPji");
29     if (!ml.get_output_latency) {
30       return NULL;
31     }
32   }
33 
34   media_lib * rv = NULL;
35   rv = calloc(1, sizeof(media_lib));
36   assert(rv);
37   *rv = ml;
38   return rv;
39 }
40 
41 void
cubeb_close_media_library(media_lib * ml)42 cubeb_close_media_library(media_lib * ml)
43 {
44   dlclose(ml->libmedia);
45   ml->libmedia = NULL;
46   ml->get_output_latency = NULL;
47   free(ml);
48 }
49 
50 uint32_t
cubeb_get_output_latency_from_media_library(media_lib * ml)51 cubeb_get_output_latency_from_media_library(media_lib * ml)
52 {
53   uint32_t latency = 0;
54   const int audio_stream_type_music = 3;
55   int32_t r = ml->get_output_latency(&latency, audio_stream_type_music);
56   if (r) {
57     return 0;
58   }
59   return latency;
60 }
61 
62 #endif // _CUBEB_MEDIA_LIBRARY_H_
63