+++ /dev/null
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#include <vorbis/vorbisfile.h>
-#pragma GCC diagnostic pop
-#include <msp/strings/format.h>
-#include "oggdecoder.h"
-
-using namespace std;
-
-namespace {
-
-size_t read(void *ptr, size_t size, size_t nmemb, void *src)
-{
- Msp::IO::Base *in = reinterpret_cast<Msp::IO::Base *>(src);
- unsigned len = in->read(reinterpret_cast<char *>(ptr), size*nmemb);
- return len/size;
-}
-
-int seek(void *src, ogg_int64_t offset, int whence)
-{
- Msp::IO::SeekType type;
- if(whence==SEEK_SET)
- type = Msp::IO::S_BEG;
- else if(whence==SEEK_CUR)
- type = Msp::IO::S_CUR;
- else if(whence==SEEK_END)
- type = Msp::IO::S_END;
- else
- return -1;
-
- Msp::IO::Seekable *in = reinterpret_cast<Msp::IO::Seekable *>(src);
- return in->seek(offset, type);
-}
-
-long tell(void *src)
-{
- return reinterpret_cast<Msp::IO::Seekable *>(src)->tell();
-}
-
-ov_callbacks io_callbacks =
-{
- &read,
- &seek,
- 0,
- &tell
-};
-
-} // namespace
-
-
-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)
-{
- 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)*get_unit_size(format);
-}
-
-OggDecoder::~OggDecoder()
-{
- if(priv->ovfile.datasource)
- ov_clear(&priv->ovfile);
- delete priv;
-}
-
-bool OggDecoder::detect(const std::string &sig)
-{
- static const char ogg_sig[] = { 'O', 'g', 'g', 'S' };
- if(sig.size()<sizeof(ogg_sig))
- return false;
- return !sig.compare(0, sizeof(ogg_sig), ogg_sig, sizeof(ogg_sig));
-}
-
-void OggDecoder::seek(unsigned pos)
-{
- pos /= get_unit_size(format);
- ov_pcm_seek(&priv->ovfile, pos);
-}
-
-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 ogg_error("ov_read", res);
- else if(res==0)
- eof_flag = true;
- return res;
-}
-
-} // namespace AL
-} // namespace Msp