X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Foggdecoder.cpp;h=cd2def8ca78d1d86488d2ceb2d15a25ce9a916e7;hb=d365c5394308740f478fbdfbb23e2c5d972f19f0;hp=a00b78ed7341bbfb42e1229d006490f15a6514b1;hpb=10cdb043b613d60c5de8f1cce0f7a5512b0d0074;p=libs%2Fal.git diff --git a/source/oggdecoder.cpp b/source/oggdecoder.cpp index a00b78e..cd2def8 100644 --- a/source/oggdecoder.cpp +++ b/source/oggdecoder.cpp @@ -1,5 +1,8 @@ -#include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" #include +#pragma GCC diagnostic pop +#include #include "oggdecoder.h" using namespace std; @@ -48,6 +51,30 @@ ov_callbacks io_callbacks = namespace Msp { namespace AL { +ogg_error::ogg_error(const std::string &func, int code): + runtime_error(format("%s: %s", func, get_message(code))) +{ } + +string ogg_error::get_message(int code) +{ + switch(code) + { + case OV_FALSE: return "No data available"; + case OV_HOLE: return "Missing or corrupt data"; + case OV_EREAD: return "Read error"; + case OV_EFAULT: return "Internal inconsistency"; + case OV_EIMPL: return "Not implemented"; + case OV_EINVAL: return "Invalid argument"; + case OV_ENOTVORBIS: return "Not Vorbis data"; + case OV_EBADHEADER: return "Corrupt Vorbis header"; + case OV_EVERSION: return "Unsupported version"; + case OV_EBADLINK: return "Bad link"; + case OV_ENOSEEK: return "Stream is not seekable"; + default: return format("Unknown error (%d)", code); + } +} + + struct OggDecoder::Private { OggVorbis_File ovfile; @@ -56,20 +83,15 @@ struct OggDecoder::Private OggDecoder::OggDecoder(IO::Seekable &io): priv(new Private) { - if(ov_open_callbacks(&io, &priv->ovfile, 0, 0, io_callbacks)<0) - throw runtime_error("Could not open ogg vorbis resource"); + int ret = ov_open_callbacks(&io, &priv->ovfile, 0, 0, io_callbacks); + if(ret<0) + throw ogg_error("ov_open_callbacks", ret); vorbis_info *info = ov_info(&priv->ovfile, -1); freq = info->rate; + format = create_format(2, info->channels); - size = ov_pcm_total(&priv->ovfile, 0)*info->channels*2; - - switch(info->channels) - { - case 1: format = MONO16; break; - case 2: format = STEREO16; break; - default: throw runtime_error("Unsupported number of channels"); - } + size = ov_pcm_total(&priv->ovfile, 0)*get_unit_size(format); } OggDecoder::~OggDecoder() @@ -79,9 +101,18 @@ OggDecoder::~OggDecoder() delete priv; } -void OggDecoder::rewind() +bool OggDecoder::detect(const std::string &sig) +{ + static const char ogg_sig[] = { 'O', 'g', 'g', 'S' }; + if(sig.size()ovfile, 0); + pos /= get_unit_size(format); + ov_pcm_seek(&priv->ovfile, pos); } unsigned OggDecoder::read(char *buf, unsigned len) @@ -89,7 +120,7 @@ unsigned OggDecoder::read(char *buf, unsigned len) int section = 0; int res = ov_read(&priv->ovfile, buf, len, 0, 2, 1, §ion); if(res<0) - throw runtime_error("Error reading ogg vorbis file"); + throw ogg_error("ov_read", res); else if(res==0) eof_flag = true; return res;