seal 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/LICENSE +13 -0
- data/README.md +265 -0
- data/ext/seal/extconf.rb +45 -0
- data/include/al/al.h +724 -0
- data/include/al/alc.h +277 -0
- data/include/al/efx-presets.h +402 -0
- data/include/al/efx.h +758 -0
- data/include/mpg123/mpg123.h +1034 -0
- data/include/ogg/config_types.h +25 -0
- data/include/ogg/ogg.h +210 -0
- data/include/ogg/os_types.h +147 -0
- data/include/seal.h +23 -0
- data/include/seal/buf.h +143 -0
- data/include/seal/core.h +95 -0
- data/include/seal/efs.h +112 -0
- data/include/seal/err.h +93 -0
- data/include/seal/fmt.h +58 -0
- data/include/seal/listener.h +103 -0
- data/include/seal/raw.h +86 -0
- data/include/seal/rvb.h +520 -0
- data/include/seal/src.h +413 -0
- data/include/seal/stream.h +81 -0
- data/include/vorbis/codec.h +243 -0
- data/include/vorbis/vorbisfile.h +206 -0
- data/mpg123/AUTHORS +150 -0
- data/mpg123/COPYING +773 -0
- data/mpg123/ChangeLog +3 -0
- data/mpg123/INSTALL +111 -0
- data/mpg123/Makefile.am +99 -0
- data/mpg123/Makefile.in +1043 -0
- data/mpg123/NEWS +1200 -0
- data/mpg123/NEWS.libmpg123 +133 -0
- data/mpg123/README +203 -0
- data/mpg123/TODO +38 -0
- data/mpg123/aclocal.m4 +1168 -0
- data/mpg123/build/config.guess +1530 -0
- data/mpg123/build/config.sub +1782 -0
- data/mpg123/build/depcomp +707 -0
- data/mpg123/build/install-sh +527 -0
- data/mpg123/build/ltmain.sh +9655 -0
- data/mpg123/build/missing +330 -0
- data/mpg123/configure +20267 -0
- data/mpg123/configure.ac +2178 -0
- data/mpg123/doc/ACCURACY +2 -0
- data/mpg123/doc/BENCHMARKING +110 -0
- data/mpg123/doc/BUGS +3 -0
- data/mpg123/doc/CONTACT +17 -0
- data/mpg123/doc/LICENSE +22 -0
- data/mpg123/doc/Makefile.am +32 -0
- data/mpg123/doc/Makefile.in +490 -0
- data/mpg123/doc/PATENTS +39 -0
- data/mpg123/doc/README.3DNOW +56 -0
- data/mpg123/doc/README.gain +171 -0
- data/mpg123/doc/README.remote +218 -0
- data/mpg123/doc/ROAD_TO_LGPL +270 -0
- data/mpg123/doc/THANKS +13 -0
- data/mpg123/doc/TODO +63 -0
- data/mpg123/doc/doxy_examples.c +21 -0
- data/mpg123/doc/doxygen.conf +41 -0
- data/mpg123/doc/doxyhead.xhtml +12 -0
- data/mpg123/doc/examples/dump_seekindex.c +41 -0
- data/mpg123/doc/examples/extract_frames.c +92 -0
- data/mpg123/doc/examples/feedseek.c +238 -0
- data/mpg123/doc/examples/id3dump.c +178 -0
- data/mpg123/doc/examples/mpg123_to_wav.c +118 -0
- data/mpg123/doc/examples/mpglib.c +92 -0
- data/mpg123/doc/examples/scan.c +47 -0
- data/mpg123/doc/libmpg123_speed.txt +84 -0
- data/mpg123/equalize.dat +37 -0
- data/mpg123/libmpg123.pc.in +11 -0
- data/mpg123/m4/addrconfig.m4 +34 -0
- data/mpg123/m4/libtool.m4 +7982 -0
- data/mpg123/m4/ltoptions.m4 +384 -0
- data/mpg123/m4/ltsugar.m4 +123 -0
- data/mpg123/m4/ltversion.m4 +23 -0
- data/mpg123/m4/lt~obsolete.m4 +98 -0
- data/mpg123/makedll.sh +19 -0
- data/mpg123/man1/mpg123.1 +512 -0
- data/mpg123/mpg123.spec +68 -0
- data/mpg123/mpg123.spec.in +68 -0
- data/mpg123/ports/MSVC++/2005/libmpg123/libmpg123.vcproj +741 -0
- data/mpg123/ports/MSVC++/2008/dump_seekindex/dump_seekindex.vcproj +194 -0
- data/mpg123/ports/MSVC++/2008/feedseek/feedseek.vcproj +195 -0
- data/mpg123/ports/MSVC++/2008/libmpg123/libmpg123.vcproj +1357 -0
- data/mpg123/ports/MSVC++/2008/mpg123.sln +44 -0
- data/mpg123/ports/MSVC++/2008/mpglib/mpglib.vcproj +191 -0
- data/mpg123/ports/MSVC++/2008/scan/scan.vcproj +195 -0
- data/mpg123/ports/MSVC++/2008clr/2008clr.sln +81 -0
- data/mpg123/ports/MSVC++/2008clr/examples/ReplaceReaderclr/Program.cs +435 -0
- data/mpg123/ports/MSVC++/2008clr/examples/ReplaceReaderclr/Properties/AssemblyInfo.cs +36 -0
- data/mpg123/ports/MSVC++/2008clr/examples/ReplaceReaderclr/ReplaceReaderclr.csproj +72 -0
- data/mpg123/ports/MSVC++/2008clr/examples/feedseekclr/Program.cs +331 -0
- data/mpg123/ports/MSVC++/2008clr/examples/feedseekclr/Properties/AssemblyInfo.cs +36 -0
- data/mpg123/ports/MSVC++/2008clr/examples/feedseekclr/feedseekclr.csproj +71 -0
- data/mpg123/ports/MSVC++/2008clr/examples/scanclr/Program.cs +79 -0
- data/mpg123/ports/MSVC++/2008clr/examples/scanclr/Properties/AssemblyInfo.cs +36 -0
- data/mpg123/ports/MSVC++/2008clr/examples/scanclr/scanclr.csproj +70 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/AssemblyInfo.cpp +76 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/ReadMe.txt +165 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/advanced.cpp +91 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/advanced.h +130 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/dllmain.cpp +19 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/enum.h +218 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/error.cpp +48 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/error.h +134 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/id3v1.cpp +92 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/id3v1.h +132 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/id3v2.cpp +138 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/id3v2.h +152 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/mpg123clr.cpp +896 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/mpg123clr.h +953 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/mpg123clr.rc +102 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/mpg123clr.vcproj +328 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/resource.h +14 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/stdafx.cpp +8 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/stdafx.h +38 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/string.cpp +166 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/string.h +265 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/targetver.h +24 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/text.cpp +67 -0
- data/mpg123/ports/MSVC++/2008clr/mpg123clr/text.h +111 -0
- data/mpg123/ports/MSVC++/2010/dump_seekindex/dump_seekindex.vcxproj +90 -0
- data/mpg123/ports/MSVC++/2010/dump_seekindex/dump_seekindex.vcxproj.filters +6 -0
- data/mpg123/ports/MSVC++/2010/feedseek/feedseek.vcxproj +95 -0
- data/mpg123/ports/MSVC++/2010/feedseek/feedseek.vcxproj.filters +6 -0
- data/mpg123/ports/MSVC++/2010/libmpg123/libmpg123.vcxproj +960 -0
- data/mpg123/ports/MSVC++/2010/libmpg123/libmpg123.vcxproj.user +3 -0
- data/mpg123/ports/MSVC++/2010/libmpg123/yasm.exe +0 -0
- data/mpg123/ports/MSVC++/2010/mpg123.sln +38 -0
- data/mpg123/ports/MSVC++/2010/scan/scan.vcxproj +93 -0
- data/mpg123/ports/MSVC++/2010/scan/scan.vcxproj.filters +6 -0
- data/mpg123/ports/MSVC++/CMP3Stream/INCLUDE/CORE/CORE_FileIn.H +15 -0
- data/mpg123/ports/MSVC++/CMP3Stream/INCLUDE/CORE/SourceFilter_MP3.H +139 -0
- data/mpg123/ports/MSVC++/CMP3Stream/INCLUDE/IIEP_Def.H +206 -0
- data/mpg123/ports/MSVC++/CMP3Stream/INCLUDE/IIEP_FileIn.H +167 -0
- data/mpg123/ports/MSVC++/CMP3Stream/README +4 -0
- data/mpg123/ports/MSVC++/CMP3Stream/SOURCE/CORE_FileIn.CPP +462 -0
- data/mpg123/ports/MSVC++/CMP3Stream/SOURCE/CORE_Log.CPP +122 -0
- data/mpg123/ports/MSVC++/CMP3Stream/SOURCE/CORE_Mutex.CPP +35 -0
- data/mpg123/ports/MSVC++/CMP3Stream/SOURCE/SourceFilter_MP3Stream.CPP +586 -0
- data/mpg123/ports/MSVC++/CMP3Stream/libMPG123/PLACE_LIBMPG123_SOURCES_HERE +0 -0
- data/mpg123/ports/MSVC++/CMP3Stream/libMPG123/libMPG123.vcproj +245 -0
- data/mpg123/ports/MSVC++/config.h +35 -0
- data/mpg123/ports/MSVC++/examples/feedseek.c +240 -0
- data/mpg123/ports/MSVC++/examples/scan.c +47 -0
- data/mpg123/ports/MSVC++/mpg123.h +46 -0
- data/mpg123/ports/MSVC++/msvc.c +59 -0
- data/mpg123/ports/README +26 -0
- data/mpg123/ports/Sony_PSP/Makefile.psp +38 -0
- data/mpg123/ports/Sony_PSP/README +11 -0
- data/mpg123/ports/Sony_PSP/config.h +368 -0
- data/mpg123/ports/Sony_PSP/readers.c.patch +2 -0
- data/mpg123/ports/Xcode/config.h +197 -0
- data/mpg123/ports/Xcode/mpg123.h +17 -0
- data/mpg123/ports/Xcode/mpg123.xcodeproj/project.pbxproj +670 -0
- data/mpg123/ports/mpg123_.pas +478 -0
- data/mpg123/scripts/benchmark-cpu.pl +56 -0
- data/mpg123/scripts/tag_lyrics.py +76 -0
- data/mpg123/src/Makefile.am +186 -0
- data/mpg123/src/Makefile.in +1097 -0
- data/mpg123/src/audio.c +725 -0
- data/mpg123/src/audio.h +106 -0
- data/mpg123/src/buffer.c +312 -0
- data/mpg123/src/buffer.h +45 -0
- data/mpg123/src/common.c +240 -0
- data/mpg123/src/common.h +29 -0
- data/mpg123/src/config.h.in +436 -0
- data/mpg123/src/control_generic.c +809 -0
- data/mpg123/src/equalizer.c +48 -0
- data/mpg123/src/genre.c +271 -0
- data/mpg123/src/genre.h +15 -0
- data/mpg123/src/getlopt.c +148 -0
- data/mpg123/src/getlopt.h +77 -0
- data/mpg123/src/httpget.c +700 -0
- data/mpg123/src/httpget.h +66 -0
- data/mpg123/src/legacy_module.c +74 -0
- data/mpg123/src/libmpg123/Makefile.am +141 -0
- data/mpg123/src/libmpg123/Makefile.in +919 -0
- data/mpg123/src/libmpg123/compat.c +138 -0
- data/mpg123/src/libmpg123/compat.h +178 -0
- data/mpg123/src/libmpg123/dct36_3dnow.S +505 -0
- data/mpg123/src/libmpg123/dct36_3dnowext.S +512 -0
- data/mpg123/src/libmpg123/dct64.c +174 -0
- data/mpg123/src/libmpg123/dct64_3dnow.S +712 -0
- data/mpg123/src/libmpg123/dct64_3dnowext.S +714 -0
- data/mpg123/src/libmpg123/dct64_altivec.c +315 -0
- data/mpg123/src/libmpg123/dct64_i386.c +336 -0
- data/mpg123/src/libmpg123/dct64_i486.c +342 -0
- data/mpg123/src/libmpg123/dct64_mmx.S +811 -0
- data/mpg123/src/libmpg123/dct64_neon.S +297 -0
- data/mpg123/src/libmpg123/dct64_neon_float.S +270 -0
- data/mpg123/src/libmpg123/dct64_sse.S +454 -0
- data/mpg123/src/libmpg123/dct64_sse_float.S +401 -0
- data/mpg123/src/libmpg123/dct64_x86_64.S +464 -0
- data/mpg123/src/libmpg123/dct64_x86_64_float.S +426 -0
- data/mpg123/src/libmpg123/debug.h +171 -0
- data/mpg123/src/libmpg123/decode.h +268 -0
- data/mpg123/src/libmpg123/dither.c +119 -0
- data/mpg123/src/libmpg123/dither.h +23 -0
- data/mpg123/src/libmpg123/equalizer.c +17 -0
- data/mpg123/src/libmpg123/equalizer_3dnow.S +70 -0
- data/mpg123/src/libmpg123/feature.c +106 -0
- data/mpg123/src/libmpg123/format.c +521 -0
- data/mpg123/src/libmpg123/frame.c +1046 -0
- data/mpg123/src/libmpg123/frame.h +410 -0
- data/mpg123/src/libmpg123/gapless.h +119 -0
- data/mpg123/src/libmpg123/getbits.h +100 -0
- data/mpg123/src/libmpg123/getcpuflags.S +91 -0
- data/mpg123/src/libmpg123/getcpuflags.h +47 -0
- data/mpg123/src/libmpg123/huffman.h +340 -0
- data/mpg123/src/libmpg123/icy.c +32 -0
- data/mpg123/src/libmpg123/icy.h +38 -0
- data/mpg123/src/libmpg123/icy2utf8.c +438 -0
- data/mpg123/src/libmpg123/icy2utf8.h +10 -0
- data/mpg123/src/libmpg123/id3.c +999 -0
- data/mpg123/src/libmpg123/id3.h +43 -0
- data/mpg123/src/libmpg123/index.c +134 -0
- data/mpg123/src/libmpg123/index.h +59 -0
- data/mpg123/src/libmpg123/intsym.h +256 -0
- data/mpg123/src/libmpg123/l12_integer_tables.h +278 -0
- data/mpg123/src/libmpg123/l2tables.h +164 -0
- data/mpg123/src/libmpg123/l3_integer_tables.h +1002 -0
- data/mpg123/src/libmpg123/layer1.c +155 -0
- data/mpg123/src/libmpg123/layer2.c +371 -0
- data/mpg123/src/libmpg123/layer3.c +2053 -0
- data/mpg123/src/libmpg123/lfs_alias.c +252 -0
- data/mpg123/src/libmpg123/lfs_wrap.c +751 -0
- data/mpg123/src/libmpg123/libmpg123.c +1607 -0
- data/mpg123/src/libmpg123/mangle.h +74 -0
- data/mpg123/src/libmpg123/mpeghead.h +87 -0
- data/mpg123/src/libmpg123/mpg123.h.in +1075 -0
- data/mpg123/src/libmpg123/mpg123lib_intern.h +338 -0
- data/mpg123/src/libmpg123/ntom.c +148 -0
- data/mpg123/src/libmpg123/optimize.c +964 -0
- data/mpg123/src/libmpg123/optimize.h +219 -0
- data/mpg123/src/libmpg123/parse.c +1179 -0
- data/mpg123/src/libmpg123/parse.h +25 -0
- data/mpg123/src/libmpg123/reader.h +137 -0
- data/mpg123/src/libmpg123/readers.c +1235 -0
- data/mpg123/src/libmpg123/sample.h +152 -0
- data/mpg123/src/libmpg123/stringbuf.c +163 -0
- data/mpg123/src/libmpg123/synth.c +816 -0
- data/mpg123/src/libmpg123/synth.h +196 -0
- data/mpg123/src/libmpg123/synth_3dnow.S +318 -0
- data/mpg123/src/libmpg123/synth_3dnowext.S +6 -0
- data/mpg123/src/libmpg123/synth_8bit.c +142 -0
- data/mpg123/src/libmpg123/synth_8bit.h +86 -0
- data/mpg123/src/libmpg123/synth_altivec.c +1057 -0
- data/mpg123/src/libmpg123/synth_arm.S +271 -0
- data/mpg123/src/libmpg123/synth_arm_accurate.S +287 -0
- data/mpg123/src/libmpg123/synth_i486.c +252 -0
- data/mpg123/src/libmpg123/synth_i586.S +336 -0
- data/mpg123/src/libmpg123/synth_i586_dither.S +375 -0
- data/mpg123/src/libmpg123/synth_mmx.S +125 -0
- data/mpg123/src/libmpg123/synth_mono.h +64 -0
- data/mpg123/src/libmpg123/synth_neon.S +123 -0
- data/mpg123/src/libmpg123/synth_neon_accurate.S +173 -0
- data/mpg123/src/libmpg123/synth_neon_float.S +149 -0
- data/mpg123/src/libmpg123/synth_neon_s32.S +168 -0
- data/mpg123/src/libmpg123/synth_ntom.h +213 -0
- data/mpg123/src/libmpg123/synth_real.c +404 -0
- data/mpg123/src/libmpg123/synth_s32.c +411 -0
- data/mpg123/src/libmpg123/synth_sse.S +6 -0
- data/mpg123/src/libmpg123/synth_sse3d.h +246 -0
- data/mpg123/src/libmpg123/synth_sse_accurate.S +294 -0
- data/mpg123/src/libmpg123/synth_sse_float.S +241 -0
- data/mpg123/src/libmpg123/synth_sse_s32.S +306 -0
- data/mpg123/src/libmpg123/synth_stereo_neon.S +175 -0
- data/mpg123/src/libmpg123/synth_stereo_neon_accurate.S +262 -0
- data/mpg123/src/libmpg123/synth_stereo_neon_float.S +220 -0
- data/mpg123/src/libmpg123/synth_stereo_neon_s32.S +247 -0
- data/mpg123/src/libmpg123/synth_stereo_sse_accurate.S +508 -0
- data/mpg123/src/libmpg123/synth_stereo_sse_float.S +416 -0
- data/mpg123/src/libmpg123/synth_stereo_sse_s32.S +540 -0
- data/mpg123/src/libmpg123/synth_stereo_x86_64.S +335 -0
- data/mpg123/src/libmpg123/synth_stereo_x86_64_accurate.S +454 -0
- data/mpg123/src/libmpg123/synth_stereo_x86_64_float.S +396 -0
- data/mpg123/src/libmpg123/synth_stereo_x86_64_s32.S +473 -0
- data/mpg123/src/libmpg123/synth_x86_64.S +244 -0
- data/mpg123/src/libmpg123/synth_x86_64_accurate.S +301 -0
- data/mpg123/src/libmpg123/synth_x86_64_float.S +259 -0
- data/mpg123/src/libmpg123/synth_x86_64_s32.S +312 -0
- data/mpg123/src/libmpg123/synths.h +52 -0
- data/mpg123/src/libmpg123/tabinit.c +294 -0
- data/mpg123/src/libmpg123/tabinit_mmx.S +210 -0
- data/mpg123/src/libmpg123/testcpu.c +35 -0
- data/mpg123/src/libmpg123/true.h +14 -0
- data/mpg123/src/local.c +63 -0
- data/mpg123/src/local.h +21 -0
- data/mpg123/src/metaprint.c +373 -0
- data/mpg123/src/metaprint.h +17 -0
- data/mpg123/src/module.c +306 -0
- data/mpg123/src/module.h +48 -0
- data/mpg123/src/mpg123.c +1405 -0
- data/mpg123/src/mpg123app.h +171 -0
- data/mpg123/src/output/Makefile.am +213 -0
- data/mpg123/src/output/Makefile.in +1238 -0
- data/mpg123/src/output/aix.c +300 -0
- data/mpg123/src/output/alib.c +209 -0
- data/mpg123/src/output/alsa.c +297 -0
- data/mpg123/src/output/arts.c +117 -0
- data/mpg123/src/output/coreaudio.c +370 -0
- data/mpg123/src/output/dummy.c +78 -0
- data/mpg123/src/output/esd.c +167 -0
- data/mpg123/src/output/hp.c +184 -0
- data/mpg123/src/output/jack.c +450 -0
- data/mpg123/src/output/mint.c +197 -0
- data/mpg123/src/output/nas.c +335 -0
- data/mpg123/src/output/openal.c +197 -0
- data/mpg123/src/output/os2.c +665 -0
- data/mpg123/src/output/oss.c +319 -0
- data/mpg123/src/output/portaudio.c +255 -0
- data/mpg123/src/output/pulse.c +164 -0
- data/mpg123/src/output/sdl.c +206 -0
- data/mpg123/src/output/sgi.c +213 -0
- data/mpg123/src/output/sndio.c +161 -0
- data/mpg123/src/output/sun.c +281 -0
- data/mpg123/src/output/win32.c +229 -0
- data/mpg123/src/playlist.c +596 -0
- data/mpg123/src/playlist.h +52 -0
- data/mpg123/src/resolver.c +319 -0
- data/mpg123/src/resolver.h +25 -0
- data/mpg123/src/sfifo.c +146 -0
- data/mpg123/src/sfifo.h +95 -0
- data/mpg123/src/streamdump.c +74 -0
- data/mpg123/src/streamdump.h +20 -0
- data/mpg123/src/term.c +479 -0
- data/mpg123/src/term.h +81 -0
- data/mpg123/src/tests/noise.c +52 -0
- data/mpg123/src/tests/plain_id3.c +109 -0
- data/mpg123/src/tests/seek_accuracy.c +261 -0
- data/mpg123/src/tests/seek_whence.c +56 -0
- data/mpg123/src/tests/testtext.h +34 -0
- data/mpg123/src/tests/text.c +80 -0
- data/mpg123/src/wav.c +464 -0
- data/mpg123/src/wavhead.h +68 -0
- data/mpg123/src/win32_net.c +599 -0
- data/mpg123/src/win32_support.c +191 -0
- data/mpg123/src/win32_support.h +152 -0
- data/mpg123/src/xfermem.c +321 -0
- data/mpg123/src/xfermem.h +74 -0
- data/mpg123/windows-builds.sh +137 -0
- data/msvc/lib/OpenAL32.lib +0 -0
- data/spec/fixtures/heal.ogg +0 -0
- data/spec/fixtures/tone_up.wav +0 -0
- data/spec/seal/buffer_spec.rb +37 -0
- data/spec/seal/core_spec.rb +29 -0
- data/spec/seal/effect_slot_spec.rb +38 -0
- data/spec/seal/listener_spec.rb +33 -0
- data/spec/seal/reverb_spec.rb +51 -0
- data/spec/seal/source_spec.rb +370 -0
- data/spec/seal/stream_spec.rb +38 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/attribute_examples.rb +75 -0
- data/spec/support/audio_object_with_format.rb +27 -0
- data/spec/support/movable_object.rb +22 -0
- data/src/libogg/bitwise.c +857 -0
- data/src/libogg/framing.c +2093 -0
- data/src/libvorbis/backends.h +144 -0
- data/src/libvorbis/bitrate.c +253 -0
- data/src/libvorbis/bitrate.h +59 -0
- data/src/libvorbis/block.c +1046 -0
- data/src/libvorbis/codebook.c +484 -0
- data/src/libvorbis/codebook.h +119 -0
- data/src/libvorbis/codec_internal.h +167 -0
- data/src/libvorbis/envelope.c +375 -0
- data/src/libvorbis/envelope.h +80 -0
- data/src/libvorbis/floor0.c +221 -0
- data/src/libvorbis/floor1.c +1100 -0
- data/src/libvorbis/highlevel.h +58 -0
- data/src/libvorbis/info.c +668 -0
- data/src/libvorbis/lookup.c +94 -0
- data/src/libvorbis/lookup.h +32 -0
- data/src/libvorbis/lookup_data.h +192 -0
- data/src/libvorbis/lpc.c +160 -0
- data/src/libvorbis/lpc.h +29 -0
- data/src/libvorbis/lsp.c +456 -0
- data/src/libvorbis/lsp.h +28 -0
- data/src/libvorbis/mapping0.c +816 -0
- data/src/libvorbis/masking.h +785 -0
- data/src/libvorbis/mdct.c +563 -0
- data/src/libvorbis/mdct.h +71 -0
- data/src/libvorbis/misc.h +57 -0
- data/src/libvorbis/os.h +186 -0
- data/src/libvorbis/psy.c +1206 -0
- data/src/libvorbis/psy.h +154 -0
- data/src/libvorbis/registry.c +45 -0
- data/src/libvorbis/registry.h +32 -0
- data/src/libvorbis/res0.c +889 -0
- data/src/libvorbis/scales.h +90 -0
- data/src/libvorbis/sharedbook.c +579 -0
- data/src/libvorbis/smallft.c +1255 -0
- data/src/libvorbis/smallft.h +34 -0
- data/src/libvorbis/synthesis.c +184 -0
- data/src/libvorbis/vorbisfile.c +2337 -0
- data/src/libvorbis/window.c +2135 -0
- data/src/libvorbis/window.h +26 -0
- data/src/rubyext.c +2329 -0
- data/src/seal/buf.c +124 -0
- data/src/seal/core.c +283 -0
- data/src/seal/efs.c +74 -0
- data/src/seal/err.c +118 -0
- data/src/seal/fmt.c +86 -0
- data/src/seal/listener.c +111 -0
- data/src/seal/mpg.c +174 -0
- data/src/seal/mpg.h +24 -0
- data/src/seal/ov.c +180 -0
- data/src/seal/ov.h +22 -0
- data/src/seal/raw.c +59 -0
- data/src/seal/reader.c +102 -0
- data/src/seal/reader.h +59 -0
- data/src/seal/rvb.c +368 -0
- data/src/seal/src.c +654 -0
- data/src/seal/stream.c +109 -0
- data/src/seal/threading.c +66 -0
- data/src/seal/threading.h +20 -0
- data/src/seal/wav.c +297 -0
- data/src/seal/wav.h +23 -0
- data/src/win32api.rb +29 -0
- 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
|
+
}
|