1 #pragma GCC diagnostic push
2 #pragma GCC diagnostic ignored "-Wunused-variable"
3 #include <vorbis/vorbisfile.h>
4 #pragma GCC diagnostic pop
5 #include <msp/strings/format.h>
6 #include "oggdecoder.h"
12 size_t read(void *ptr, size_t size, size_t nmemb, void *src)
14 Msp::IO::Base *in = reinterpret_cast<Msp::IO::Base *>(src);
15 unsigned len = in->read(reinterpret_cast<char *>(ptr), size*nmemb);
19 int seek(void *src, ogg_int64_t offset, int whence)
21 Msp::IO::SeekType type;
23 type = Msp::IO::S_BEG;
24 else if(whence==SEEK_CUR)
25 type = Msp::IO::S_CUR;
26 else if(whence==SEEK_END)
27 type = Msp::IO::S_END;
31 Msp::IO::Seekable *in = reinterpret_cast<Msp::IO::Seekable *>(src);
32 return in->seek(offset, type);
37 return reinterpret_cast<Msp::IO::Seekable *>(src)->tell();
40 ov_callbacks io_callbacks =
54 ogg_error::ogg_error(const std::string &func, int code):
55 runtime_error(format("%s: %s", func, get_message(code)))
58 string ogg_error::get_message(int code)
62 case OV_FALSE: return "No data available";
63 case OV_HOLE: return "Missing or corrupt data";
64 case OV_EREAD: return "Read error";
65 case OV_EFAULT: return "Internal inconsistency";
66 case OV_EIMPL: return "Not implemented";
67 case OV_EINVAL: return "Invalid argument";
68 case OV_ENOTVORBIS: return "Not Vorbis data";
69 case OV_EBADHEADER: return "Corrupt Vorbis header";
70 case OV_EVERSION: return "Unsupported version";
71 case OV_EBADLINK: return "Bad link";
72 case OV_ENOSEEK: return "Stream is not seekable";
73 default: return format("Unknown error (%d)", code);
78 struct OggDecoder::Private
80 OggVorbis_File ovfile;
83 OggDecoder::OggDecoder(IO::Seekable &io):
86 int ret = ov_open_callbacks(&io, &priv->ovfile, 0, 0, io_callbacks);
88 throw ogg_error("ov_open_callbacks", ret);
90 vorbis_info *info = ov_info(&priv->ovfile, -1);
92 format = create_format(2, info->channels);
94 size = ov_pcm_total(&priv->ovfile, 0)*get_unit_size(format);
97 OggDecoder::~OggDecoder()
99 if(priv->ovfile.datasource)
100 ov_clear(&priv->ovfile);
104 bool OggDecoder::detect(const std::string &sig)
106 static const char ogg_sig[] = { 'O', 'g', 'g', 'S' };
107 if(sig.size()<sizeof(ogg_sig))
109 return !sig.compare(0, sizeof(ogg_sig), ogg_sig);
112 void OggDecoder::rewind()
114 ov_pcm_seek(&priv->ovfile, 0);
117 unsigned OggDecoder::read(char *buf, unsigned len)
120 int res = ov_read(&priv->ovfile, buf, len, 0, 2, 1, §ion);
122 throw ogg_error("ov_read", res);