#include "i_soundinternal.h" #ifdef HAVE_MPG123 static bool inited = false; off_t MPG123Decoder::mem_lseek(void *handle, off_t offset, int whence) { MPG123Decoder *self = reinterpret_cast(handle); switch(whence) { case SEEK_SET: if(offset < 0 || offset > (off_t)self->MemLength) return -1; self->MemPos = offset; break; case SEEK_CUR: if((offset > 0 && (off_t)(self->MemLength-self->MemPos) < offset) || (offset < 0 && (off_t)self->MemPos < -offset)) return -1; self->MemPos += offset; break; case SEEK_END: if(offset > 0 || -offset > (off_t)self->MemLength) return -1; self->MemPos = self->MemLength + offset; break; default: return -1; } return self->MemPos; } ssize_t MPG123Decoder::mem_read(void *handle, void *buffer, size_t bytes) { MPG123Decoder *self = reinterpret_cast(handle); if(bytes > self->MemLength-self->MemPos) bytes = self->MemLength-self->MemPos; memcpy(buffer, self->MemData+self->MemPos, bytes); self->MemPos += bytes; return bytes; } MPG123Decoder::~MPG123Decoder() { if(MPG123) { mpg123_close(MPG123); mpg123_delete(MPG123); MPG123 = 0; } } bool MPG123Decoder::open(const char *data, size_t length) { if(!inited) { if(mpg123_init() != MPG123_OK) return false; inited = true; } MemData = data; MemPos = 0; MemLength = length; MPG123 = mpg123_new(NULL, NULL); if(mpg123_replace_reader_handle(MPG123, mem_read, mem_lseek, NULL) == MPG123_OK && mpg123_open_handle(MPG123, this) == MPG123_OK) { int enc, channels; long srate; if(mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK) { if((channels == 1 || channels == 2) && srate > 0 && mpg123_format_none(MPG123) == MPG123_OK && mpg123_format(MPG123, srate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK) { // All OK Done = false; return true; } } mpg123_close(MPG123); } mpg123_delete(MPG123); MPG123 = 0; return false; } void MPG123Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) { int enc = 0, channels = 0; long srate = 0; mpg123_getformat(MPG123, &srate, &channels, &enc); *samplerate = srate; if(channels == 2) *chans = ChannelConfig_Stereo; else *chans = ChannelConfig_Mono; *type = SampleType_Int16; } size_t MPG123Decoder::read(char *buffer, size_t bytes) { size_t amt = 0; while(!Done && bytes > 0) { size_t got = 0; int ret = mpg123_read(MPG123, (unsigned char*)buffer, bytes, &got); bytes -= got; buffer += got; amt += got; if(ret == MPG123_NEW_FORMAT || ret == MPG123_DONE || got == 0) { Done = true; break; } } return amt; } bool MPG123Decoder::open(const char *fname, size_t offset, size_t length) { return false; } bool MPG123Decoder::seek(size_t ms_offset) { int enc, channels; long srate; if(mpg123_getformat(MPG123, &srate, &channels, &enc) == MPG123_OK) { size_t smp_offset = (size_t)((double)ms_offset / 1000. * srate); if(mpg123_seek(MPG123, smp_offset, SEEK_SET) >= 0) { Done = false; return true; } } return false; } size_t MPG123Decoder::getSampleOffset() { return mpg123_tell(MPG123); } #endif