1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
//-------------------------------------------------------------------------
// This class encapsulates the OggFLAC stream. Only the functions
// needed by the alsaplayer flac plugin are implemented.
//
// Copyright (c) 2002 by Drew Hess <dhess@bothan.net>
//
/* This file is part of AlsaPlayer.
*
* AlsaPlayer is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* AlsaPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
//-------------------------------------------------------------------------
#include "OggFlacStream.h"
#include "FlacEngine.h"
#include <string.h>
#include "alsaplayer_error.h"
#include <string>
using namespace std;
namespace Flac
{
// static
bool
OggFlacStream::isOggFlacStream (const string & name)
{
reader_type * rdr = reader_open (name.c_str (), NULL, NULL);
if (!rdr)
return false;
OggFlacStream f (name, rdr, false);
return f.open ();
} // OggFlacStream::isOggFlacStream
OggFlacStream::OggFlacStream (const string & name,
reader_type * f,
bool reportErrors)
: FlacStream (name, f, reportErrors),
_decoder (0)
{
} // OggFlacStream::OggFlacStream
OggFlacStream::~OggFlacStream ()
{
if (_decoder)
{
OggFLAC__stream_decoder_finish (_decoder);
OggFLAC__stream_decoder_delete (_decoder);
_decoder = 0;
}
} // OggFlacStream::~OggFlacStream
bool
OggFlacStream::open ()
{
// it's illegal to call this on an already open stream
if (_decoder)
return false;
_decoder = OggFLAC__stream_decoder_new ();
if (!_decoder)
return false;
bool status = true;
status &= OggFLAC__stream_decoder_set_read_callback (_decoder,
readCallBack);
status &= OggFLAC__stream_decoder_set_write_callback (_decoder,
writeCallBack);
status &= OggFLAC__stream_decoder_set_metadata_callback (_decoder,
metaCallBack);
status &= OggFLAC__stream_decoder_set_error_callback (_decoder,
errCallBack);
status &= OggFLAC__stream_decoder_set_client_data (_decoder,
(void *) this);
if (!status)
return false;
status = (OggFLAC__stream_decoder_init (_decoder) ==
OggFLAC__STREAM_DECODER_OK);
if (!status)
return false;
// this will invoke the metaCallBack
if (!OggFLAC__stream_decoder_process_until_end_of_metadata (_decoder))
return false;
// now that we've opened the stream, tell the engine it's safe to
// initialize itself.
if (!_engine->init ())
return false;
// return the metaCallBack's status
return _mcbSuccess;
} // OggFlacStream::open
bool
OggFlacStream::processOneBlock ()
{
if (!_decoder)
return false;
return OggFLAC__stream_decoder_process_single (_decoder);
} // OggFlacStream::processOneBlock
// static
void
OggFlacStream::metaCallBack (const OggFLAC__StreamDecoder * decoder,
const FLAC__StreamMetadata * md,
void * client_data)
{
OggFlacStream * f = (OggFlacStream *) client_data;
if (!f)
{
f->apError ("OggFlacStream::metaCallBack(): no client data");
return;
}
f->realMetaCallBack (md);
} // OggFlacStream::metaCallBack
// static
void
OggFlacStream::errCallBack (const OggFLAC__StreamDecoder * decoder,
FLAC__StreamDecoderErrorStatus status,
void * client_data)
{
OggFlacStream * f = (OggFlacStream *) client_data;
if (!f)
{
f->apError ("OggFlacStream::errCallBack (): no client data");
return;
}
f->realErrCallBack ("OggFLAC", status);
} // OggFlacStream::errCallBack
// static
FLAC__StreamDecoderWriteStatus
OggFlacStream::writeCallBack (const OggFLAC__StreamDecoder * decoder,
const FLAC__Frame * block,
const FLAC__int32 * const buffer[],
void * client_data)
{
if (!client_data)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
OggFlacStream * f = (OggFlacStream *) client_data;
if (!f)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
return f->realWriteCallBack (block, buffer);
} // OggFlacStream::writeCallBack
// static
FLAC__StreamDecoderReadStatus
OggFlacStream::readCallBack (const OggFLAC__StreamDecoder * decoder,
FLAC__byte buffer[],
size_t * bytes,
void * client_data)
{
if (!client_data)
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
OggFlacStream * f = (OggFlacStream *) client_data;
if (!f)
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
return f->realReadCallBack (buffer, bytes);
} // OggFlacStream::readCallBack
} // namespace Flac
|