]> git.tdb.fi Git - libs/al.git/blobdiff - source/oggdecoder.cpp
Add dedicated exception classes for decoding sounds
[libs/al.git] / source / oggdecoder.cpp
index a00b78ed7341bbfb42e1229d006490f15a6514b1..5462b79bb4d8c6c0cdd0c3871cf9e91d1bafdb81 100644 (file)
@@ -1,5 +1,5 @@
-#include <stdexcept>
 #include <vorbis/vorbisfile.h>
+#include <msp/strings/format.h>
 #include "oggdecoder.h"
 
 using namespace std;
@@ -48,6 +48,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,8 +80,9 @@ 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;
@@ -68,7 +93,7 @@ OggDecoder::OggDecoder(IO::Seekable &io):
        {
        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));
        }
 }
 
@@ -89,7 +114,7 @@ unsigned OggDecoder::read(char *buf, unsigned len)
        int section = 0;
        int res = ov_read(&priv->ovfile, buf, len, 0, 2, 1, &section);
        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;