seal 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (421) hide show
  1. data/.yardopts +1 -0
  2. data/LICENSE +13 -0
  3. data/README.md +265 -0
  4. data/ext/seal/extconf.rb +45 -0
  5. data/include/al/al.h +724 -0
  6. data/include/al/alc.h +277 -0
  7. data/include/al/efx-presets.h +402 -0
  8. data/include/al/efx.h +758 -0
  9. data/include/mpg123/mpg123.h +1034 -0
  10. data/include/ogg/config_types.h +25 -0
  11. data/include/ogg/ogg.h +210 -0
  12. data/include/ogg/os_types.h +147 -0
  13. data/include/seal.h +23 -0
  14. data/include/seal/buf.h +143 -0
  15. data/include/seal/core.h +95 -0
  16. data/include/seal/efs.h +112 -0
  17. data/include/seal/err.h +93 -0
  18. data/include/seal/fmt.h +58 -0
  19. data/include/seal/listener.h +103 -0
  20. data/include/seal/raw.h +86 -0
  21. data/include/seal/rvb.h +520 -0
  22. data/include/seal/src.h +413 -0
  23. data/include/seal/stream.h +81 -0
  24. data/include/vorbis/codec.h +243 -0
  25. data/include/vorbis/vorbisfile.h +206 -0
  26. data/mpg123/AUTHORS +150 -0
  27. data/mpg123/COPYING +773 -0
  28. data/mpg123/ChangeLog +3 -0
  29. data/mpg123/INSTALL +111 -0
  30. data/mpg123/Makefile.am +99 -0
  31. data/mpg123/Makefile.in +1043 -0
  32. data/mpg123/NEWS +1200 -0
  33. data/mpg123/NEWS.libmpg123 +133 -0
  34. data/mpg123/README +203 -0
  35. data/mpg123/TODO +38 -0
  36. data/mpg123/aclocal.m4 +1168 -0
  37. data/mpg123/build/config.guess +1530 -0
  38. data/mpg123/build/config.sub +1782 -0
  39. data/mpg123/build/depcomp +707 -0
  40. data/mpg123/build/install-sh +527 -0
  41. data/mpg123/build/ltmain.sh +9655 -0
  42. data/mpg123/build/missing +330 -0
  43. data/mpg123/configure +20267 -0
  44. data/mpg123/configure.ac +2178 -0
  45. data/mpg123/doc/ACCURACY +2 -0
  46. data/mpg123/doc/BENCHMARKING +110 -0
  47. data/mpg123/doc/BUGS +3 -0
  48. data/mpg123/doc/CONTACT +17 -0
  49. data/mpg123/doc/LICENSE +22 -0
  50. data/mpg123/doc/Makefile.am +32 -0
  51. data/mpg123/doc/Makefile.in +490 -0
  52. data/mpg123/doc/PATENTS +39 -0
  53. data/mpg123/doc/README.3DNOW +56 -0
  54. data/mpg123/doc/README.gain +171 -0
  55. data/mpg123/doc/README.remote +218 -0
  56. data/mpg123/doc/ROAD_TO_LGPL +270 -0
  57. data/mpg123/doc/THANKS +13 -0
  58. data/mpg123/doc/TODO +63 -0
  59. data/mpg123/doc/doxy_examples.c +21 -0
  60. data/mpg123/doc/doxygen.conf +41 -0
  61. data/mpg123/doc/doxyhead.xhtml +12 -0
  62. data/mpg123/doc/examples/dump_seekindex.c +41 -0
  63. data/mpg123/doc/examples/extract_frames.c +92 -0
  64. data/mpg123/doc/examples/feedseek.c +238 -0
  65. data/mpg123/doc/examples/id3dump.c +178 -0
  66. data/mpg123/doc/examples/mpg123_to_wav.c +118 -0
  67. data/mpg123/doc/examples/mpglib.c +92 -0
  68. data/mpg123/doc/examples/scan.c +47 -0
  69. data/mpg123/doc/libmpg123_speed.txt +84 -0
  70. data/mpg123/equalize.dat +37 -0
  71. data/mpg123/libmpg123.pc.in +11 -0
  72. data/mpg123/m4/addrconfig.m4 +34 -0
  73. data/mpg123/m4/libtool.m4 +7982 -0
  74. data/mpg123/m4/ltoptions.m4 +384 -0
  75. data/mpg123/m4/ltsugar.m4 +123 -0
  76. data/mpg123/m4/ltversion.m4 +23 -0
  77. data/mpg123/m4/lt~obsolete.m4 +98 -0
  78. data/mpg123/makedll.sh +19 -0
  79. data/mpg123/man1/mpg123.1 +512 -0
  80. data/mpg123/mpg123.spec +68 -0
  81. data/mpg123/mpg123.spec.in +68 -0
  82. data/mpg123/ports/MSVC++/2005/libmpg123/libmpg123.vcproj +741 -0
  83. data/mpg123/ports/MSVC++/2008/dump_seekindex/dump_seekindex.vcproj +194 -0
  84. data/mpg123/ports/MSVC++/2008/feedseek/feedseek.vcproj +195 -0
  85. data/mpg123/ports/MSVC++/2008/libmpg123/libmpg123.vcproj +1357 -0
  86. data/mpg123/ports/MSVC++/2008/mpg123.sln +44 -0
  87. data/mpg123/ports/MSVC++/2008/mpglib/mpglib.vcproj +191 -0
  88. data/mpg123/ports/MSVC++/2008/scan/scan.vcproj +195 -0
  89. data/mpg123/ports/MSVC++/2008clr/2008clr.sln +81 -0
  90. data/mpg123/ports/MSVC++/2008clr/examples/ReplaceReaderclr/Program.cs +435 -0
  91. data/mpg123/ports/MSVC++/2008clr/examples/ReplaceReaderclr/Properties/AssemblyInfo.cs +36 -0
  92. data/mpg123/ports/MSVC++/2008clr/examples/ReplaceReaderclr/ReplaceReaderclr.csproj +72 -0
  93. data/mpg123/ports/MSVC++/2008clr/examples/feedseekclr/Program.cs +331 -0
  94. data/mpg123/ports/MSVC++/2008clr/examples/feedseekclr/Properties/AssemblyInfo.cs +36 -0
  95. data/mpg123/ports/MSVC++/2008clr/examples/feedseekclr/feedseekclr.csproj +71 -0
  96. data/mpg123/ports/MSVC++/2008clr/examples/scanclr/Program.cs +79 -0
  97. data/mpg123/ports/MSVC++/2008clr/examples/scanclr/Properties/AssemblyInfo.cs +36 -0
  98. data/mpg123/ports/MSVC++/2008clr/examples/scanclr/scanclr.csproj +70 -0
  99. data/mpg123/ports/MSVC++/2008clr/mpg123clr/AssemblyInfo.cpp +76 -0
  100. data/mpg123/ports/MSVC++/2008clr/mpg123clr/ReadMe.txt +165 -0
  101. data/mpg123/ports/MSVC++/2008clr/mpg123clr/advanced.cpp +91 -0
  102. data/mpg123/ports/MSVC++/2008clr/mpg123clr/advanced.h +130 -0
  103. data/mpg123/ports/MSVC++/2008clr/mpg123clr/dllmain.cpp +19 -0
  104. data/mpg123/ports/MSVC++/2008clr/mpg123clr/enum.h +218 -0
  105. data/mpg123/ports/MSVC++/2008clr/mpg123clr/error.cpp +48 -0
  106. data/mpg123/ports/MSVC++/2008clr/mpg123clr/error.h +134 -0
  107. data/mpg123/ports/MSVC++/2008clr/mpg123clr/id3v1.cpp +92 -0
  108. data/mpg123/ports/MSVC++/2008clr/mpg123clr/id3v1.h +132 -0
  109. data/mpg123/ports/MSVC++/2008clr/mpg123clr/id3v2.cpp +138 -0
  110. data/mpg123/ports/MSVC++/2008clr/mpg123clr/id3v2.h +152 -0
  111. data/mpg123/ports/MSVC++/2008clr/mpg123clr/mpg123clr.cpp +896 -0
  112. data/mpg123/ports/MSVC++/2008clr/mpg123clr/mpg123clr.h +953 -0
  113. data/mpg123/ports/MSVC++/2008clr/mpg123clr/mpg123clr.rc +102 -0
  114. data/mpg123/ports/MSVC++/2008clr/mpg123clr/mpg123clr.vcproj +328 -0
  115. data/mpg123/ports/MSVC++/2008clr/mpg123clr/resource.h +14 -0
  116. data/mpg123/ports/MSVC++/2008clr/mpg123clr/stdafx.cpp +8 -0
  117. data/mpg123/ports/MSVC++/2008clr/mpg123clr/stdafx.h +38 -0
  118. data/mpg123/ports/MSVC++/2008clr/mpg123clr/string.cpp +166 -0
  119. data/mpg123/ports/MSVC++/2008clr/mpg123clr/string.h +265 -0
  120. data/mpg123/ports/MSVC++/2008clr/mpg123clr/targetver.h +24 -0
  121. data/mpg123/ports/MSVC++/2008clr/mpg123clr/text.cpp +67 -0
  122. data/mpg123/ports/MSVC++/2008clr/mpg123clr/text.h +111 -0
  123. data/mpg123/ports/MSVC++/2010/dump_seekindex/dump_seekindex.vcxproj +90 -0
  124. data/mpg123/ports/MSVC++/2010/dump_seekindex/dump_seekindex.vcxproj.filters +6 -0
  125. data/mpg123/ports/MSVC++/2010/feedseek/feedseek.vcxproj +95 -0
  126. data/mpg123/ports/MSVC++/2010/feedseek/feedseek.vcxproj.filters +6 -0
  127. data/mpg123/ports/MSVC++/2010/libmpg123/libmpg123.vcxproj +960 -0
  128. data/mpg123/ports/MSVC++/2010/libmpg123/libmpg123.vcxproj.user +3 -0
  129. data/mpg123/ports/MSVC++/2010/libmpg123/yasm.exe +0 -0
  130. data/mpg123/ports/MSVC++/2010/mpg123.sln +38 -0
  131. data/mpg123/ports/MSVC++/2010/scan/scan.vcxproj +93 -0
  132. data/mpg123/ports/MSVC++/2010/scan/scan.vcxproj.filters +6 -0
  133. data/mpg123/ports/MSVC++/CMP3Stream/INCLUDE/CORE/CORE_FileIn.H +15 -0
  134. data/mpg123/ports/MSVC++/CMP3Stream/INCLUDE/CORE/SourceFilter_MP3.H +139 -0
  135. data/mpg123/ports/MSVC++/CMP3Stream/INCLUDE/IIEP_Def.H +206 -0
  136. data/mpg123/ports/MSVC++/CMP3Stream/INCLUDE/IIEP_FileIn.H +167 -0
  137. data/mpg123/ports/MSVC++/CMP3Stream/README +4 -0
  138. data/mpg123/ports/MSVC++/CMP3Stream/SOURCE/CORE_FileIn.CPP +462 -0
  139. data/mpg123/ports/MSVC++/CMP3Stream/SOURCE/CORE_Log.CPP +122 -0
  140. data/mpg123/ports/MSVC++/CMP3Stream/SOURCE/CORE_Mutex.CPP +35 -0
  141. data/mpg123/ports/MSVC++/CMP3Stream/SOURCE/SourceFilter_MP3Stream.CPP +586 -0
  142. data/mpg123/ports/MSVC++/CMP3Stream/libMPG123/PLACE_LIBMPG123_SOURCES_HERE +0 -0
  143. data/mpg123/ports/MSVC++/CMP3Stream/libMPG123/libMPG123.vcproj +245 -0
  144. data/mpg123/ports/MSVC++/config.h +35 -0
  145. data/mpg123/ports/MSVC++/examples/feedseek.c +240 -0
  146. data/mpg123/ports/MSVC++/examples/scan.c +47 -0
  147. data/mpg123/ports/MSVC++/mpg123.h +46 -0
  148. data/mpg123/ports/MSVC++/msvc.c +59 -0
  149. data/mpg123/ports/README +26 -0
  150. data/mpg123/ports/Sony_PSP/Makefile.psp +38 -0
  151. data/mpg123/ports/Sony_PSP/README +11 -0
  152. data/mpg123/ports/Sony_PSP/config.h +368 -0
  153. data/mpg123/ports/Sony_PSP/readers.c.patch +2 -0
  154. data/mpg123/ports/Xcode/config.h +197 -0
  155. data/mpg123/ports/Xcode/mpg123.h +17 -0
  156. data/mpg123/ports/Xcode/mpg123.xcodeproj/project.pbxproj +670 -0
  157. data/mpg123/ports/mpg123_.pas +478 -0
  158. data/mpg123/scripts/benchmark-cpu.pl +56 -0
  159. data/mpg123/scripts/tag_lyrics.py +76 -0
  160. data/mpg123/src/Makefile.am +186 -0
  161. data/mpg123/src/Makefile.in +1097 -0
  162. data/mpg123/src/audio.c +725 -0
  163. data/mpg123/src/audio.h +106 -0
  164. data/mpg123/src/buffer.c +312 -0
  165. data/mpg123/src/buffer.h +45 -0
  166. data/mpg123/src/common.c +240 -0
  167. data/mpg123/src/common.h +29 -0
  168. data/mpg123/src/config.h.in +436 -0
  169. data/mpg123/src/control_generic.c +809 -0
  170. data/mpg123/src/equalizer.c +48 -0
  171. data/mpg123/src/genre.c +271 -0
  172. data/mpg123/src/genre.h +15 -0
  173. data/mpg123/src/getlopt.c +148 -0
  174. data/mpg123/src/getlopt.h +77 -0
  175. data/mpg123/src/httpget.c +700 -0
  176. data/mpg123/src/httpget.h +66 -0
  177. data/mpg123/src/legacy_module.c +74 -0
  178. data/mpg123/src/libmpg123/Makefile.am +141 -0
  179. data/mpg123/src/libmpg123/Makefile.in +919 -0
  180. data/mpg123/src/libmpg123/compat.c +138 -0
  181. data/mpg123/src/libmpg123/compat.h +178 -0
  182. data/mpg123/src/libmpg123/dct36_3dnow.S +505 -0
  183. data/mpg123/src/libmpg123/dct36_3dnowext.S +512 -0
  184. data/mpg123/src/libmpg123/dct64.c +174 -0
  185. data/mpg123/src/libmpg123/dct64_3dnow.S +712 -0
  186. data/mpg123/src/libmpg123/dct64_3dnowext.S +714 -0
  187. data/mpg123/src/libmpg123/dct64_altivec.c +315 -0
  188. data/mpg123/src/libmpg123/dct64_i386.c +336 -0
  189. data/mpg123/src/libmpg123/dct64_i486.c +342 -0
  190. data/mpg123/src/libmpg123/dct64_mmx.S +811 -0
  191. data/mpg123/src/libmpg123/dct64_neon.S +297 -0
  192. data/mpg123/src/libmpg123/dct64_neon_float.S +270 -0
  193. data/mpg123/src/libmpg123/dct64_sse.S +454 -0
  194. data/mpg123/src/libmpg123/dct64_sse_float.S +401 -0
  195. data/mpg123/src/libmpg123/dct64_x86_64.S +464 -0
  196. data/mpg123/src/libmpg123/dct64_x86_64_float.S +426 -0
  197. data/mpg123/src/libmpg123/debug.h +171 -0
  198. data/mpg123/src/libmpg123/decode.h +268 -0
  199. data/mpg123/src/libmpg123/dither.c +119 -0
  200. data/mpg123/src/libmpg123/dither.h +23 -0
  201. data/mpg123/src/libmpg123/equalizer.c +17 -0
  202. data/mpg123/src/libmpg123/equalizer_3dnow.S +70 -0
  203. data/mpg123/src/libmpg123/feature.c +106 -0
  204. data/mpg123/src/libmpg123/format.c +521 -0
  205. data/mpg123/src/libmpg123/frame.c +1046 -0
  206. data/mpg123/src/libmpg123/frame.h +410 -0
  207. data/mpg123/src/libmpg123/gapless.h +119 -0
  208. data/mpg123/src/libmpg123/getbits.h +100 -0
  209. data/mpg123/src/libmpg123/getcpuflags.S +91 -0
  210. data/mpg123/src/libmpg123/getcpuflags.h +47 -0
  211. data/mpg123/src/libmpg123/huffman.h +340 -0
  212. data/mpg123/src/libmpg123/icy.c +32 -0
  213. data/mpg123/src/libmpg123/icy.h +38 -0
  214. data/mpg123/src/libmpg123/icy2utf8.c +438 -0
  215. data/mpg123/src/libmpg123/icy2utf8.h +10 -0
  216. data/mpg123/src/libmpg123/id3.c +999 -0
  217. data/mpg123/src/libmpg123/id3.h +43 -0
  218. data/mpg123/src/libmpg123/index.c +134 -0
  219. data/mpg123/src/libmpg123/index.h +59 -0
  220. data/mpg123/src/libmpg123/intsym.h +256 -0
  221. data/mpg123/src/libmpg123/l12_integer_tables.h +278 -0
  222. data/mpg123/src/libmpg123/l2tables.h +164 -0
  223. data/mpg123/src/libmpg123/l3_integer_tables.h +1002 -0
  224. data/mpg123/src/libmpg123/layer1.c +155 -0
  225. data/mpg123/src/libmpg123/layer2.c +371 -0
  226. data/mpg123/src/libmpg123/layer3.c +2053 -0
  227. data/mpg123/src/libmpg123/lfs_alias.c +252 -0
  228. data/mpg123/src/libmpg123/lfs_wrap.c +751 -0
  229. data/mpg123/src/libmpg123/libmpg123.c +1607 -0
  230. data/mpg123/src/libmpg123/mangle.h +74 -0
  231. data/mpg123/src/libmpg123/mpeghead.h +87 -0
  232. data/mpg123/src/libmpg123/mpg123.h.in +1075 -0
  233. data/mpg123/src/libmpg123/mpg123lib_intern.h +338 -0
  234. data/mpg123/src/libmpg123/ntom.c +148 -0
  235. data/mpg123/src/libmpg123/optimize.c +964 -0
  236. data/mpg123/src/libmpg123/optimize.h +219 -0
  237. data/mpg123/src/libmpg123/parse.c +1179 -0
  238. data/mpg123/src/libmpg123/parse.h +25 -0
  239. data/mpg123/src/libmpg123/reader.h +137 -0
  240. data/mpg123/src/libmpg123/readers.c +1235 -0
  241. data/mpg123/src/libmpg123/sample.h +152 -0
  242. data/mpg123/src/libmpg123/stringbuf.c +163 -0
  243. data/mpg123/src/libmpg123/synth.c +816 -0
  244. data/mpg123/src/libmpg123/synth.h +196 -0
  245. data/mpg123/src/libmpg123/synth_3dnow.S +318 -0
  246. data/mpg123/src/libmpg123/synth_3dnowext.S +6 -0
  247. data/mpg123/src/libmpg123/synth_8bit.c +142 -0
  248. data/mpg123/src/libmpg123/synth_8bit.h +86 -0
  249. data/mpg123/src/libmpg123/synth_altivec.c +1057 -0
  250. data/mpg123/src/libmpg123/synth_arm.S +271 -0
  251. data/mpg123/src/libmpg123/synth_arm_accurate.S +287 -0
  252. data/mpg123/src/libmpg123/synth_i486.c +252 -0
  253. data/mpg123/src/libmpg123/synth_i586.S +336 -0
  254. data/mpg123/src/libmpg123/synth_i586_dither.S +375 -0
  255. data/mpg123/src/libmpg123/synth_mmx.S +125 -0
  256. data/mpg123/src/libmpg123/synth_mono.h +64 -0
  257. data/mpg123/src/libmpg123/synth_neon.S +123 -0
  258. data/mpg123/src/libmpg123/synth_neon_accurate.S +173 -0
  259. data/mpg123/src/libmpg123/synth_neon_float.S +149 -0
  260. data/mpg123/src/libmpg123/synth_neon_s32.S +168 -0
  261. data/mpg123/src/libmpg123/synth_ntom.h +213 -0
  262. data/mpg123/src/libmpg123/synth_real.c +404 -0
  263. data/mpg123/src/libmpg123/synth_s32.c +411 -0
  264. data/mpg123/src/libmpg123/synth_sse.S +6 -0
  265. data/mpg123/src/libmpg123/synth_sse3d.h +246 -0
  266. data/mpg123/src/libmpg123/synth_sse_accurate.S +294 -0
  267. data/mpg123/src/libmpg123/synth_sse_float.S +241 -0
  268. data/mpg123/src/libmpg123/synth_sse_s32.S +306 -0
  269. data/mpg123/src/libmpg123/synth_stereo_neon.S +175 -0
  270. data/mpg123/src/libmpg123/synth_stereo_neon_accurate.S +262 -0
  271. data/mpg123/src/libmpg123/synth_stereo_neon_float.S +220 -0
  272. data/mpg123/src/libmpg123/synth_stereo_neon_s32.S +247 -0
  273. data/mpg123/src/libmpg123/synth_stereo_sse_accurate.S +508 -0
  274. data/mpg123/src/libmpg123/synth_stereo_sse_float.S +416 -0
  275. data/mpg123/src/libmpg123/synth_stereo_sse_s32.S +540 -0
  276. data/mpg123/src/libmpg123/synth_stereo_x86_64.S +335 -0
  277. data/mpg123/src/libmpg123/synth_stereo_x86_64_accurate.S +454 -0
  278. data/mpg123/src/libmpg123/synth_stereo_x86_64_float.S +396 -0
  279. data/mpg123/src/libmpg123/synth_stereo_x86_64_s32.S +473 -0
  280. data/mpg123/src/libmpg123/synth_x86_64.S +244 -0
  281. data/mpg123/src/libmpg123/synth_x86_64_accurate.S +301 -0
  282. data/mpg123/src/libmpg123/synth_x86_64_float.S +259 -0
  283. data/mpg123/src/libmpg123/synth_x86_64_s32.S +312 -0
  284. data/mpg123/src/libmpg123/synths.h +52 -0
  285. data/mpg123/src/libmpg123/tabinit.c +294 -0
  286. data/mpg123/src/libmpg123/tabinit_mmx.S +210 -0
  287. data/mpg123/src/libmpg123/testcpu.c +35 -0
  288. data/mpg123/src/libmpg123/true.h +14 -0
  289. data/mpg123/src/local.c +63 -0
  290. data/mpg123/src/local.h +21 -0
  291. data/mpg123/src/metaprint.c +373 -0
  292. data/mpg123/src/metaprint.h +17 -0
  293. data/mpg123/src/module.c +306 -0
  294. data/mpg123/src/module.h +48 -0
  295. data/mpg123/src/mpg123.c +1405 -0
  296. data/mpg123/src/mpg123app.h +171 -0
  297. data/mpg123/src/output/Makefile.am +213 -0
  298. data/mpg123/src/output/Makefile.in +1238 -0
  299. data/mpg123/src/output/aix.c +300 -0
  300. data/mpg123/src/output/alib.c +209 -0
  301. data/mpg123/src/output/alsa.c +297 -0
  302. data/mpg123/src/output/arts.c +117 -0
  303. data/mpg123/src/output/coreaudio.c +370 -0
  304. data/mpg123/src/output/dummy.c +78 -0
  305. data/mpg123/src/output/esd.c +167 -0
  306. data/mpg123/src/output/hp.c +184 -0
  307. data/mpg123/src/output/jack.c +450 -0
  308. data/mpg123/src/output/mint.c +197 -0
  309. data/mpg123/src/output/nas.c +335 -0
  310. data/mpg123/src/output/openal.c +197 -0
  311. data/mpg123/src/output/os2.c +665 -0
  312. data/mpg123/src/output/oss.c +319 -0
  313. data/mpg123/src/output/portaudio.c +255 -0
  314. data/mpg123/src/output/pulse.c +164 -0
  315. data/mpg123/src/output/sdl.c +206 -0
  316. data/mpg123/src/output/sgi.c +213 -0
  317. data/mpg123/src/output/sndio.c +161 -0
  318. data/mpg123/src/output/sun.c +281 -0
  319. data/mpg123/src/output/win32.c +229 -0
  320. data/mpg123/src/playlist.c +596 -0
  321. data/mpg123/src/playlist.h +52 -0
  322. data/mpg123/src/resolver.c +319 -0
  323. data/mpg123/src/resolver.h +25 -0
  324. data/mpg123/src/sfifo.c +146 -0
  325. data/mpg123/src/sfifo.h +95 -0
  326. data/mpg123/src/streamdump.c +74 -0
  327. data/mpg123/src/streamdump.h +20 -0
  328. data/mpg123/src/term.c +479 -0
  329. data/mpg123/src/term.h +81 -0
  330. data/mpg123/src/tests/noise.c +52 -0
  331. data/mpg123/src/tests/plain_id3.c +109 -0
  332. data/mpg123/src/tests/seek_accuracy.c +261 -0
  333. data/mpg123/src/tests/seek_whence.c +56 -0
  334. data/mpg123/src/tests/testtext.h +34 -0
  335. data/mpg123/src/tests/text.c +80 -0
  336. data/mpg123/src/wav.c +464 -0
  337. data/mpg123/src/wavhead.h +68 -0
  338. data/mpg123/src/win32_net.c +599 -0
  339. data/mpg123/src/win32_support.c +191 -0
  340. data/mpg123/src/win32_support.h +152 -0
  341. data/mpg123/src/xfermem.c +321 -0
  342. data/mpg123/src/xfermem.h +74 -0
  343. data/mpg123/windows-builds.sh +137 -0
  344. data/msvc/lib/OpenAL32.lib +0 -0
  345. data/spec/fixtures/heal.ogg +0 -0
  346. data/spec/fixtures/tone_up.wav +0 -0
  347. data/spec/seal/buffer_spec.rb +37 -0
  348. data/spec/seal/core_spec.rb +29 -0
  349. data/spec/seal/effect_slot_spec.rb +38 -0
  350. data/spec/seal/listener_spec.rb +33 -0
  351. data/spec/seal/reverb_spec.rb +51 -0
  352. data/spec/seal/source_spec.rb +370 -0
  353. data/spec/seal/stream_spec.rb +38 -0
  354. data/spec/spec_helper.rb +45 -0
  355. data/spec/support/attribute_examples.rb +75 -0
  356. data/spec/support/audio_object_with_format.rb +27 -0
  357. data/spec/support/movable_object.rb +22 -0
  358. data/src/libogg/bitwise.c +857 -0
  359. data/src/libogg/framing.c +2093 -0
  360. data/src/libvorbis/backends.h +144 -0
  361. data/src/libvorbis/bitrate.c +253 -0
  362. data/src/libvorbis/bitrate.h +59 -0
  363. data/src/libvorbis/block.c +1046 -0
  364. data/src/libvorbis/codebook.c +484 -0
  365. data/src/libvorbis/codebook.h +119 -0
  366. data/src/libvorbis/codec_internal.h +167 -0
  367. data/src/libvorbis/envelope.c +375 -0
  368. data/src/libvorbis/envelope.h +80 -0
  369. data/src/libvorbis/floor0.c +221 -0
  370. data/src/libvorbis/floor1.c +1100 -0
  371. data/src/libvorbis/highlevel.h +58 -0
  372. data/src/libvorbis/info.c +668 -0
  373. data/src/libvorbis/lookup.c +94 -0
  374. data/src/libvorbis/lookup.h +32 -0
  375. data/src/libvorbis/lookup_data.h +192 -0
  376. data/src/libvorbis/lpc.c +160 -0
  377. data/src/libvorbis/lpc.h +29 -0
  378. data/src/libvorbis/lsp.c +456 -0
  379. data/src/libvorbis/lsp.h +28 -0
  380. data/src/libvorbis/mapping0.c +816 -0
  381. data/src/libvorbis/masking.h +785 -0
  382. data/src/libvorbis/mdct.c +563 -0
  383. data/src/libvorbis/mdct.h +71 -0
  384. data/src/libvorbis/misc.h +57 -0
  385. data/src/libvorbis/os.h +186 -0
  386. data/src/libvorbis/psy.c +1206 -0
  387. data/src/libvorbis/psy.h +154 -0
  388. data/src/libvorbis/registry.c +45 -0
  389. data/src/libvorbis/registry.h +32 -0
  390. data/src/libvorbis/res0.c +889 -0
  391. data/src/libvorbis/scales.h +90 -0
  392. data/src/libvorbis/sharedbook.c +579 -0
  393. data/src/libvorbis/smallft.c +1255 -0
  394. data/src/libvorbis/smallft.h +34 -0
  395. data/src/libvorbis/synthesis.c +184 -0
  396. data/src/libvorbis/vorbisfile.c +2337 -0
  397. data/src/libvorbis/window.c +2135 -0
  398. data/src/libvorbis/window.h +26 -0
  399. data/src/rubyext.c +2329 -0
  400. data/src/seal/buf.c +124 -0
  401. data/src/seal/core.c +283 -0
  402. data/src/seal/efs.c +74 -0
  403. data/src/seal/err.c +118 -0
  404. data/src/seal/fmt.c +86 -0
  405. data/src/seal/listener.c +111 -0
  406. data/src/seal/mpg.c +174 -0
  407. data/src/seal/mpg.h +24 -0
  408. data/src/seal/ov.c +180 -0
  409. data/src/seal/ov.h +22 -0
  410. data/src/seal/raw.c +59 -0
  411. data/src/seal/reader.c +102 -0
  412. data/src/seal/reader.h +59 -0
  413. data/src/seal/rvb.c +368 -0
  414. data/src/seal/src.c +654 -0
  415. data/src/seal/stream.c +109 -0
  416. data/src/seal/threading.c +66 -0
  417. data/src/seal/threading.h +20 -0
  418. data/src/seal/wav.c +297 -0
  419. data/src/seal/wav.h +23 -0
  420. data/src/win32api.rb +29 -0
  421. metadata +563 -0
@@ -0,0 +1,25 @@
1
+ /*
2
+ parse: spawned from common; clustering around stream/frame parsing
3
+
4
+ copyright ?-2007 by the mpg123 project - free software under the terms of the LGPL 2.1
5
+ see COPYING and AUTHORS files in distribution or http://mpg123.org
6
+ initially written by Michael Hipp & Thomas Orgis
7
+ */
8
+
9
+ #ifndef MPG123_PARSE_H
10
+ #define MPG123_PARSE_H
11
+
12
+ #include "frame.h"
13
+
14
+ int read_frame_init(mpg123_handle* fr);
15
+ int frame_bitrate(mpg123_handle *fr);
16
+ long frame_freq(mpg123_handle *fr);
17
+ int read_frame_recover(mpg123_handle* fr); /* dead? */
18
+ int read_frame(mpg123_handle *fr);
19
+ void set_pointer(mpg123_handle *fr, long backstep);
20
+ int position_info(mpg123_handle* fr, unsigned long no, long buffsize, unsigned long* frames_left, double* current_seconds, double* seconds_left);
21
+ double compute_bpf(mpg123_handle *fr);
22
+ long time_to_frame(mpg123_handle *fr, double seconds);
23
+ int get_songlen(mpg123_handle *fr,int no);
24
+
25
+ #endif
@@ -0,0 +1,137 @@
1
+ /*
2
+ reader: reading input data
3
+
4
+ copyright ?-2007 by the mpg123 project - free software under the terms of the LGPL 2.1
5
+ see COPYING and AUTHORS files in distribution or http://mpg123.org
6
+ initially written by Thomas Orgis (after code from Michael Hipp)
7
+ */
8
+
9
+ #ifndef MPG123_READER_H
10
+ #define MPG123_READER_H
11
+
12
+ #include "config.h"
13
+ #include "mpg123.h"
14
+
15
+ #ifndef NO_FEEDER
16
+ struct buffy
17
+ {
18
+ unsigned char *data;
19
+ ssize_t size;
20
+ ssize_t realsize;
21
+ struct buffy *next;
22
+ };
23
+
24
+
25
+ struct bufferchain
26
+ {
27
+ struct buffy* first; /* The beginning of the chain. */
28
+ struct buffy* last; /* The end... of the chain. */
29
+ ssize_t size; /* Aggregated size of all buffies. */
30
+ /* These positions are relative to buffer chain beginning. */
31
+ ssize_t pos; /* Position in whole chain. */
32
+ ssize_t firstpos; /* The point of return on non-forget() */
33
+ /* The "real" filepos is fileoff + pos. */
34
+ off_t fileoff; /* Beginning of chain is at this file offset. */
35
+ size_t bufblock; /* Default (minimal) size of buffers. */
36
+ size_t pool_size; /* Keep that many buffers in storage. */
37
+ size_t pool_fill; /* That many buffers are there. */
38
+ /* A pool of buffers to re-use, if activated. It's a linked list that is worked on from the front. */
39
+ struct buffy *pool;
40
+ };
41
+
42
+ /* Call this before any buffer chain use (even bc_init()). */
43
+ void bc_prepare(struct bufferchain *, size_t pool_size, size_t bufblock);
44
+ /* Free persistent data in the buffer chain, after bc_reset(). */
45
+ void bc_cleanup(struct bufferchain *);
46
+ /* Change pool size. This does not actually allocate/free anything on itself, just instructs later operations to free less / allocate more buffers. */
47
+ void bc_poolsize(struct bufferchain *, size_t pool_size, size_t bufblock);
48
+ /* Return available byte count in the buffer. */
49
+ size_t bc_fill(struct bufferchain *bc);
50
+
51
+ #endif
52
+
53
+ struct reader_data
54
+ {
55
+ off_t filelen; /* total file length or total buffer size */
56
+ off_t filepos; /* position in file or position in buffer chain */
57
+ int filept;
58
+ /* Custom opaque I/O handle from the client. */
59
+ void *iohandle;
60
+ int flags;
61
+ long timeout_sec;
62
+ ssize_t (*fdread) (mpg123_handle *, void *, size_t);
63
+ /* User can replace the read and lseek functions. The r_* are the stored replacement functions or NULL. */
64
+ ssize_t (*r_read) (int fd, void *buf, size_t count);
65
+ off_t (*r_lseek)(int fd, off_t offset, int whence);
66
+ /* These are custom I/O routines for opaque user handles.
67
+ They get picked if there's some iohandle set. */
68
+ ssize_t (*r_read_handle) (void *handle, void *buf, size_t count);
69
+ off_t (*r_lseek_handle)(void *handle, off_t offset, int whence);
70
+ /* An optional cleaner for the handle on closing the stream. */
71
+ void (*cleanup_handle)(void *handle);
72
+ /* These two pointers are the actual workers (default map to POSIX read/lseek). */
73
+ ssize_t (*read) (int fd, void *buf, size_t count);
74
+ off_t (*lseek)(int fd, off_t offset, int whence);
75
+ /* Buffered readers want that abstracted, set internally. */
76
+ ssize_t (*fullread)(mpg123_handle *, unsigned char *, ssize_t);
77
+ #ifndef NO_FEEDER
78
+ struct bufferchain buffer; /* Not dynamically allocated, these few struct bytes aren't worth the trouble. */
79
+ #endif
80
+ };
81
+
82
+ /* start to use off_t to properly do LFS in future ... used to be long */
83
+ struct reader
84
+ {
85
+ int (*init) (mpg123_handle *);
86
+ void (*close) (mpg123_handle *);
87
+ ssize_t (*fullread) (mpg123_handle *, unsigned char *, ssize_t);
88
+ int (*head_read) (mpg123_handle *, unsigned long *newhead); /* succ: TRUE, else <= 0 (FALSE or READER_MORE) */
89
+ int (*head_shift) (mpg123_handle *, unsigned long *head); /* succ: TRUE, else <= 0 (FALSE or READER_MORE) */
90
+ off_t (*skip_bytes) (mpg123_handle *, off_t len); /* succ: >=0, else error or READER_MORE */
91
+ int (*read_frame_body)(mpg123_handle *, unsigned char *, int size);
92
+ int (*back_bytes) (mpg123_handle *, off_t bytes);
93
+ int (*seek_frame) (mpg123_handle *, off_t num);
94
+ off_t (*tell) (mpg123_handle *);
95
+ void (*rewind) (mpg123_handle *);
96
+ void (*forget) (mpg123_handle *);
97
+ };
98
+
99
+ /* Open a file by path or use an opened file descriptor. */
100
+ int open_stream(mpg123_handle *, const char *path, int fd);
101
+ /* Open an external handle. */
102
+ int open_stream_handle(mpg123_handle *, void *iohandle);
103
+
104
+ /* feed based operation has some specials */
105
+ int open_feed(mpg123_handle *);
106
+ /* externally called function, returns 0 on success, -1 on error */
107
+ int feed_more(mpg123_handle *fr, const unsigned char *in, long count);
108
+ void feed_forget(mpg123_handle *fr); /* forget the data that has been read (free some buffers) */
109
+ off_t feed_set_pos(mpg123_handle *fr, off_t pos); /* Set position (inside available data if possible), return wanted byte offset of next feed. */
110
+
111
+ void open_bad(mpg123_handle *);
112
+
113
+ #define READER_FD_OPENED 0x1
114
+ #define READER_ID3TAG 0x2
115
+ #define READER_SEEKABLE 0x4
116
+ #define READER_BUFFERED 0x8
117
+ #define READER_NONBLOCK 0x20
118
+ #define READER_HANDLEIO 0x40
119
+
120
+ #define READER_STREAM 0
121
+ #define READER_ICY_STREAM 1
122
+ #define READER_FEED 2
123
+ /* These two add a little buffering to enable small seeks for peek ahead. */
124
+ #define READER_BUF_STREAM 3
125
+ #define READER_BUF_ICY_STREAM 4
126
+
127
+ #ifdef READ_SYSTEM
128
+ #define READER_SYSTEM 5
129
+ #define READERS 6
130
+ #else
131
+ #define READERS 5
132
+ #endif
133
+
134
+ #define READER_ERROR MPG123_ERR
135
+ #define READER_MORE MPG123_NEED_MORE
136
+
137
+ #endif
@@ -0,0 +1,1235 @@
1
+ /* TODO: Check all read calls (in loops, especially!) for return value 0 (EOF)! */
2
+
3
+ /*
4
+ readers.c: reading input data
5
+
6
+ copyright ?-2008 by the mpg123 project - free software under the terms of the LGPL 2.1
7
+ see COPYING and AUTHORS files in distribution or http://mpg123.org
8
+ initially written by Michael Hipp
9
+ */
10
+
11
+ #include "mpg123lib_intern.h"
12
+ #include <sys/stat.h>
13
+ #include <fcntl.h>
14
+ #include <errno.h>
15
+ /* For select(), I need select.h according to POSIX 2001, else: sys/time.h sys/types.h unistd.h (the latter two included in compat.h already). */
16
+ #ifdef HAVE_SYS_SELECT_H
17
+ #include <sys/select.h>
18
+ #endif
19
+ #ifdef HAVE_SYS_TIME_H
20
+ #include <sys/time.h>
21
+ #endif
22
+ #ifdef _MSC_VER
23
+ #include <io.h>
24
+ #endif
25
+
26
+ #include "compat.h"
27
+ #include "debug.h"
28
+
29
+ static int default_init(mpg123_handle *fr);
30
+ static off_t get_fileinfo(mpg123_handle *);
31
+ static ssize_t posix_read(int fd, void *buf, size_t count){ return read(fd, buf, count); }
32
+ static off_t posix_lseek(int fd, off_t offset, int whence){ return lseek(fd, offset, whence); }
33
+ static off_t nix_lseek(int fd, off_t offset, int whence){ return -1; }
34
+
35
+ static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count);
36
+
37
+ /* Wrapper to decide between descriptor-based and external handle-based I/O. */
38
+ static off_t io_seek(struct reader_data *rdat, off_t offset, int whence);
39
+ static ssize_t io_read(struct reader_data *rdat, void *buf, size_t count);
40
+
41
+ #ifndef NO_FEEDER
42
+ /* Bufferchain methods. */
43
+ static void bc_init(struct bufferchain *bc);
44
+ static void bc_reset(struct bufferchain *bc);
45
+ static int bc_append(struct bufferchain *bc, ssize_t size);
46
+ #if 0
47
+ static void bc_drop(struct bufferchain *bc);
48
+ #endif
49
+ static int bc_add(struct bufferchain *bc, const unsigned char *data, ssize_t size);
50
+ static ssize_t bc_give(struct bufferchain *bc, unsigned char *out, ssize_t size);
51
+ static ssize_t bc_skip(struct bufferchain *bc, ssize_t count);
52
+ static ssize_t bc_seekback(struct bufferchain *bc, ssize_t count);
53
+ static void bc_forget(struct bufferchain *bc);
54
+ #endif
55
+
56
+ /* A normal read and a read with timeout. */
57
+ static ssize_t plain_read(mpg123_handle *fr, void *buf, size_t count)
58
+ {
59
+ ssize_t ret = io_read(&fr->rdat, buf, count);
60
+ if(VERBOSE3) debug2("read %li bytes of %li", (long)ret, (long)count);
61
+ return ret;
62
+ }
63
+
64
+ #ifdef TIMEOUT_READ
65
+
66
+ /* Wait for data becoming available, allowing soft-broken network connection to die
67
+ This is needed for Shoutcast servers that have forgotten about us while connection was temporarily down. */
68
+ static ssize_t timeout_read(mpg123_handle *fr, void *buf, size_t count)
69
+ {
70
+ struct timeval tv;
71
+ ssize_t ret = 0;
72
+ fd_set fds;
73
+ tv.tv_sec = fr->rdat.timeout_sec;
74
+ tv.tv_usec = 0;
75
+ FD_ZERO(&fds);
76
+ FD_SET(fr->rdat.filept, &fds);
77
+ ret = select(fr->rdat.filept+1, &fds, NULL, NULL, &tv);
78
+ /* This works only with "my" read function. Not user-replaced. */
79
+ if(ret > 0) ret = read(fr->rdat.filept, buf, count);
80
+ else
81
+ {
82
+ ret=-1; /* no activity is the error */
83
+ if(NOQUIET) error("stream timed out");
84
+ }
85
+ return ret;
86
+ }
87
+ #endif
88
+
89
+ #ifndef NO_ICY
90
+ /* stream based operation with icy meta data*/
91
+ static ssize_t icy_fullread(mpg123_handle *fr, unsigned char *buf, ssize_t count)
92
+ {
93
+ ssize_t ret,cnt;
94
+ cnt = 0;
95
+ if(fr->rdat.flags & READER_SEEKABLE)
96
+ {
97
+ if(NOQUIET) error("mpg123 programmer error: I don't do ICY on seekable streams.");
98
+ return -1;
99
+ }
100
+ /*
101
+ There used to be a check for expected file end here (length value or ID3 flag).
102
+ This is not needed:
103
+ 1. EOF is indicated by fdread returning zero bytes anyway.
104
+ 2. We get false positives of EOF for either files that grew or
105
+ 3. ... files that have ID3v1 tags in between (stream with intro).
106
+ */
107
+
108
+ while(cnt < count)
109
+ {
110
+ /* all icy code is inside this if block, everything else is the plain fullread we know */
111
+ /* debug1("read: %li left", (long) count-cnt); */
112
+ if(fr->icy.next < count-cnt)
113
+ {
114
+ unsigned char temp_buff;
115
+ size_t meta_size;
116
+ ssize_t cut_pos;
117
+
118
+ /* we are near icy-metaint boundary, read up to the boundary */
119
+ if(fr->icy.next > 0)
120
+ {
121
+ cut_pos = fr->icy.next;
122
+ ret = fr->rdat.fdread(fr,buf+cnt,cut_pos);
123
+ if(ret < 1)
124
+ {
125
+ if(ret == 0) break; /* Just EOF. */
126
+ if(NOQUIET) error("icy boundary read");
127
+
128
+ return READER_ERROR;
129
+ }
130
+
131
+ if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret;
132
+ cnt += ret;
133
+ fr->icy.next -= ret;
134
+ if(fr->icy.next > 0)
135
+ {
136
+ debug1("another try... still %li left", (long)fr->icy.next);
137
+ continue;
138
+ }
139
+ }
140
+ /* now off to read icy data */
141
+
142
+ /* one byte icy-meta size (must be multiplied by 16 to get icy-meta length) */
143
+
144
+ ret = fr->rdat.fdread(fr,&temp_buff,1); /* Getting one single byte hast to suceed. */
145
+ if(ret < 0){ if(NOQUIET) error("reading icy size"); return READER_ERROR; }
146
+ if(ret == 0) break;
147
+
148
+ debug2("got meta-size byte: %u, at filepos %li", temp_buff, (long)fr->rdat.filepos );
149
+ if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret; /* 1... */
150
+
151
+ if((meta_size = ((size_t) temp_buff) * 16))
152
+ {
153
+ /* we have got some metadata */
154
+ char *meta_buff;
155
+ /* TODO: Get rid of this malloc ... perhaps hooking into the reader buffer pool? */
156
+ meta_buff = malloc(meta_size+1);
157
+ if(meta_buff != NULL)
158
+ {
159
+ ssize_t left = meta_size;
160
+ while(left > 0)
161
+ {
162
+ ret = fr->rdat.fdread(fr,meta_buff+meta_size-left,left);
163
+ /* 0 is error here, too... there _must_ be the ICY data, the server promised! */
164
+ if(ret < 1){ if(NOQUIET) error("reading icy-meta"); return READER_ERROR; }
165
+ left -= ret;
166
+ }
167
+ meta_buff[meta_size] = 0; /* string paranoia */
168
+ if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret;
169
+
170
+ if(fr->icy.data) free(fr->icy.data);
171
+ fr->icy.data = meta_buff;
172
+ fr->metaflags |= MPG123_NEW_ICY;
173
+ debug2("icy-meta: %s size: %d bytes", fr->icy.data, (int)meta_size);
174
+ }
175
+ else
176
+ {
177
+ if(NOQUIET) error1("cannot allocate memory for meta_buff (%lu bytes) ... trying to skip the metadata!", (unsigned long)meta_size);
178
+ fr->rd->skip_bytes(fr, meta_size);
179
+ }
180
+ }
181
+ fr->icy.next = fr->icy.interval;
182
+ }
183
+ else
184
+ {
185
+ ret = plain_fullread(fr, buf+cnt, count-cnt);
186
+ if(ret < 0){ if(NOQUIET) error1("reading the rest of %li", (long)(count-cnt)); return READER_ERROR; }
187
+ if(ret == 0) break;
188
+
189
+ cnt += ret;
190
+ fr->icy.next -= ret;
191
+ }
192
+ }
193
+ /* debug1("done reading, got %li", (long)cnt); */
194
+ return cnt;
195
+ }
196
+ #else
197
+ #define icy_fullread NULL
198
+ #endif /* NO_ICY */
199
+
200
+ /* stream based operation */
201
+ static ssize_t plain_fullread(mpg123_handle *fr,unsigned char *buf, ssize_t count)
202
+ {
203
+ ssize_t ret,cnt=0;
204
+
205
+ #ifdef EXTRA_DEBUG
206
+ debug1("plain fullread of %"SSIZE_P, (size_p)count);
207
+ #endif
208
+ /*
209
+ There used to be a check for expected file end here (length value or ID3 flag).
210
+ This is not needed:
211
+ 1. EOF is indicated by fdread returning zero bytes anyway.
212
+ 2. We get false positives of EOF for either files that grew or
213
+ 3. ... files that have ID3v1 tags in between (stream with intro).
214
+ */
215
+ while(cnt < count)
216
+ {
217
+ ret = fr->rdat.fdread(fr,buf+cnt,count-cnt);
218
+ if(ret < 0) return READER_ERROR;
219
+ if(ret == 0) break;
220
+ if(!(fr->rdat.flags & READER_BUFFERED)) fr->rdat.filepos += ret;
221
+ cnt += ret;
222
+ }
223
+ return cnt;
224
+ }
225
+
226
+ static off_t stream_lseek(mpg123_handle *fr, off_t pos, int whence)
227
+ {
228
+ off_t ret;
229
+ ret = io_seek(&fr->rdat, pos, whence);
230
+ if (ret >= 0) fr->rdat.filepos = ret;
231
+ else
232
+ {
233
+ fr->err = MPG123_LSEEK_FAILED;
234
+ ret = READER_ERROR; /* not the original value */
235
+ }
236
+ return ret;
237
+ }
238
+
239
+ static void stream_close(mpg123_handle *fr)
240
+ {
241
+ if(fr->rdat.flags & READER_FD_OPENED) compat_close(fr->rdat.filept);
242
+
243
+ fr->rdat.filept = 0;
244
+
245
+ #ifndef NO_FEEDER
246
+ if(fr->rdat.flags & READER_BUFFERED) bc_reset(&fr->rdat.buffer);
247
+ #endif
248
+ if(fr->rdat.flags & READER_HANDLEIO)
249
+ {
250
+ if(fr->rdat.cleanup_handle != NULL) fr->rdat.cleanup_handle(fr->rdat.iohandle);
251
+
252
+ fr->rdat.iohandle = NULL;
253
+ }
254
+ }
255
+
256
+ static int stream_seek_frame(mpg123_handle *fr, off_t newframe)
257
+ {
258
+ debug2("seek_frame to %"OFF_P" (from %"OFF_P")", (off_p)newframe, (off_p)fr->num);
259
+ /* Seekable streams can go backwards and jump forwards.
260
+ Non-seekable streams still can go forward, just not jump. */
261
+ if((fr->rdat.flags & READER_SEEKABLE) || (newframe >= fr->num))
262
+ {
263
+ off_t preframe; /* a leading frame we jump to */
264
+ off_t seek_to; /* the byte offset we want to reach */
265
+ off_t to_skip; /* bytes to skip to get there (can be negative) */
266
+ /*
267
+ now seek to nearest leading index position and read from there until newframe is reached.
268
+ We use skip_bytes, which handles seekable and non-seekable streams
269
+ (the latter only for positive offset, which we ensured before entering here).
270
+ */
271
+ seek_to = frame_index_find(fr, newframe, &preframe);
272
+ /* No need to seek to index position if we are closer already.
273
+ But I am picky about fr->num == newframe, play safe by reading the frame again.
274
+ If you think that's stupid, don't call a seek to the current frame. */
275
+ if(fr->num >= newframe || fr->num < preframe)
276
+ {
277
+ to_skip = seek_to - fr->rd->tell(fr);
278
+ if(fr->rd->skip_bytes(fr, to_skip) != seek_to)
279
+ return READER_ERROR;
280
+
281
+ debug2("going to %lu; just got %lu", (long unsigned)newframe, (long unsigned)preframe);
282
+ fr->num = preframe-1; /* Watch out! I am going to read preframe... fr->num should indicate the frame before! */
283
+ }
284
+ while(fr->num < newframe)
285
+ {
286
+ /* try to be non-fatal now... frameNum only gets advanced on success anyway */
287
+ if(!read_frame(fr)) break;
288
+ }
289
+ /* Now the wanted frame should be ready for decoding. */
290
+ debug1("arrived at %lu", (long unsigned)fr->num);
291
+
292
+ return MPG123_OK;
293
+ }
294
+ else
295
+ {
296
+ fr->err = MPG123_NO_SEEK;
297
+ return READER_ERROR; /* invalid, no seek happened */
298
+ }
299
+ }
300
+
301
+ /* return FALSE on error, TRUE on success, READER_MORE on occasion */
302
+ static int generic_head_read(mpg123_handle *fr,unsigned long *newhead)
303
+ {
304
+ unsigned char hbuf[4];
305
+ int ret = fr->rd->fullread(fr,hbuf,4);
306
+ if(ret == READER_MORE) return ret;
307
+ if(ret != 4) return FALSE;
308
+
309
+ *newhead = ((unsigned long) hbuf[0] << 24) |
310
+ ((unsigned long) hbuf[1] << 16) |
311
+ ((unsigned long) hbuf[2] << 8) |
312
+ (unsigned long) hbuf[3];
313
+
314
+ return TRUE;
315
+ }
316
+
317
+ /* return FALSE on error, TRUE on success, READER_MORE on occasion */
318
+ static int generic_head_shift(mpg123_handle *fr,unsigned long *head)
319
+ {
320
+ unsigned char hbuf;
321
+ int ret = fr->rd->fullread(fr,&hbuf,1);
322
+ if(ret == READER_MORE) return ret;
323
+ if(ret != 1) return FALSE;
324
+
325
+ *head <<= 8;
326
+ *head |= hbuf;
327
+ *head &= 0xffffffff;
328
+ return TRUE;
329
+ }
330
+
331
+ /* returns reached position... negative ones are bad... */
332
+ static off_t stream_skip_bytes(mpg123_handle *fr,off_t len)
333
+ {
334
+ if(fr->rdat.flags & READER_SEEKABLE)
335
+ {
336
+ off_t ret = stream_lseek(fr, len, SEEK_CUR);
337
+ return (ret < 0) ? READER_ERROR : ret;
338
+ }
339
+ else if(len >= 0)
340
+ {
341
+ unsigned char buf[1024]; /* ThOr: Compaq cxx complained and it makes sense to me... or should one do a cast? What for? */
342
+ ssize_t ret;
343
+ while (len > 0)
344
+ {
345
+ ssize_t num = len < (off_t)sizeof(buf) ? (ssize_t)len : (ssize_t)sizeof(buf);
346
+ ret = fr->rd->fullread(fr, buf, num);
347
+ if (ret < 0) return ret;
348
+ else if(ret == 0) break; /* EOF... an error? interface defined to tell the actual position... */
349
+ len -= ret;
350
+ }
351
+ return fr->rd->tell(fr);
352
+ }
353
+ #ifndef NO_FEEDER
354
+ else if(fr->rdat.flags & READER_BUFFERED)
355
+ { /* Perhaps we _can_ go a bit back. */
356
+ if(fr->rdat.buffer.pos >= -len)
357
+ {
358
+ fr->rdat.buffer.pos += len;
359
+ return fr->rd->tell(fr);
360
+ }
361
+ else
362
+ {
363
+ fr->err = MPG123_NO_SEEK;
364
+ return READER_ERROR;
365
+ }
366
+ }
367
+ #endif
368
+ else
369
+ {
370
+ fr->err = MPG123_NO_SEEK;
371
+ return READER_ERROR;
372
+ }
373
+ }
374
+
375
+ /* Return 0 on success... */
376
+ static int stream_back_bytes(mpg123_handle *fr, off_t bytes)
377
+ {
378
+ off_t want = fr->rd->tell(fr)-bytes;
379
+ if(want < 0) return READER_ERROR;
380
+ if(stream_skip_bytes(fr,-bytes) != want) return READER_ERROR;
381
+
382
+ return 0;
383
+ }
384
+
385
+
386
+ /* returns size on success... */
387
+ static int generic_read_frame_body(mpg123_handle *fr,unsigned char *buf, int size)
388
+ {
389
+ long l;
390
+
391
+ if((l=fr->rd->fullread(fr,buf,size)) != size)
392
+ {
393
+ long ll = l;
394
+ if(ll <= 0) ll = 0;
395
+ return READER_MORE;
396
+ }
397
+ return l;
398
+ }
399
+
400
+ static off_t generic_tell(mpg123_handle *fr)
401
+ {
402
+ #ifndef NO_FEEDER
403
+ if(fr->rdat.flags & READER_BUFFERED)
404
+ fr->rdat.filepos = fr->rdat.buffer.fileoff+fr->rdat.buffer.pos;
405
+ #endif
406
+
407
+ return fr->rdat.filepos;
408
+ }
409
+
410
+ /* This does not (fully) work for non-seekable streams... You have to check for that flag, pal! */
411
+ static void stream_rewind(mpg123_handle *fr)
412
+ {
413
+ if(fr->rdat.flags & READER_SEEKABLE)
414
+ {
415
+ fr->rdat.filepos = stream_lseek(fr,0,SEEK_SET);
416
+ #ifndef NO_FEEDER
417
+ fr->rdat.buffer.fileoff = fr->rdat.filepos;
418
+ #endif
419
+ }
420
+ #ifndef NO_FEEDER
421
+ if(fr->rdat.flags & READER_BUFFERED)
422
+ {
423
+ fr->rdat.buffer.pos = 0;
424
+ fr->rdat.buffer.firstpos = 0;
425
+ fr->rdat.filepos = fr->rdat.buffer.fileoff;
426
+ }
427
+ #endif
428
+ }
429
+
430
+ /*
431
+ * returns length of a file (if filept points to a file)
432
+ * reads the last 128 bytes information into buffer
433
+ * ... that is not totally safe...
434
+ */
435
+ static off_t get_fileinfo(mpg123_handle *fr)
436
+ {
437
+ off_t len;
438
+
439
+ if((len=io_seek(&fr->rdat,0,SEEK_END)) < 0) return -1;
440
+
441
+ if(io_seek(&fr->rdat,-128,SEEK_END) < 0) return -1;
442
+
443
+ if(fr->rd->fullread(fr,(unsigned char *)fr->id3buf,128) != 128) return -1;
444
+
445
+ if(!strncmp((char*)fr->id3buf,"TAG",3)) len -= 128;
446
+
447
+ if(io_seek(&fr->rdat,0,SEEK_SET) < 0) return -1;
448
+
449
+ if(len <= 0) return -1;
450
+
451
+ return len;
452
+ }
453
+
454
+ #ifndef NO_FEEDER
455
+ /* Methods for the buffer chain, mainly used for feed reader, but not just that. */
456
+
457
+
458
+ static struct buffy* buffy_new(size_t size, size_t minsize)
459
+ {
460
+ struct buffy *newbuf;
461
+ newbuf = malloc(sizeof(struct buffy));
462
+ if(newbuf == NULL) return NULL;
463
+
464
+ newbuf->realsize = size > minsize ? size : minsize;
465
+ newbuf->data = malloc(newbuf->realsize);
466
+ if(newbuf->data == NULL)
467
+ {
468
+ free(newbuf);
469
+ return NULL;
470
+ }
471
+ newbuf->size = 0;
472
+ newbuf->next = NULL;
473
+ return newbuf;
474
+ }
475
+
476
+ static void buffy_del(struct buffy* buf)
477
+ {
478
+ if(buf)
479
+ {
480
+ free(buf->data);
481
+ free(buf);
482
+ }
483
+ }
484
+
485
+ /* Delete this buffy and all following buffies. */
486
+ static void buffy_del_chain(struct buffy* buf)
487
+ {
488
+ while(buf)
489
+ {
490
+ struct buffy* next = buf->next;
491
+ buffy_del(buf);
492
+ buf = next;
493
+ }
494
+ }
495
+
496
+ void bc_prepare(struct bufferchain *bc, size_t pool_size, size_t bufblock)
497
+ {
498
+ bc_poolsize(bc, pool_size, bufblock);
499
+ bc->pool = NULL;
500
+ bc->pool_fill = 0;
501
+ bc_init(bc); /* Ensure that members are zeroed for read-only use. */
502
+ }
503
+
504
+ size_t bc_fill(struct bufferchain *bc)
505
+ {
506
+ return (size_t)(bc->size - bc->pos);
507
+ }
508
+
509
+ void bc_poolsize(struct bufferchain *bc, size_t pool_size, size_t bufblock)
510
+ {
511
+ bc->pool_size = pool_size;
512
+ bc->bufblock = bufblock;
513
+ }
514
+
515
+ void bc_cleanup(struct bufferchain *bc)
516
+ {
517
+ buffy_del_chain(bc->pool);
518
+ bc->pool = NULL;
519
+ bc->pool_fill = 0;
520
+ }
521
+
522
+ /* Fetch a buffer from the pool (if possible) or create one. */
523
+ static struct buffy* bc_alloc(struct bufferchain *bc, size_t size)
524
+ {
525
+ /* Easy route: Just try the first available buffer.
526
+ Size does not matter, it's only a hint for creation of new buffers. */
527
+ if(bc->pool)
528
+ {
529
+ struct buffy *buf = bc->pool;
530
+ bc->pool = buf->next;
531
+ buf->next = NULL; /* That shall be set to a sensible value later. */
532
+ buf->size = 0;
533
+ --bc->pool_fill;
534
+ debug2("bc_alloc: picked %p from pool (fill now %"SIZE_P")", buf, (size_p)bc->pool_fill);
535
+ return buf;
536
+ }
537
+ else return buffy_new(size, bc->bufblock);
538
+ }
539
+
540
+ /* Either stuff the buffer back into the pool or free it for good. */
541
+ static void bc_free(struct bufferchain *bc, struct buffy* buf)
542
+ {
543
+ if(!buf) return;
544
+
545
+ if(bc->pool_fill < bc->pool_size)
546
+ {
547
+ buf->next = bc->pool;
548
+ bc->pool = buf;
549
+ ++bc->pool_fill;
550
+ }
551
+ else buffy_del(buf);
552
+ }
553
+
554
+ /* Make the buffer count in the pool match the pool size. */
555
+ static int bc_fill_pool(struct bufferchain *bc)
556
+ {
557
+ /* Remove superfluous ones. */
558
+ while(bc->pool_fill > bc->pool_size)
559
+ {
560
+ /* Lazyness: Just work on the front. */
561
+ struct buffy* buf = bc->pool;
562
+ bc->pool = buf->next;
563
+ buffy_del(buf);
564
+ --bc->pool_fill;
565
+ }
566
+
567
+ /* Add missing ones. */
568
+ while(bc->pool_fill < bc->pool_size)
569
+ {
570
+ /* Again, just work on the front. */
571
+ struct buffy* buf;
572
+ buf = buffy_new(0, bc->bufblock); /* Use default block size. */
573
+ if(!buf) return -1;
574
+
575
+ buf->next = bc->pool;
576
+ bc->pool = buf;
577
+ ++bc->pool_fill;
578
+ }
579
+
580
+ return 0;
581
+ }
582
+
583
+
584
+ static void bc_init(struct bufferchain *bc)
585
+ {
586
+ bc->first = NULL;
587
+ bc->last = bc->first;
588
+ bc->size = 0;
589
+ bc->pos = 0;
590
+ bc->firstpos = 0;
591
+ bc->fileoff = 0;
592
+ }
593
+
594
+ static void bc_reset(struct bufferchain *bc)
595
+ {
596
+ /* Free current chain, possibly stuffing back into the pool. */
597
+ while(bc->first)
598
+ {
599
+ struct buffy* buf = bc->first;
600
+ bc->first = buf->next;
601
+ bc_free(bc, buf);
602
+ }
603
+ bc_fill_pool(bc); /* Ignoring an error here... */
604
+ bc_init(bc);
605
+ }
606
+
607
+ /* Create a new buffy at the end to be filled. */
608
+ static int bc_append(struct bufferchain *bc, ssize_t size)
609
+ {
610
+ struct buffy *newbuf;
611
+ if(size < 1) return -1;
612
+
613
+ newbuf = bc_alloc(bc, size);
614
+ if(newbuf == NULL) return -2;
615
+
616
+ if(bc->last != NULL) bc->last->next = newbuf;
617
+ else if(bc->first == NULL) bc->first = newbuf;
618
+
619
+ bc->last = newbuf;
620
+ debug3("bc_append: new last buffer %p with %"SSIZE_P" B (really %"SSIZE_P")", bc->last, (ssize_p)bc->last->size, (ssize_p)bc->last->realsize);
621
+ return 0;
622
+ }
623
+
624
+ /* Append a new buffer and copy content to it. */
625
+ static int bc_add(struct bufferchain *bc, const unsigned char *data, ssize_t size)
626
+ {
627
+ int ret = 0;
628
+ ssize_t part = 0;
629
+ debug2("bc_add: adding %"SSIZE_P" bytes at %"OFF_P, (ssize_p)size, (off_p)(bc->fileoff+bc->size));
630
+ if(size >=4) debug4("first bytes: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
631
+
632
+ while(size > 0)
633
+ {
634
+ /* Try to fill up the last buffer block. */
635
+ if(bc->last != NULL && bc->last->size < bc->last->realsize)
636
+ {
637
+ part = bc->last->realsize - bc->last->size;
638
+ if(part > size) part = size;
639
+
640
+ debug2("bc_add: adding %"SSIZE_P" B to existing block %p", (ssize_p)part, bc->last);
641
+ memcpy(bc->last->data+bc->last->size, data, part);
642
+ bc->last->size += part;
643
+ size -= part;
644
+ bc->size += part;
645
+ data += part;
646
+ }
647
+
648
+ /* If there is still data left, put it into a new buffer block. */
649
+ if(size > 0 && (ret = bc_append(bc, size)) != 0)
650
+ break;
651
+ }
652
+
653
+ return ret;
654
+ }
655
+
656
+ /* Common handler for "You want more than I can give." situation. */
657
+ static ssize_t bc_need_more(struct bufferchain *bc)
658
+ {
659
+ debug3("hit end, back to beginning (%li - %li < %li)", (long)bc->size, (long)bc->pos, (long)bc->size);
660
+ /* go back to firstpos, undo the previous reads */
661
+ bc->pos = bc->firstpos;
662
+ return READER_MORE;
663
+ }
664
+
665
+ /* Give some data, advancing position but not forgetting yet. */
666
+ static ssize_t bc_give(struct bufferchain *bc, unsigned char *out, ssize_t size)
667
+ {
668
+ struct buffy *b = bc->first;
669
+ ssize_t gotcount = 0;
670
+ ssize_t offset = 0;
671
+ if(bc->size - bc->pos < size) return bc_need_more(bc);
672
+
673
+ /* find the current buffer */
674
+ while(b != NULL && (offset + b->size) <= bc->pos)
675
+ {
676
+ offset += b->size;
677
+ b = b->next;
678
+ }
679
+ /* now start copying from there */
680
+ while(gotcount < size && (b != NULL))
681
+ {
682
+ ssize_t loff = bc->pos - offset;
683
+ ssize_t chunk = size - gotcount; /* amount of bytes to get from here... */
684
+ if(chunk > b->size - loff) chunk = b->size - loff;
685
+
686
+ #ifdef EXTRA_DEBUG
687
+ debug3("copying %liB from %p+%li",(long)chunk, b->data, (long)loff);
688
+ #endif
689
+
690
+ memcpy(out+gotcount, b->data+loff, chunk);
691
+ gotcount += chunk;
692
+ bc->pos += chunk;
693
+ offset += b->size;
694
+ b = b->next;
695
+ }
696
+ #ifdef EXTRA_DEBUG
697
+ debug2("got %li bytes, pos advanced to %li", (long)gotcount, (long)bc->pos);
698
+ #endif
699
+
700
+ return gotcount;
701
+ }
702
+
703
+ /* Skip some bytes and return the new position.
704
+ The buffers are still there, just the read pointer is moved! */
705
+ static ssize_t bc_skip(struct bufferchain *bc, ssize_t count)
706
+ {
707
+ if(count >= 0)
708
+ {
709
+ if(bc->size - bc->pos < count) return bc_need_more(bc);
710
+ else return bc->pos += count;
711
+ }
712
+ else return READER_ERROR;
713
+ }
714
+
715
+ static ssize_t bc_seekback(struct bufferchain *bc, ssize_t count)
716
+ {
717
+ if(count >= 0 && count <= bc->pos) return bc->pos -= count;
718
+ else return READER_ERROR;
719
+ }
720
+
721
+ /* Throw away buffies that we passed. */
722
+ static void bc_forget(struct bufferchain *bc)
723
+ {
724
+ struct buffy *b = bc->first;
725
+ /* free all buffers that are def'n'tly outdated */
726
+ /* we have buffers until filepos... delete all buffers fully below it */
727
+ if(b) debug2("bc_forget: block %lu pos %lu", (unsigned long)b->size, (unsigned long)bc->pos);
728
+ else debug("forget with nothing there!");
729
+
730
+ while(b != NULL && bc->pos >= b->size)
731
+ {
732
+ struct buffy *n = b->next; /* != NULL or this is indeed the end and the last cycle anyway */
733
+ if(n == NULL) bc->last = NULL; /* Going to delete the last buffy... */
734
+ bc->fileoff += b->size;
735
+ bc->pos -= b->size;
736
+ bc->size -= b->size;
737
+
738
+ debug5("bc_forget: forgot %p with %lu, pos=%li, size=%li, fileoff=%li", (void*)b->data, (long)b->size, (long)bc->pos, (long)bc->size, (long)bc->fileoff);
739
+
740
+ bc_free(bc, b);
741
+ b = n;
742
+ }
743
+ bc->first = b;
744
+ bc->firstpos = bc->pos;
745
+ }
746
+
747
+ /* reader for input via manually provided buffers */
748
+
749
+ static int feed_init(mpg123_handle *fr)
750
+ {
751
+ bc_init(&fr->rdat.buffer);
752
+ bc_fill_pool(&fr->rdat.buffer);
753
+ fr->rdat.filelen = 0;
754
+ fr->rdat.filepos = 0;
755
+ fr->rdat.flags |= READER_BUFFERED;
756
+ return 0;
757
+ }
758
+
759
+ /* externally called function, returns 0 on success, -1 on error */
760
+ int feed_more(mpg123_handle *fr, const unsigned char *in, long count)
761
+ {
762
+ int ret = 0;
763
+ if(VERBOSE3) debug("feed_more");
764
+ if((ret = bc_add(&fr->rdat.buffer, in, count)) != 0)
765
+ {
766
+ ret = READER_ERROR;
767
+ if(NOQUIET) error1("Failed to add buffer, return: %i", ret);
768
+ }
769
+ else /* Not talking about filelen... that stays at 0. */
770
+
771
+ if(VERBOSE3) debug3("feed_more: %p %luB bufsize=%lu", fr->rdat.buffer.last->data,
772
+ (unsigned long)fr->rdat.buffer.last->size, (unsigned long)fr->rdat.buffer.size);
773
+ return ret;
774
+ }
775
+
776
+ static ssize_t feed_read(mpg123_handle *fr, unsigned char *out, ssize_t count)
777
+ {
778
+ ssize_t gotcount = bc_give(&fr->rdat.buffer, out, count);
779
+ if(gotcount >= 0 && gotcount != count) return READER_ERROR;
780
+ else return gotcount;
781
+ }
782
+
783
+ /* returns reached position... negative ones are bad... */
784
+ static off_t feed_skip_bytes(mpg123_handle *fr,off_t len)
785
+ {
786
+ /* This is either the new buffer offset or some negative error value. */
787
+ off_t res = bc_skip(&fr->rdat.buffer, (ssize_t)len);
788
+ if(res < 0) return res;
789
+
790
+ return fr->rdat.buffer.fileoff+res;
791
+ }
792
+
793
+ static int feed_back_bytes(mpg123_handle *fr, off_t bytes)
794
+ {
795
+ if(bytes >=0)
796
+ return bc_seekback(&fr->rdat.buffer, (ssize_t)bytes) >= 0 ? 0 : READER_ERROR;
797
+ else
798
+ return feed_skip_bytes(fr, -bytes) >= 0 ? 0 : READER_ERROR;
799
+ }
800
+
801
+ static int feed_seek_frame(mpg123_handle *fr, off_t num){ return READER_ERROR; }
802
+
803
+ /* Not just for feed reader, also for self-feeding buffered reader. */
804
+ static void buffered_forget(mpg123_handle *fr)
805
+ {
806
+ bc_forget(&fr->rdat.buffer);
807
+ fr->rdat.filepos = fr->rdat.buffer.fileoff + fr->rdat.buffer.pos;
808
+ }
809
+
810
+ off_t feed_set_pos(mpg123_handle *fr, off_t pos)
811
+ {
812
+ struct bufferchain *bc = &fr->rdat.buffer;
813
+ if(pos >= bc->fileoff && pos-bc->fileoff < bc->size)
814
+ { /* We have the position! */
815
+ bc->pos = (ssize_t)(pos - bc->fileoff);
816
+ debug1("feed_set_pos inside, next feed from %"OFF_P, (off_p)(bc->fileoff+bc->size));
817
+ return bc->fileoff+bc->size; /* Next input after end of buffer... */
818
+ }
819
+ else
820
+ { /* I expect to get the specific position on next feed. Forget what I have now. */
821
+ bc_reset(bc);
822
+ bc->fileoff = pos;
823
+ debug1("feed_set_pos outside, buffer reset, next feed from %"OFF_P, (off_p)pos);
824
+ return pos; /* Next input from exactly that position. */
825
+ }
826
+ }
827
+
828
+ /* The specific stuff for buffered stream reader. */
829
+
830
+ static ssize_t buffered_fullread(mpg123_handle *fr, unsigned char *out, ssize_t count)
831
+ {
832
+ struct bufferchain *bc = &fr->rdat.buffer;
833
+ ssize_t gotcount;
834
+ if(bc->size - bc->pos < count)
835
+ { /* Add more stuff to buffer. If hitting end of file, adjust count. */
836
+ unsigned char readbuf[4096];
837
+ ssize_t need = count - (bc->size-bc->pos);
838
+ while(need>0)
839
+ {
840
+ int ret;
841
+ ssize_t got = fr->rdat.fullread(fr, readbuf, sizeof(readbuf));
842
+ if(got < 0)
843
+ {
844
+ if(NOQUIET) error("buffer reading");
845
+ return READER_ERROR;
846
+ }
847
+
848
+ if(VERBOSE3) debug1("buffered_fullread: buffering %li bytes from stream (if > 0)", (long)got);
849
+ if(got > 0 && (ret=bc_add(bc, readbuf, got)) != 0)
850
+ {
851
+ if(NOQUIET) error1("unable to add to chain, return: %i", ret);
852
+ return READER_ERROR;
853
+ }
854
+
855
+ need -= got; /* May underflow here... */
856
+ if(got < sizeof(readbuf)) /* That naturally catches got == 0, too. */
857
+ {
858
+ if(VERBOSE3) fprintf(stderr, "Note: Input data end.\n");
859
+ break; /* End. */
860
+ }
861
+ }
862
+ if(bc->size - bc->pos < count)
863
+ count = bc->size - bc->pos; /* We want only what we got. */
864
+ }
865
+ gotcount = bc_give(bc, out, count);
866
+
867
+ if(VERBOSE3) debug2("wanted %li, got %li", (long)count, (long)gotcount);
868
+
869
+ if(gotcount != count){ if(NOQUIET) error("gotcount != count"); return READER_ERROR; }
870
+ else return gotcount;
871
+ }
872
+ #else
873
+ int feed_more(mpg123_handle *fr, const unsigned char *in, long count)
874
+ {
875
+ fr->err = MPG123_MISSING_FEATURE;
876
+ return -1;
877
+ }
878
+ off_t feed_set_pos(mpg123_handle *fr, off_t pos)
879
+ {
880
+ fr->err = MPG123_MISSING_FEATURE;
881
+ return -1;
882
+ }
883
+ #endif /* NO_FEEDER */
884
+
885
+ /*****************************************************************
886
+ * read frame helper
887
+ */
888
+
889
+ #define bugger_off { mh->err = MPG123_NO_READER; return MPG123_ERR; }
890
+ static int bad_init(mpg123_handle *mh) bugger_off
891
+ static void bad_close(mpg123_handle *mh){}
892
+ static ssize_t bad_fullread(mpg123_handle *mh, unsigned char *data, ssize_t count) bugger_off
893
+ static int bad_head_read(mpg123_handle *mh, unsigned long *newhead) bugger_off
894
+ static int bad_head_shift(mpg123_handle *mh, unsigned long *head) bugger_off
895
+ static off_t bad_skip_bytes(mpg123_handle *mh, off_t len) bugger_off
896
+ static int bad_read_frame_body(mpg123_handle *mh, unsigned char *data, int size) bugger_off
897
+ static int bad_back_bytes(mpg123_handle *mh, off_t bytes) bugger_off
898
+ static int bad_seek_frame(mpg123_handle *mh, off_t num) bugger_off
899
+ static off_t bad_tell(mpg123_handle *mh) bugger_off
900
+ static void bad_rewind(mpg123_handle *mh){}
901
+ #undef bugger_off
902
+
903
+ #define READER_STREAM 0
904
+ #define READER_ICY_STREAM 1
905
+ #define READER_FEED 2
906
+ #define READER_BUF_STREAM 3
907
+ #define READER_BUF_ICY_STREAM 4
908
+ static struct reader readers[] =
909
+ {
910
+ { /* READER_STREAM */
911
+ default_init,
912
+ stream_close,
913
+ plain_fullread,
914
+ generic_head_read,
915
+ generic_head_shift,
916
+ stream_skip_bytes,
917
+ generic_read_frame_body,
918
+ stream_back_bytes,
919
+ stream_seek_frame,
920
+ generic_tell,
921
+ stream_rewind,
922
+ NULL
923
+ } ,
924
+ { /* READER_ICY_STREAM */
925
+ default_init,
926
+ stream_close,
927
+ icy_fullread,
928
+ generic_head_read,
929
+ generic_head_shift,
930
+ stream_skip_bytes,
931
+ generic_read_frame_body,
932
+ stream_back_bytes,
933
+ stream_seek_frame,
934
+ generic_tell,
935
+ stream_rewind,
936
+ NULL
937
+ },
938
+ #ifdef NO_FEEDER
939
+ #define feed_init NULL
940
+ #define feed_read NULL
941
+ #define buffered_fullread NULL
942
+ #define feed_seek_frame NULL
943
+ #define feed_back_bytes NULL
944
+ #define feed_skip_bytes NULL
945
+ #define buffered_forget NULL
946
+ #endif
947
+ { /* READER_FEED */
948
+ feed_init,
949
+ stream_close,
950
+ feed_read,
951
+ generic_head_read,
952
+ generic_head_shift,
953
+ feed_skip_bytes,
954
+ generic_read_frame_body,
955
+ feed_back_bytes,
956
+ feed_seek_frame,
957
+ generic_tell,
958
+ stream_rewind,
959
+ buffered_forget
960
+ },
961
+ { /* READER_BUF_STREAM */
962
+ default_init,
963
+ stream_close,
964
+ buffered_fullread,
965
+ generic_head_read,
966
+ generic_head_shift,
967
+ stream_skip_bytes,
968
+ generic_read_frame_body,
969
+ stream_back_bytes,
970
+ stream_seek_frame,
971
+ generic_tell,
972
+ stream_rewind,
973
+ buffered_forget
974
+ } ,
975
+ { /* READER_BUF_ICY_STREAM */
976
+ default_init,
977
+ stream_close,
978
+ buffered_fullread,
979
+ generic_head_read,
980
+ generic_head_shift,
981
+ stream_skip_bytes,
982
+ generic_read_frame_body,
983
+ stream_back_bytes,
984
+ stream_seek_frame,
985
+ generic_tell,
986
+ stream_rewind,
987
+ buffered_forget
988
+ },
989
+ #ifdef READ_SYSTEM
990
+ ,{
991
+ system_init,
992
+ NULL, /* filled in by system_init() */
993
+ fullread,
994
+ NULL,
995
+ NULL,
996
+ NULL,
997
+ NULL,
998
+ NULL,
999
+ NULL,
1000
+ NULL,
1001
+ NULL,
1002
+ NULL,
1003
+ }
1004
+ #endif
1005
+ };
1006
+
1007
+ static struct reader bad_reader =
1008
+ {
1009
+ bad_init,
1010
+ bad_close,
1011
+ bad_fullread,
1012
+ bad_head_read,
1013
+ bad_head_shift,
1014
+ bad_skip_bytes,
1015
+ bad_read_frame_body,
1016
+ bad_back_bytes,
1017
+ bad_seek_frame,
1018
+ bad_tell,
1019
+ bad_rewind,
1020
+ NULL
1021
+ };
1022
+
1023
+ static int default_init(mpg123_handle *fr)
1024
+ {
1025
+ #ifdef TIMEOUT_READ
1026
+ if(fr->p.timeout > 0)
1027
+ {
1028
+ int flags;
1029
+ if(fr->rdat.r_read != NULL)
1030
+ {
1031
+ error("Timeout reading does not work with user-provided read function. Implement it yourself!");
1032
+ return -1;
1033
+ }
1034
+ flags = fcntl(fr->rdat.filept, F_GETFL);
1035
+ flags |= O_NONBLOCK;
1036
+ fcntl(fr->rdat.filept, F_SETFL, flags);
1037
+ fr->rdat.fdread = timeout_read;
1038
+ fr->rdat.timeout_sec = fr->p.timeout;
1039
+ fr->rdat.flags |= READER_NONBLOCK;
1040
+ }
1041
+ else
1042
+ #endif
1043
+ fr->rdat.fdread = plain_read;
1044
+
1045
+ fr->rdat.read = fr->rdat.r_read != NULL ? fr->rdat.r_read : posix_read;
1046
+ fr->rdat.lseek = fr->rdat.r_lseek != NULL ? fr->rdat.r_lseek : posix_lseek;
1047
+ #ifndef NO_ICY
1048
+ /* ICY streams of any sort shall not be seekable. */
1049
+ if(fr->p.icy_interval > 0) fr->rdat.lseek = nix_lseek;
1050
+ #endif
1051
+
1052
+ fr->rdat.filelen = get_fileinfo(fr);
1053
+ fr->rdat.filepos = 0;
1054
+ /*
1055
+ Don't enable seeking on ICY streams, just plain normal files.
1056
+ This check is necessary since the client can enforce ICY parsing on files that would otherwise be seekable.
1057
+ It is a task for the future to make the ICY parsing safe with seeks ... or not.
1058
+ */
1059
+ if(fr->rdat.filelen >= 0)
1060
+ {
1061
+ fr->rdat.flags |= READER_SEEKABLE;
1062
+ if(!strncmp((char*)fr->id3buf,"TAG",3))
1063
+ {
1064
+ fr->rdat.flags |= READER_ID3TAG;
1065
+ fr->metaflags |= MPG123_NEW_ID3;
1066
+ }
1067
+ }
1068
+ /* Switch reader to a buffered one, if allowed. */
1069
+ else if(fr->p.flags & MPG123_SEEKBUFFER)
1070
+ {
1071
+ #ifdef NO_FEEDER
1072
+ error("Buffered readers not supported in this build.");
1073
+ fr->err = MPG123_MISSING_FEATURE;
1074
+ return -1;
1075
+ #else
1076
+ if (fr->rd == &readers[READER_STREAM])
1077
+ {
1078
+ fr->rd = &readers[READER_BUF_STREAM];
1079
+ fr->rdat.fullread = plain_fullread;
1080
+ }
1081
+ #ifndef NO_ICY
1082
+ else if(fr->rd == &readers[READER_ICY_STREAM])
1083
+ {
1084
+ fr->rd = &readers[READER_BUF_ICY_STREAM];
1085
+ fr->rdat.fullread = icy_fullread;
1086
+ }
1087
+ #endif
1088
+ else
1089
+ {
1090
+ if(NOQUIET) error("mpg123 Programmer's fault: invalid reader");
1091
+ return -1;
1092
+ }
1093
+ bc_init(&fr->rdat.buffer);
1094
+ fr->rdat.filelen = 0; /* We carry the offset, but never know how big the stream is. */
1095
+ fr->rdat.flags |= READER_BUFFERED;
1096
+ #endif /* NO_FEEDER */
1097
+ }
1098
+ return 0;
1099
+ }
1100
+
1101
+
1102
+ void open_bad(mpg123_handle *mh)
1103
+ {
1104
+ debug("open_bad");
1105
+ #ifndef NO_ICY
1106
+ clear_icy(&mh->icy);
1107
+ #endif
1108
+ mh->rd = &bad_reader;
1109
+ mh->rdat.flags = 0;
1110
+ #ifndef NO_FEEDER
1111
+ bc_init(&mh->rdat.buffer);
1112
+ #endif
1113
+ mh->rdat.filelen = -1;
1114
+ }
1115
+
1116
+ int open_feed(mpg123_handle *fr)
1117
+ {
1118
+ debug("feed reader");
1119
+ #ifdef NO_FEEDER
1120
+ error("Buffered readers not supported in this build.");
1121
+ fr->err = MPG123_MISSING_FEATURE;
1122
+ return -1;
1123
+ #else
1124
+ #ifndef NO_ICY
1125
+ if(fr->p.icy_interval > 0)
1126
+ {
1127
+ if(NOQUIET) error("Feed reader cannot do ICY parsing!");
1128
+
1129
+ return -1;
1130
+ }
1131
+ clear_icy(&fr->icy);
1132
+ #endif
1133
+ fr->rd = &readers[READER_FEED];
1134
+ fr->rdat.flags = 0;
1135
+ if(fr->rd->init(fr) < 0) return -1;
1136
+
1137
+ debug("feed reader init successful");
1138
+ return 0;
1139
+ #endif /* NO_FEEDER */
1140
+ }
1141
+
1142
+ /* Final code common to open_stream and open_stream_handle. */
1143
+ static int open_finish(mpg123_handle *fr)
1144
+ {
1145
+ #ifndef NO_ICY
1146
+ if(fr->p.icy_interval > 0)
1147
+ {
1148
+ debug("ICY reader");
1149
+ fr->icy.interval = fr->p.icy_interval;
1150
+ fr->icy.next = fr->icy.interval;
1151
+ fr->rd = &readers[READER_ICY_STREAM];
1152
+ }
1153
+ else
1154
+ #endif
1155
+ {
1156
+ fr->rd = &readers[READER_STREAM];
1157
+ debug("stream reader");
1158
+ }
1159
+
1160
+ if(fr->rd->init(fr) < 0) return -1;
1161
+
1162
+ return MPG123_OK;
1163
+ }
1164
+
1165
+ int open_stream(mpg123_handle *fr, const char *bs_filenam, int fd)
1166
+ {
1167
+ int filept_opened = 1;
1168
+ int filept; /* descriptor of opened file/stream */
1169
+
1170
+ clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
1171
+
1172
+ if(!bs_filenam) /* no file to open, got a descriptor (stdin) */
1173
+ {
1174
+ filept = fd;
1175
+ filept_opened = 0; /* and don't try to close it... */
1176
+ }
1177
+ #ifndef O_BINARY
1178
+ #define O_BINARY (0)
1179
+ #endif
1180
+ else if((filept = compat_open(bs_filenam, O_RDONLY|O_BINARY)) < 0) /* a plain old file to open... */
1181
+ {
1182
+ if(NOQUIET) error2("Cannot open file %s: %s", bs_filenam, strerror(errno));
1183
+ fr->err = MPG123_BAD_FILE;
1184
+ return MPG123_ERR; /* error... */
1185
+ }
1186
+
1187
+ /* now we have something behind filept and can init the reader */
1188
+ fr->rdat.filelen = -1;
1189
+ fr->rdat.filept = filept;
1190
+ fr->rdat.flags = 0;
1191
+ if(filept_opened) fr->rdat.flags |= READER_FD_OPENED;
1192
+
1193
+ return open_finish(fr);
1194
+ }
1195
+
1196
+ int open_stream_handle(mpg123_handle *fr, void *iohandle)
1197
+ {
1198
+ clear_icy(&fr->icy); /* can be done inside frame_clear ...? */
1199
+ fr->rdat.filelen = -1;
1200
+ fr->rdat.filept = -1;
1201
+ fr->rdat.iohandle = iohandle;
1202
+ fr->rdat.flags = 0;
1203
+ fr->rdat.flags |= READER_HANDLEIO;
1204
+
1205
+ return open_finish(fr);
1206
+ }
1207
+
1208
+ /* Wrappers for actual reading/seeking... I'm full of wrappers here. */
1209
+ static off_t io_seek(struct reader_data *rdat, off_t offset, int whence)
1210
+ {
1211
+ if(rdat->flags & READER_HANDLEIO)
1212
+ {
1213
+ if(rdat->r_lseek_handle != NULL)
1214
+ {
1215
+ return rdat->r_lseek_handle(rdat->iohandle, offset, whence);
1216
+ }
1217
+ else return -1;
1218
+ }
1219
+ else
1220
+ return rdat->lseek(rdat->filept, offset, whence);
1221
+ }
1222
+
1223
+ static ssize_t io_read(struct reader_data *rdat, void *buf, size_t count)
1224
+ {
1225
+ if(rdat->flags & READER_HANDLEIO)
1226
+ {
1227
+ if(rdat->r_read_handle != NULL)
1228
+ {
1229
+ return rdat->r_read_handle(rdat->iohandle, buf, count);
1230
+ }
1231
+ else return -1;
1232
+ }
1233
+ else
1234
+ return rdat->read(rdat->filept, buf, count);
1235
+ }