loader.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. //
  2. // Dynamically loads the vorbis file shared library / dll
  3. //
  4. #include "loader.h"
  5. typedef void (*alProc)(void);
  6. //
  7. // Windows --------------------------------------------------------------------
  8. //
  9. #ifdef _WIN32
  10. #define WIN32_LEAN_AND_MEAN 1
  11. #include <windows.h>
  12. static HMODULE libvbf;
  13. static int open_libvbf(void) {
  14. libvbf = LoadLibraryA("libvorbisfile.dll");
  15. if (libvbf == NULL) {
  16. return -1;
  17. }
  18. return 0;
  19. }
  20. static void close_libvbf(void) {
  21. FreeLibrary(libvbf);
  22. }
  23. static alProc get_proc(const char *proc) {
  24. return (alProc) GetProcAddress(libvbf, proc);
  25. }
  26. //
  27. // Mac --------------------------------------------------------------------
  28. //
  29. #elif defined(__APPLE__) || defined(__APPLE_CC__)
  30. #include <Carbon/Carbon.h>
  31. CFBundleRef bundle;
  32. CFURLRef bundleURL;
  33. static void open_libvbf(void) {
  34. bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
  35. CFSTR("/System/Library/Frameworks/OpenAL.framework"),
  36. kCFURLPOSIXPathStyle, true);
  37. bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL);
  38. assert(bundle != NULL);
  39. }
  40. static void close_libvbf(void) {
  41. CFRelease(bundle);
  42. CFRelease(bundleURL);
  43. }
  44. static alProc get_proc(const char *proc) {
  45. GL3WglProc res;
  46. CFStringRef procname = CFStringCreateWithCString(kCFAllocatorDefault, proc,
  47. kCFStringEncodingASCII);
  48. res = (GL3WglProc) CFBundleGetFunctionPointerForName(bundle, procname);
  49. CFRelease(procname);
  50. return res;
  51. }
  52. //
  53. // Linux --------------------------------------------------------------------
  54. //
  55. #else
  56. #include <dlfcn.h>
  57. static void *libvbf;
  58. static char* lib_names[] = {
  59. "libvorbisfile.so.3",
  60. "libvorbisfile.so",
  61. NULL
  62. };
  63. static int open_libvbf(void) {
  64. int i = 0;
  65. while (lib_names[i] != NULL) {
  66. libvbf = dlopen(lib_names[i], RTLD_LAZY | RTLD_GLOBAL);
  67. if (libvbf != NULL) {
  68. dlerror(); // clear errors
  69. return 0;
  70. }
  71. i++;
  72. }
  73. return -1;
  74. }
  75. static void close_libvbf(void) {
  76. dlclose(libvbf);
  77. }
  78. static alProc get_proc(const char *proc) {
  79. return dlsym(libvbf, proc);
  80. }
  81. #endif
  82. // Prototypes of local functions
  83. static void load_procs(void);
  84. // Pointers to functions loaded from shared library
  85. LPOVCLEAR p_ov_clear;
  86. LPOVFOPEN p_ov_fopen;
  87. LPOVOPEN p_ov_open;
  88. LPOVOPENCALLBACKS p_ov_open_callbacks;
  89. LPOVTEST p_ov_test;
  90. LPOVTESTCALLBACKS p_ov_test_callbacks;
  91. LPOVTESTOPEN p_ov_test_open;
  92. LPOVBITRATE p_ov_bitrate;
  93. LPOVBITRATEINSTANT p_ov_bitrate_instant;
  94. LPOVSTREAMS p_ov_streams;
  95. LPOVSEEKABLE p_ov_seekable;
  96. LPOVSERIALNUMBER p_ov_serialnumber;
  97. LPOVRAWTOTAL p_ov_raw_total;
  98. LPOVPCMTOTAL p_ov_pcm_total;
  99. LPOVTIMETOTAL p_ov_time_total;
  100. LPOVRAWSEEK p_ov_raw_seek;
  101. LPOVPCMSEEK p_ov_pcm_seek;
  102. LPOVPCMSEEKPAGE p_ov_pcm_seek_page;
  103. LPOVTIMESEEK p_ov_time_seek;
  104. LPOVTIMESEEKPAGE p_ov_time_seek_page;
  105. LPOVRAWSEEKLAP p_ov_raw_seek_lap;
  106. LPOVPCMSEEKLAP p_ov_pcm_seek_lap;
  107. LPOVPCMSEEKPAGELAP p_ov_pcm_seek_page_lap;
  108. LPOVTIMESEEKLAP p_ov_time_seek_lap;
  109. LPOVTIMESEEKPAGELAP p_ov_time_seek_page_lap;
  110. LPOVRAWTELL p_ov_raw_tell;
  111. LPOVPCMTELL p_ov_pcm_tell;
  112. LPOVTIMETELL p_ov_time_tell;
  113. LPOVINFO p_ov_info;
  114. LPOVCOMMENT p_ov_comment;
  115. LPOVREADFLOAT p_ov_read_float;
  116. LPOVREADFILTER p_ov_read_filter;
  117. LPOVREAD p_ov_read;
  118. LPOVCROSSLAP p_ov_crosslap;
  119. LPOVHALFRATE p_ov_halfrate;
  120. LPOVHALFRATEP p_ov_halfrate_p;
  121. // Load functions from shared library
  122. int vorbisfile_load() {
  123. int res = open_libvbf();
  124. if (res) {
  125. return res;
  126. }
  127. load_procs();
  128. return 0;
  129. }
  130. // Loads function addresses and store in the pointers
  131. static void load_procs(void) {
  132. p_ov_clear = (LPOVCLEAR)get_proc("ov_clear");
  133. p_ov_fopen = (LPOVFOPEN)get_proc("ov_fopen");
  134. p_ov_open = (LPOVOPEN)get_proc("ov_open");
  135. p_ov_open_callbacks = (LPOVOPENCALLBACKS)get_proc("ov_open_callbacks");
  136. p_ov_test = (LPOVTEST)get_proc("ov_test");
  137. p_ov_test_callbacks = (LPOVTESTCALLBACKS)get_proc("ov_test_callbacks");
  138. p_ov_test_open = (LPOVTESTOPEN)get_proc("ov_test_open");
  139. p_ov_bitrate = (LPOVBITRATE)get_proc("ov_bitrate");
  140. p_ov_bitrate_instant = (LPOVBITRATEINSTANT)get_proc("ov_bitrate_instant");
  141. p_ov_streams = (LPOVSTREAMS)get_proc("ov_streams");
  142. p_ov_seekable = (LPOVSEEKABLE)get_proc("ov_seekable");
  143. p_ov_serialnumber = (LPOVSERIALNUMBER)get_proc("ov_serialnumber");
  144. p_ov_raw_total = (LPOVRAWTOTAL)get_proc("ov_raw_total");
  145. p_ov_pcm_total = (LPOVPCMTOTAL)get_proc("ov_pcm_total");
  146. p_ov_time_total = (LPOVTIMETOTAL)get_proc("ov_time_total");
  147. p_ov_raw_seek = (LPOVRAWSEEK)get_proc("ov_raw_seek");
  148. p_ov_pcm_seek = (LPOVPCMSEEK)get_proc("ov_pcm_seek");
  149. p_ov_pcm_seek_page = (LPOVPCMSEEKPAGE)get_proc("ov_pcm_seek_page");
  150. p_ov_time_seek = (LPOVTIMESEEK)get_proc("ov_time_seek");
  151. p_ov_time_seek_page = (LPOVTIMESEEKPAGE)get_proc("ov_time_seek_page");
  152. p_ov_raw_seek_lap = (LPOVRAWSEEKLAP)get_proc("ov_raw_seek_lap");
  153. p_ov_pcm_seek_lap = (LPOVPCMSEEKLAP)get_proc("ov_pcm_seek_lap");
  154. p_ov_pcm_seek_page_lap = (LPOVPCMSEEKPAGELAP)get_proc("ov_pcm_seek_page_lap");
  155. p_ov_time_seek_lap = (LPOVTIMESEEKLAP)get_proc("ov_time_seek_lap");
  156. p_ov_time_seek_page_lap = (LPOVTIMESEEKPAGELAP)get_proc("ov_time_seek_page_lap");
  157. p_ov_raw_tell = (LPOVRAWTELL)get_proc("ov_raw_tell");
  158. p_ov_pcm_tell = (LPOVPCMTELL)get_proc("ov_pcm_tell");
  159. p_ov_time_tell = (LPOVTIMETELL)get_proc("ov_time_tell");
  160. p_ov_info = (LPOVINFO)get_proc("ov_info");
  161. p_ov_comment = (LPOVCOMMENT)get_proc("ov_comment");
  162. p_ov_read_float = (LPOVREADFLOAT)get_proc("ov_read_float");
  163. p_ov_read_filter = (LPOVREADFILTER)get_proc("ov_read_filter");
  164. p_ov_read = (LPOVREAD)get_proc("ov_read");
  165. p_ov_crosslap = (LPOVCROSSLAP)get_proc("ov_crosslap");
  166. p_ov_halfrate = (LPOVHALFRATE)get_proc("ov_halfrate");
  167. p_ov_halfrate_p = (LPOVHALFRATEP)get_proc("ov_halfrate_p");
  168. }
  169. //
  170. // Go code cannot directly call the vorbis file function pointers loaded dynamically
  171. // The following C functions call the corresponding function pointers and can be
  172. // called by Go code.
  173. //
  174. int ov_clear(OggVorbis_File *vf) {
  175. return p_ov_clear(vf);
  176. }
  177. int ov_fopen(const char *path,OggVorbis_File *vf) {
  178. return p_ov_fopen(path, vf);
  179. }
  180. int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes) {
  181. return ov_open(f, vf, initial, ibytes);
  182. }
  183. int ov_open_callbacks(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks) {
  184. return p_ov_open_callbacks(datasource, vf, initial, ibytes, callbacks);
  185. }
  186. int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes) {
  187. return p_ov_test(f, vf, initial, ibytes);
  188. }
  189. int ov_test_callbacks(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks) {
  190. return p_ov_test_callbacks(datasource, vf, initial, ibytes, callbacks);
  191. }
  192. int ov_test_open(OggVorbis_File *vf) {
  193. return p_ov_test_open(vf);
  194. }
  195. long ov_bitrate(OggVorbis_File *vf,int i) {
  196. return p_ov_bitrate(vf, i);
  197. }
  198. long ov_bitrate_instant(OggVorbis_File *vf) {
  199. return p_ov_bitrate_instant(vf);
  200. }
  201. long ov_streams(OggVorbis_File *vf) {
  202. return p_ov_streams(vf);
  203. }
  204. long ov_seekable(OggVorbis_File *vf) {
  205. return p_ov_seekable(vf);
  206. }
  207. long ov_serialnumber(OggVorbis_File *vf,int i) {
  208. return p_ov_serialnumber(vf, i);
  209. }
  210. ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i) {
  211. return p_ov_raw_total(vf, i);
  212. }
  213. ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i) {
  214. return p_ov_pcm_total(vf, i);
  215. }
  216. double ov_time_total(OggVorbis_File *vf,int i) {
  217. return p_ov_time_total(vf, i);
  218. }
  219. int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos) {
  220. return p_ov_raw_seek(vf, pos);
  221. }
  222. int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos) {
  223. return p_ov_pcm_seek(vf, pos);
  224. }
  225. int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos) {
  226. return p_ov_pcm_seek_page(vf, pos);
  227. }
  228. int ov_time_seek(OggVorbis_File *vf,double pos) {
  229. return p_ov_time_seek(vf, pos);
  230. }
  231. int ov_time_seek_page(OggVorbis_File *vf,double pos) {
  232. return p_ov_time_seek(vf, pos);
  233. }
  234. int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos) {
  235. return p_ov_raw_seek_lap(vf, pos);
  236. }
  237. int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos) {
  238. return p_ov_pcm_seek(vf, pos);
  239. }
  240. int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos) {
  241. return p_ov_pcm_seek_page_lap(vf, pos);
  242. }
  243. int ov_time_seek_lap(OggVorbis_File *vf,double pos) {
  244. return p_ov_time_seek_lap(vf, pos);
  245. }
  246. int ov_time_seek_page_lap(OggVorbis_File *vf,double pos) {
  247. return p_ov_time_seek_page_lap(vf, pos);
  248. }
  249. ogg_int64_t ov_raw_tell(OggVorbis_File *vf) {
  250. return p_ov_raw_tell(vf);
  251. }
  252. ogg_int64_t ov_pcm_tell(OggVorbis_File *vf) {
  253. return p_ov_pcm_tell(vf);
  254. }
  255. double ov_time_tell(OggVorbis_File *vf) {
  256. return p_ov_time_tell(vf);
  257. }
  258. vorbis_info *ov_info(OggVorbis_File *vf,int link) {
  259. return p_ov_info(vf, link);
  260. }
  261. vorbis_comment *ov_comment(OggVorbis_File *vf,int link) {
  262. return p_ov_comment(vf, link);
  263. }
  264. long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int samples, int *bitstream) {
  265. return p_ov_read_float(vf, pcm_channels, samples, bitstream);
  266. }
  267. long ov_read_filter(OggVorbis_File *vf,char *buffer,int length, int bigendianp,int word,int sgned,int *bitstream,
  268. void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param) {
  269. return p_ov_read_filter(vf, buffer, length, bigendianp, word, sgned, bitstream, filter, filter_param);
  270. }
  271. long ov_read(OggVorbis_File *vf,char *buffer,int length, int bigendianp,int word,int sgned,int *bitstream) {
  272. return p_ov_read(vf, buffer, length, bigendianp, word, sgned, bitstream);
  273. }
  274. int ov_crosslap(OggVorbis_File *vf1,OggVorbis_File *vf2) {
  275. return p_ov_crosslap(vf1, vf2);
  276. }
  277. int ov_halfrate(OggVorbis_File *vf,int flag) {
  278. return p_ov_halfrate(vf, flag);
  279. }
  280. int ov_halfrate_p(OggVorbis_File *vf) {
  281. return p_ov_halfrate_p(vf);
  282. }