-#include <stdexcept>
#include <vorbis/vorbisfile.h>
+#include <msp/strings/format.h>
#include "oggdecoder.h"
using namespace std;
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;
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;
{
case 1: format = MONO16; break;
case 2: format = STEREO16; break;
- default: throw runtime_error("Unsupported number of channels");
+ default: throw unsupported_sound(Msp::format("%d channels", info->channels));
}
}
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;
#ifndef MSP_AL_OGGDECODER_H_
#define MSP_AL_OGGDECODER_H_
+#include <stdexcept>
#include "sounddecoder.h"
namespace Msp {
namespace AL {
+class ogg_error: public std::runtime_error
+{
+public:
+ ogg_error(const std::string &, int);
+ virtual ~ogg_error() throw() { }
+
+private:
+ static std::string get_message(int);
+};
+
+
class OggDecoder: public SoundDecoder
{
private: