decoder/Client: new interface which wraps struct Decoder

Prepare for a Decoder API redesign based on an abstract class with
virtual methods.
This commit is contained in:
Max Kellermann 2016-11-18 07:13:35 +01:00
parent 595d1942cb
commit fd77acc217
46 changed files with 460 additions and 407 deletions

View File

@ -100,6 +100,7 @@ libmpd_a_SOURCES = \
src/decoder/DecoderCommand.hxx \
src/decoder/DecoderControl.cxx src/decoder/DecoderControl.hxx \
src/decoder/DecoderAPI.cxx src/decoder/DecoderAPI.hxx \
src/decoder/Client.hxx \
src/decoder/DecoderPlugin.hxx \
src/decoder/DecoderInternal.cxx src/decoder/DecoderInternal.hxx \
src/decoder/DecoderPrint.cxx src/decoder/DecoderPrint.hxx \

31
src/decoder/Client.hxx Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright 2003-2016 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_DECODER_CLIENT_HXX
#define MPD_DECODER_CLIENT_HXX
#include "check.h"
/**
* An interface between the decoder plugin and the MPD core.
*/
class DecoderClient {
};
#endif

View File

@ -38,10 +38,11 @@
#include <math.h>
void
decoder_initialized(Decoder &decoder,
decoder_initialized(DecoderClient &client,
const AudioFormat audio_format,
bool seekable, SignedSongTime duration)
{
auto &decoder = (Decoder &)client;
DecoderControl &dc = decoder.dc;
struct audio_format_string af_string;
@ -91,8 +92,9 @@ decoder_initialized(Decoder &decoder,
*/
gcc_pure
static bool
decoder_prepare_initial_seek(Decoder &decoder)
decoder_prepare_initial_seek(DecoderClient &client)
{
auto &decoder = (Decoder &)client;
const DecoderControl &dc = decoder.dc;
assert(dc.pipe != nullptr);
@ -138,8 +140,10 @@ decoder_prepare_initial_seek(Decoder &decoder)
*/
gcc_pure
static DecoderCommand
decoder_get_virtual_command(Decoder &decoder)
decoder_get_virtual_command(DecoderClient &client)
{
auto &decoder = (Decoder &)client;
if (decoder.error)
/* an error has occurred: stop the decoder plugin */
return DecoderCommand::STOP;
@ -155,21 +159,24 @@ decoder_get_virtual_command(Decoder &decoder)
gcc_pure
static DecoderCommand
decoder_lock_get_virtual_command(Decoder &decoder)
decoder_lock_get_virtual_command(DecoderClient &client)
{
auto &decoder = (Decoder &)client;
const ScopeLock protect(decoder.dc.mutex);
return decoder_get_virtual_command(decoder);
}
DecoderCommand
decoder_get_command(Decoder &decoder)
decoder_get_command(DecoderClient &client)
{
auto &decoder = (Decoder &)client;
return decoder_lock_get_virtual_command(decoder);
}
void
decoder_command_finished(Decoder &decoder)
decoder_command_finished(DecoderClient &client)
{
auto &decoder = (Decoder &)client;
DecoderControl &dc = decoder.dc;
const ScopeLock protect(dc.mutex);
@ -211,8 +218,9 @@ decoder_command_finished(Decoder &decoder)
}
SongTime
decoder_seek_time(Decoder &decoder)
decoder_seek_time(DecoderClient &client)
{
auto &decoder = (Decoder &)client;
const DecoderControl &dc = decoder.dc;
assert(dc.pipe != nullptr);
@ -228,15 +236,18 @@ decoder_seek_time(Decoder &decoder)
}
uint64_t
decoder_seek_where_frame(Decoder &decoder)
decoder_seek_where_frame(DecoderClient &client)
{
auto &decoder = (Decoder &)client;
const DecoderControl &dc = decoder.dc;
return decoder_seek_time(decoder).ToScale<uint64_t>(dc.in_audio_format.sample_rate);
}
void decoder_seek_error(Decoder & decoder)
void
decoder_seek_error(DecoderClient &client)
{
auto &decoder = (Decoder &)client;
DecoderControl &dc = decoder.dc;
assert(dc.pipe != nullptr);
@ -257,8 +268,10 @@ void decoder_seek_error(Decoder & decoder)
}
InputStreamPtr
decoder_open_uri(Decoder &decoder, const char *uri)
decoder_open_uri(DecoderClient &client, const char *uri)
{
auto &decoder = (Decoder &)client;
assert(decoder.dc.state == DecoderState::START ||
decoder.dc.state == DecoderState::DECODE);
@ -311,11 +324,12 @@ decoder_check_cancel_read(const Decoder *decoder)
}
size_t
decoder_read(Decoder *decoder,
decoder_read(DecoderClient *client,
InputStream &is,
void *buffer, size_t length)
try {
/* XXX don't allow decoder==nullptr */
auto *decoder = (Decoder *)client;
assert(decoder == nullptr ||
decoder->dc.state == DecoderState::START ||
@ -342,6 +356,7 @@ try {
return nbytes;
} catch (const std::runtime_error &e) {
auto *decoder = (Decoder *)client;
if (decoder != nullptr)
decoder->error = std::current_exception();
else
@ -350,13 +365,13 @@ try {
}
bool
decoder_read_full(Decoder *decoder, InputStream &is,
decoder_read_full(DecoderClient *client, InputStream &is,
void *_buffer, size_t size)
{
uint8_t *buffer = (uint8_t *)_buffer;
while (size > 0) {
size_t nbytes = decoder_read(decoder, is, buffer, size);
size_t nbytes = decoder_read(client, is, buffer, size);
if (nbytes == 0)
return false;
@ -368,11 +383,11 @@ decoder_read_full(Decoder *decoder, InputStream &is,
}
bool
decoder_skip(Decoder *decoder, InputStream &is, size_t size)
decoder_skip(DecoderClient *client, InputStream &is, size_t size)
{
while (size > 0) {
char buffer[1024];
size_t nbytes = decoder_read(decoder, is, buffer,
size_t nbytes = decoder_read(client, is, buffer,
std::min(sizeof(buffer), size));
if (nbytes == 0)
return false;
@ -384,10 +399,11 @@ decoder_skip(Decoder *decoder, InputStream &is, size_t size)
}
void
decoder_timestamp(Decoder &decoder, double t)
decoder_timestamp(DecoderClient &client, double t)
{
assert(t >= 0);
auto &decoder = (Decoder &)client;
decoder.timestamp = t;
}
@ -396,8 +412,9 @@ decoder_timestamp(Decoder &decoder, double t)
* (decoder.chunk) if there is one.
*/
static DecoderCommand
do_send_tag(Decoder &decoder, const Tag &tag)
do_send_tag(DecoderClient &client, const Tag &tag)
{
auto &decoder = (Decoder &)client;
MusicChunk *chunk;
if (decoder.current_chunk != nullptr) {
@ -419,8 +436,9 @@ do_send_tag(Decoder &decoder, const Tag &tag)
}
static bool
update_stream_tag(Decoder &decoder, InputStream *is)
update_stream_tag(DecoderClient &client, InputStream *is)
{
auto &decoder = (Decoder &)client;
Tag *tag;
tag = is != nullptr
@ -445,11 +463,12 @@ update_stream_tag(Decoder &decoder, InputStream *is)
}
DecoderCommand
decoder_data(Decoder &decoder,
decoder_data(DecoderClient &client,
InputStream *is,
const void *data, size_t length,
uint16_t kbit_rate)
{
auto &decoder = (Decoder &)client;
DecoderControl &dc = decoder.dc;
assert(dc.state == DecoderState::DECODE);
@ -552,9 +571,10 @@ decoder_data(Decoder &decoder,
}
DecoderCommand
decoder_tag(Decoder &decoder, InputStream *is,
decoder_tag(DecoderClient &client, InputStream *is,
Tag &&tag)
{
auto &decoder = (Decoder &)client;
gcc_unused const DecoderControl &dc = decoder.dc;
DecoderCommand cmd;
@ -596,9 +616,11 @@ decoder_tag(Decoder &decoder, InputStream *is,
}
void
decoder_replay_gain(Decoder &decoder,
decoder_replay_gain(DecoderClient &client,
const ReplayGainInfo *replay_gain_info)
{
auto &decoder = (Decoder &)client;
if (replay_gain_info != nullptr) {
static unsigned serial;
if (++serial == 0)
@ -631,8 +653,9 @@ decoder_replay_gain(Decoder &decoder,
}
void
decoder_mixramp(Decoder &decoder, MixRampInfo &&mix_ramp)
decoder_mixramp(DecoderClient &client, MixRampInfo &&mix_ramp)
{
auto &decoder = (Decoder &)client;
DecoderControl &dc = decoder.dc;
dc.SetMixRamp(std::move(mix_ramp));

View File

@ -44,6 +44,8 @@
#include <stdint.h>
class DecoderClient;
/**
* Throw an instance of this class to stop decoding the current song
* (successfully). It can be used to jump out of all of a decoder's
@ -63,7 +65,7 @@ class StopDecoder {};
* unknown
*/
void
decoder_initialized(Decoder &decoder,
decoder_initialized(DecoderClient &decoder,
AudioFormat audio_format,
bool seekable, SignedSongTime duration);
@ -76,7 +78,7 @@ decoder_initialized(Decoder &decoder,
*/
gcc_pure
DecoderCommand
decoder_get_command(Decoder &decoder);
decoder_get_command(DecoderClient &decoder);
/**
* Called by the decoder when it has performed the requested command
@ -86,7 +88,7 @@ decoder_get_command(Decoder &decoder);
* @param decoder the decoder object
*/
void
decoder_command_finished(Decoder &decoder);
decoder_command_finished(DecoderClient &decoder);
/**
* Call this when you have received the DecoderCommand::SEEK command.
@ -96,7 +98,7 @@ decoder_command_finished(Decoder &decoder);
*/
gcc_pure
SongTime
decoder_seek_time(Decoder &decoder);
decoder_seek_time(DecoderClient &decoder);
/**
* Call this when you have received the DecoderCommand::SEEK command.
@ -106,7 +108,7 @@ decoder_seek_time(Decoder &decoder);
*/
gcc_pure
uint64_t
decoder_seek_where_frame(Decoder &decoder);
decoder_seek_where_frame(DecoderClient &decoder);
/**
* Call this instead of decoder_command_finished() when seeking has
@ -115,7 +117,7 @@ decoder_seek_where_frame(Decoder &decoder);
* @param decoder the decoder object
*/
void
decoder_seek_error(Decoder &decoder);
decoder_seek_error(DecoderClient &decoder);
/**
* Open a new #InputStream and wait until it's ready.
@ -125,7 +127,7 @@ decoder_seek_error(Decoder &decoder);
* Throws std::runtime_error on error.
*/
InputStreamPtr
decoder_open_uri(Decoder &decoder, const char *uri);
decoder_open_uri(DecoderClient &decoder, const char *uri);
/**
* Blocking read from the input stream.
@ -138,11 +140,11 @@ decoder_open_uri(Decoder &decoder, const char *uri);
* occurs: end of file; error; command (like SEEK or STOP).
*/
size_t
decoder_read(Decoder *decoder, InputStream &is,
decoder_read(DecoderClient *decoder, InputStream &is,
void *buffer, size_t length);
static inline size_t
decoder_read(Decoder &decoder, InputStream &is,
decoder_read(DecoderClient &decoder, InputStream &is,
void *buffer, size_t length)
{
return decoder_read(&decoder, is, buffer, length);
@ -156,7 +158,7 @@ decoder_read(Decoder &decoder, InputStream &is,
* data
*/
bool
decoder_read_full(Decoder *decoder, InputStream &is,
decoder_read_full(DecoderClient *decoder, InputStream &is,
void *buffer, size_t size);
/**
@ -165,7 +167,7 @@ decoder_read_full(Decoder *decoder, InputStream &is,
* @return true on success, false on error or command
*/
bool
decoder_skip(Decoder *decoder, InputStream &is, size_t size);
decoder_skip(DecoderClient *decoder, InputStream &is, size_t size);
/**
* Sets the time stamp for the next data chunk [seconds]. The MPD
@ -174,7 +176,7 @@ decoder_skip(Decoder *decoder, InputStream &is, size_t size);
* on the buffer size won't work.
*/
void
decoder_timestamp(Decoder &decoder, double t);
decoder_timestamp(DecoderClient &decoder, double t);
/**
* This function is called by the decoder plugin when it has
@ -189,12 +191,12 @@ decoder_timestamp(Decoder &decoder, double t);
* command pending
*/
DecoderCommand
decoder_data(Decoder &decoder, InputStream *is,
decoder_data(DecoderClient &decoder, InputStream *is,
const void *data, size_t length,
uint16_t kbit_rate);
static inline DecoderCommand
decoder_data(Decoder &decoder, InputStream &is,
decoder_data(DecoderClient &decoder, InputStream &is,
const void *data, size_t length,
uint16_t kbit_rate)
{
@ -212,10 +214,10 @@ decoder_data(Decoder &decoder, InputStream &is,
* command pending
*/
DecoderCommand
decoder_tag(Decoder &decoder, InputStream *is, Tag &&tag);
decoder_tag(DecoderClient &decoder, InputStream *is, Tag &&tag);
static inline DecoderCommand
decoder_tag(Decoder &decoder, InputStream &is, Tag &&tag)
decoder_tag(DecoderClient &decoder, InputStream &is, Tag &&tag)
{
return decoder_tag(decoder, &is, std::move(tag));
}
@ -227,13 +229,13 @@ decoder_tag(Decoder &decoder, InputStream &is, Tag &&tag)
* to invalidate the previous replay gain values
*/
void
decoder_replay_gain(Decoder &decoder,
decoder_replay_gain(DecoderClient &decoder,
const ReplayGainInfo *replay_gain_info);
/**
* Store MixRamp tags.
*/
void
decoder_mixramp(Decoder &decoder, MixRampInfo &&mix_ramp);
decoder_mixramp(DecoderClient &decoder, MixRampInfo &&mix_ramp);
#endif

View File

@ -29,7 +29,7 @@ DecoderBuffer::Fill()
/* buffer is full */
return false;
size_t nbytes = decoder_read(decoder, is,
size_t nbytes = decoder_read(client, is,
w.data, w.size);
if (nbytes == 0)
/* end of file, I/O error or decoder command
@ -65,5 +65,5 @@ DecoderBuffer::Skip(size_t nbytes)
buffer.Clear();
nbytes -= r.size;
return decoder_skip(decoder, is, nbytes);
return decoder_skip(client, is, nbytes);
}

View File

@ -27,7 +27,7 @@
#include <stddef.h>
#include <stdint.h>
struct Decoder;
class DecoderClient;
class InputStream;
/**
@ -36,7 +36,7 @@ class InputStream;
* read it. It will automatically handle shifting the buffer.
*/
class DecoderBuffer {
Decoder *const decoder;
DecoderClient *const client;
InputStream &is;
DynamicFifoBuffer<uint8_t> buffer;
@ -45,14 +45,14 @@ public:
/**
* Creates a new buffer.
*
* @param _decoder the decoder object, used for decoder_read(),
* @param _client the decoder client, used for decoder_read(),
* may be nullptr
* @param _is the input stream object where we should read from
* @param _size the maximum size of the buffer
*/
DecoderBuffer(Decoder *_decoder, InputStream &_is,
DecoderBuffer(DecoderClient *_client, InputStream &_is,
size_t _size)
:decoder(_decoder), is(_is), buffer(_size) {}
:client(_client), is(_is), buffer(_size) {}
const InputStream &GetStream() const {
return is;

View File

@ -20,6 +20,7 @@
#ifndef MPD_DECODER_INTERNAL_HXX
#define MPD_DECODER_INTERNAL_HXX
#include "Client.hxx"
#include "ReplayGainInfo.hxx"
#include <exception>
@ -29,7 +30,7 @@ struct MusicChunk;
struct DecoderControl;
struct Tag;
struct Decoder {
struct Decoder final : DecoderClient {
DecoderControl &dc;
/**

View File

@ -27,12 +27,7 @@ class InputStream;
struct TagHandler;
class Path;
template<typename T> class AllocatedString;
/**
* Opaque handle which the decoder plugin passes to the functions in
* this header.
*/
struct Decoder;
class DecoderClient;
struct DecoderPlugin {
const char *name;
@ -60,14 +55,14 @@ struct DecoderPlugin {
* possible, it is recommended to implement this method,
* because it is more versatile.
*/
void (*stream_decode)(Decoder &decoder, InputStream &is);
void (*stream_decode)(DecoderClient &client, InputStream &is);
/**
* Decode a local file.
*
* Either implement this method or stream_decode().
*/
void (*file_decode)(Decoder &decoder, Path path_fs);
void (*file_decode)(DecoderClient &client, Path path_fs);
/**
* Scan metadata of a file.
@ -127,16 +122,16 @@ struct DecoderPlugin {
/**
* Decode a stream.
*/
void StreamDecode(Decoder &decoder, InputStream &is) const {
stream_decode(decoder, is);
void StreamDecode(DecoderClient &client, InputStream &is) const {
stream_decode(client, is);
}
/**
* Decode a file.
*/
template<typename P>
void FileDecode(Decoder &decoder, P path_fs) const {
file_decode(decoder, path_fs);
void FileDecode(DecoderClient &client, P path_fs) const {
file_decode(client, path_fs);
}
/**

View File

@ -24,5 +24,5 @@
size_t
DecoderReader::Read(void *data, size_t size)
{
return decoder_read(&decoder, is, data, size);
return decoder_read(client, is, data, size);
}

View File

@ -24,7 +24,7 @@
#include "fs/io/Reader.hxx"
#include "Compiler.h"
struct Decoder;
class DecoderClient;
class InputStream;
/**
@ -32,15 +32,15 @@ class InputStream;
* interface.
*/
class DecoderReader final : public Reader {
Decoder &decoder;
DecoderClient &client;
InputStream &is;
public:
DecoderReader(Decoder &_decoder, InputStream &_is)
:decoder(_decoder), is(_is) {}
DecoderReader(DecoderClient &_client, InputStream &_is)
:client(_client), is(_is) {}
Decoder &GetDecoder() {
return decoder;
DecoderClient &GetClient() {
return client;
}
InputStream &GetInputStream() {

View File

@ -49,7 +49,7 @@ adplug_init(const ConfigBlock &block)
}
static void
adplug_file_decode(Decoder &decoder, Path path_fs)
adplug_file_decode(DecoderClient &client, Path path_fs)
{
CEmuopl opl(sample_rate, true, true);
opl.init();
@ -61,7 +61,7 @@ adplug_file_decode(Decoder &decoder, Path path_fs)
const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
assert(audio_format.IsValid());
decoder_initialized(decoder, audio_format, false,
decoder_initialized(client, audio_format, false,
SongTime::FromMS(player->songlength()));
DecoderCommand cmd;
@ -73,7 +73,7 @@ adplug_file_decode(Decoder &decoder, Path path_fs)
int16_t buffer[2048];
constexpr unsigned frames_per_buffer = ARRAY_SIZE(buffer) / 2;
opl.update(buffer, frames_per_buffer);
cmd = decoder_data(decoder, nullptr,
cmd = decoder_data(client, nullptr,
buffer, sizeof(buffer),
0);
} while (cmd == DecoderCommand::NONE);

View File

@ -51,14 +51,14 @@ audiofile_init(const ConfigBlock &)
}
struct AudioFileInputStream {
Decoder *const decoder;
DecoderClient *const client;
InputStream &is;
size_t Read(void *buffer, size_t size) {
/* libaudiofile does not like partial reads at all,
and will abort playback; therefore always force full
reads */
return decoder_read_full(decoder, is, buffer, size)
return decoder_read_full(client, is, buffer, size)
? size
: 0;
}
@ -181,14 +181,14 @@ audiofile_setup_sample_format(AFfilehandle af_fp)
}
static void
audiofile_stream_decode(Decoder &decoder, InputStream &is)
audiofile_stream_decode(DecoderClient &client, InputStream &is)
{
if (!is.IsSeekable() || !is.KnownSize()) {
LogWarning(audiofile_domain, "not seekable");
return;
}
AudioFileInputStream afis{&decoder, is};
AudioFileInputStream afis{&client, is};
AFvirtualfile *const vf = setup_virtual_fops(afis);
const AFfilehandle fh = afOpenVirtualFile(vf, "r", nullptr);
@ -210,7 +210,7 @@ audiofile_stream_decode(Decoder &decoder, InputStream &is)
const unsigned frame_size = (unsigned)
afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, true);
decoder_initialized(decoder, audio_format, true, total_time);
decoder_initialized(client, audio_format, true, total_time);
DecoderCommand cmd;
do {
@ -223,15 +223,15 @@ audiofile_stream_decode(Decoder &decoder, InputStream &is)
if (nframes <= 0)
break;
cmd = decoder_data(decoder, nullptr,
cmd = decoder_data(client, nullptr,
chunk, nframes * frame_size,
kbit_rate);
if (cmd == DecoderCommand::SEEK) {
AFframecount frame = decoder_seek_where_frame(decoder);
AFframecount frame = decoder_seek_where_frame(client);
afSeekFrame(fh, AF_DEFAULT_TRACK, frame);
decoder_command_finished(decoder);
decoder_command_finished(client);
cmd = DecoderCommand::NONE;
}
} while (cmd == DecoderCommand::NONE);

View File

@ -51,7 +51,7 @@ DsdId::Equals(const char *s) const
* Skip the #InputStream to the specified offset.
*/
bool
dsdlib_skip_to(Decoder *decoder, InputStream &is,
dsdlib_skip_to(DecoderClient *client, InputStream &is,
offset_type offset)
{
if (is.IsSeekable()) {
@ -65,14 +65,14 @@ dsdlib_skip_to(Decoder *decoder, InputStream &is,
if (is.GetOffset() > offset)
return false;
return dsdlib_skip(decoder, is, offset - is.GetOffset());
return dsdlib_skip(client, is, offset - is.GetOffset());
}
/**
* Skip some bytes from the #InputStream.
*/
bool
dsdlib_skip(Decoder *decoder, InputStream &is,
dsdlib_skip(DecoderClient *client, InputStream &is,
offset_type delta)
{
if (delta == 0)
@ -91,7 +91,7 @@ dsdlib_skip(Decoder *decoder, InputStream &is,
expensive */
return false;
return decoder_skip(decoder, is, delta);
return decoder_skip(client, is, delta);
}
bool

View File

@ -26,8 +26,8 @@
#include <stdint.h>
struct Decoder;
struct TagHandler;
class DecoderClient;
class InputStream;
struct DsdId {
@ -60,11 +60,11 @@ public:
};
bool
dsdlib_skip_to(Decoder *decoder, InputStream &is,
dsdlib_skip_to(DecoderClient *client, InputStream &is,
offset_type offset);
bool
dsdlib_skip(Decoder *decoder, InputStream &is,
dsdlib_skip(DecoderClient *client, InputStream &is,
offset_type delta);
/**

View File

@ -78,21 +78,21 @@ dsdiff_init(const ConfigBlock &block)
}
static bool
dsdiff_read_id(Decoder *decoder, InputStream &is,
dsdiff_read_id(DecoderClient *client, InputStream &is,
DsdId *id)
{
return decoder_read_full(decoder, is, id, sizeof(*id));
return decoder_read_full(client, is, id, sizeof(*id));
}
static bool
dsdiff_read_chunk_header(Decoder *decoder, InputStream &is,
dsdiff_read_chunk_header(DecoderClient *client, InputStream &is,
DsdiffChunkHeader *header)
{
return decoder_read_full(decoder, is, header, sizeof(*header));
return decoder_read_full(client, is, header, sizeof(*header));
}
static bool
dsdiff_read_payload(Decoder *decoder, InputStream &is,
dsdiff_read_payload(DecoderClient *client, InputStream &is,
const DsdiffChunkHeader *header,
void *data, size_t length)
{
@ -100,20 +100,20 @@ dsdiff_read_payload(Decoder *decoder, InputStream &is,
if (size != (uint64_t)length)
return false;
return decoder_read_full(decoder, is, data, length);
return decoder_read_full(client, is, data, length);
}
/**
* Read and parse a "SND" chunk inside "PROP".
*/
static bool
dsdiff_read_prop_snd(Decoder *decoder, InputStream &is,
dsdiff_read_prop_snd(DecoderClient *client, InputStream &is,
DsdiffMetaData *metadata,
offset_type end_offset)
{
DsdiffChunkHeader header;
while (is.GetOffset() + sizeof(header) <= end_offset) {
if (!dsdiff_read_chunk_header(decoder, is, &header))
if (!dsdiff_read_chunk_header(client, is, &header))
return false;
offset_type chunk_end_offset = is.GetOffset()
@ -123,7 +123,7 @@ dsdiff_read_prop_snd(Decoder *decoder, InputStream &is,
if (header.id.Equals("FS ")) {
uint32_t sample_rate;
if (!dsdiff_read_payload(decoder, is, &header,
if (!dsdiff_read_payload(client, is, &header,
&sample_rate,
sizeof(sample_rate)))
return false;
@ -132,18 +132,18 @@ dsdiff_read_prop_snd(Decoder *decoder, InputStream &is,
} else if (header.id.Equals("CHNL")) {
uint16_t channels;
if (header.GetSize() < sizeof(channels) ||
!decoder_read_full(decoder, is,
!decoder_read_full(client, is,
&channels, sizeof(channels)) ||
!dsdlib_skip_to(decoder, is, chunk_end_offset))
!dsdlib_skip_to(client, is, chunk_end_offset))
return false;
metadata->channels = FromBE16(channels);
} else if (header.id.Equals("CMPR")) {
DsdId type;
if (header.GetSize() < sizeof(type) ||
!decoder_read_full(decoder, is,
!decoder_read_full(client, is,
&type, sizeof(type)) ||
!dsdlib_skip_to(decoder, is, chunk_end_offset))
!dsdlib_skip_to(client, is, chunk_end_offset))
return false;
if (!type.Equals("DSD "))
@ -153,7 +153,7 @@ dsdiff_read_prop_snd(Decoder *decoder, InputStream &is,
} else {
/* ignore unknown chunk */
if (!dsdlib_skip_to(decoder, is, chunk_end_offset))
if (!dsdlib_skip_to(client, is, chunk_end_offset))
return false;
}
}
@ -165,7 +165,7 @@ dsdiff_read_prop_snd(Decoder *decoder, InputStream &is,
* Read and parse a "PROP" chunk.
*/
static bool
dsdiff_read_prop(Decoder *decoder, InputStream &is,
dsdiff_read_prop(DecoderClient *client, InputStream &is,
DsdiffMetaData *metadata,
const DsdiffChunkHeader *prop_header)
{
@ -174,14 +174,14 @@ dsdiff_read_prop(Decoder *decoder, InputStream &is,
DsdId prop_id;
if (prop_size < sizeof(prop_id) ||
!dsdiff_read_id(decoder, is, &prop_id))
!dsdiff_read_id(client, is, &prop_id))
return false;
if (prop_id.Equals("SND "))
return dsdiff_read_prop_snd(decoder, is, metadata, end_offset);
return dsdiff_read_prop_snd(client, is, metadata, end_offset);
else
/* ignore unknown PROP chunk */
return dsdlib_skip_to(decoder, is, end_offset);
return dsdlib_skip_to(client, is, end_offset);
}
static void
@ -225,7 +225,7 @@ dsdiff_handle_native_tag(InputStream &is,
*/
static bool
dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is,
dsdiff_read_metadata_extra(DecoderClient *client, InputStream &is,
DsdiffMetaData *metadata,
DsdiffChunkHeader *chunk_header,
const TagHandler &handler,
@ -233,9 +233,9 @@ dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is,
{
/* skip from DSD data to next chunk header */
if (!dsdlib_skip(decoder, is, metadata->chunk_size))
if (!dsdlib_skip(client, is, metadata->chunk_size))
return false;
if (!dsdiff_read_chunk_header(decoder, is, chunk_header))
if (!dsdiff_read_chunk_header(client, is, chunk_header))
return false;
/** offset for artist tag */
@ -276,9 +276,9 @@ dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is,
}
#endif
if (!dsdlib_skip(decoder, is, chunk_size))
if (!dsdlib_skip(client, is, chunk_size))
break;
} while (dsdiff_read_chunk_header(decoder, is, chunk_header));
} while (dsdiff_read_chunk_header(client, is, chunk_header));
/* done processing chunk headers, process tags if any */
@ -307,23 +307,23 @@ dsdiff_read_metadata_extra(Decoder *decoder, InputStream &is,
* "chunk_header" parameter.
*/
static bool
dsdiff_read_metadata(Decoder *decoder, InputStream &is,
dsdiff_read_metadata(DecoderClient *client, InputStream &is,
DsdiffMetaData *metadata,
DsdiffChunkHeader *chunk_header)
{
DsdiffHeader header;
if (!decoder_read_full(decoder, is, &header, sizeof(header)) ||
if (!decoder_read_full(client, is, &header, sizeof(header)) ||
!header.id.Equals("FRM8") ||
!header.format.Equals("DSD "))
return false;
while (true) {
if (!dsdiff_read_chunk_header(decoder, is,
if (!dsdiff_read_chunk_header(client, is,
chunk_header))
return false;
if (chunk_header->id.Equals("PROP")) {
if (!dsdiff_read_prop(decoder, is, metadata,
if (!dsdiff_read_prop(client, is, metadata,
chunk_header))
return false;
} else if (chunk_header->id.Equals("DSD ")) {
@ -336,7 +336,7 @@ dsdiff_read_metadata(Decoder *decoder, InputStream &is,
const offset_type chunk_end_offset =
is.GetOffset() + chunk_size;
if (!dsdlib_skip_to(decoder, is, chunk_end_offset))
if (!dsdlib_skip_to(client, is, chunk_end_offset))
return false;
}
}
@ -359,7 +359,7 @@ FrameToOffset(uint64_t frame, unsigned channels)
* Decode one "DSD" chunk.
*/
static bool
dsdiff_decode_chunk(Decoder &decoder, InputStream &is,
dsdiff_decode_chunk(DecoderClient &client, InputStream &is,
unsigned channels, unsigned sample_rate,
const offset_type total_bytes)
{
@ -372,23 +372,23 @@ dsdiff_decode_chunk(Decoder &decoder, InputStream &is,
const unsigned buffer_frames = sizeof(buffer) / frame_size;
const size_t buffer_size = buffer_frames * frame_size;
auto cmd = decoder_get_command(decoder);
auto cmd = decoder_get_command(client);
for (offset_type remaining_bytes = total_bytes;
remaining_bytes >= frame_size && cmd != DecoderCommand::STOP;) {
if (cmd == DecoderCommand::SEEK) {
uint64_t frame = decoder_seek_where_frame(decoder);
uint64_t frame = decoder_seek_where_frame(client);
offset_type offset = FrameToOffset(frame, channels);
if (offset >= total_bytes) {
decoder_command_finished(decoder);
decoder_command_finished(client);
break;
}
if (dsdlib_skip_to(&decoder, is,
if (dsdlib_skip_to(&client, is,
start_offset + offset)) {
decoder_command_finished(decoder);
decoder_command_finished(client);
remaining_bytes = total_bytes - offset;
} else
decoder_seek_error(decoder);
decoder_seek_error(client);
}
/* see how much aligned data from the remaining chunk
@ -399,7 +399,7 @@ dsdiff_decode_chunk(Decoder &decoder, InputStream &is,
now_size = now_frames * frame_size;
}
if (!decoder_read_full(&decoder, is, buffer, now_size))
if (!decoder_read_full(&client, is, buffer, now_size))
return false;
const size_t nbytes = now_size;
@ -408,7 +408,7 @@ dsdiff_decode_chunk(Decoder &decoder, InputStream &is,
if (lsbitfirst)
bit_reverse_buffer(buffer, buffer + nbytes);
cmd = decoder_data(decoder, is, buffer, nbytes,
cmd = decoder_data(client, is, buffer, nbytes,
sample_rate / 1000);
}
@ -416,13 +416,13 @@ dsdiff_decode_chunk(Decoder &decoder, InputStream &is,
}
static void
dsdiff_stream_decode(Decoder &decoder, InputStream &is)
dsdiff_stream_decode(DecoderClient &client, InputStream &is)
{
DsdiffMetaData metadata;
DsdiffChunkHeader chunk_header;
/* check if it is is a proper DFF file */
if (!dsdiff_read_metadata(&decoder, is, &metadata, &chunk_header))
if (!dsdiff_read_metadata(&client, is, &metadata, &chunk_header))
return;
auto audio_format = CheckAudioFormat(metadata.sample_rate / 8,
@ -437,12 +437,12 @@ dsdiff_stream_decode(Decoder &decoder, InputStream &is)
audio_format.sample_rate);
/* success: file was recognized */
decoder_initialized(decoder, audio_format, is.IsSeekable(), songtime);
decoder_initialized(client, audio_format, is.IsSeekable(), songtime);
/* every iteration of the following loop decodes one "DSD"
chunk from a DFF file */
dsdiff_decode_chunk(decoder, is,
dsdiff_decode_chunk(client, is,
metadata.channels,
metadata.sample_rate,
chunk_size);

View File

@ -98,11 +98,11 @@ struct DsfDataChunk {
* Read and parse all needed metadata chunks for DSF files.
*/
static bool
dsf_read_metadata(Decoder *decoder, InputStream &is,
dsf_read_metadata(DecoderClient *client, InputStream &is,
DsfMetaData *metadata)
{
DsfHeader dsf_header;
if (!decoder_read_full(decoder, is, &dsf_header, sizeof(dsf_header)) ||
if (!decoder_read_full(client, is, &dsf_header, sizeof(dsf_header)) ||
!dsf_header.id.Equals("DSD "))
return false;
@ -116,7 +116,7 @@ dsf_read_metadata(Decoder *decoder, InputStream &is,
/* read the 'fmt ' chunk of the DSF file */
DsfFmtChunk dsf_fmt_chunk;
if (!decoder_read_full(decoder, is,
if (!decoder_read_full(client, is,
&dsf_fmt_chunk, sizeof(dsf_fmt_chunk)) ||
!dsf_fmt_chunk.id.Equals("fmt "))
return false;
@ -144,7 +144,7 @@ dsf_read_metadata(Decoder *decoder, InputStream &is,
/* read the 'data' chunk of the DSF file */
DsfDataChunk data_chunk;
if (!decoder_read_full(decoder, is, &data_chunk, sizeof(data_chunk)) ||
if (!decoder_read_full(client, is, &data_chunk, sizeof(data_chunk)) ||
!data_chunk.id.Equals("data"))
return false;
@ -251,7 +251,7 @@ FrameToBlock(uint64_t frame)
* Decode one complete DSF 'data' chunk i.e. a complete song
*/
static bool
dsf_decode_chunk(Decoder &decoder, InputStream &is,
dsf_decode_chunk(DecoderClient &client, InputStream &is,
unsigned channels, unsigned sample_rate,
offset_type n_blocks,
bool bitreverse)
@ -259,28 +259,28 @@ dsf_decode_chunk(Decoder &decoder, InputStream &is,
const size_t block_size = channels * DSF_BLOCK_SIZE;
const offset_type start_offset = is.GetOffset();
auto cmd = decoder_get_command(decoder);
auto cmd = decoder_get_command(client);
for (offset_type i = 0; i < n_blocks && cmd != DecoderCommand::STOP;) {
if (cmd == DecoderCommand::SEEK) {
uint64_t frame = decoder_seek_where_frame(decoder);
uint64_t frame = decoder_seek_where_frame(client);
offset_type block = FrameToBlock(frame);
if (block >= n_blocks) {
decoder_command_finished(decoder);
decoder_command_finished(client);
break;
}
offset_type offset =
start_offset + block * block_size;
if (dsdlib_skip_to(&decoder, is, offset)) {
decoder_command_finished(decoder);
if (dsdlib_skip_to(&client, is, offset)) {
decoder_command_finished(client);
i = block;
} else
decoder_seek_error(decoder);
decoder_seek_error(client);
}
/* worst-case buffer size */
uint8_t buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
if (!decoder_read_full(&decoder, is, buffer, block_size))
if (!decoder_read_full(&client, is, buffer, block_size))
return false;
if (bitreverse)
@ -289,7 +289,7 @@ dsf_decode_chunk(Decoder &decoder, InputStream &is,
uint8_t interleaved_buffer[MAX_CHANNELS * DSF_BLOCK_SIZE];
InterleaveDsfBlock(interleaved_buffer, buffer, channels);
cmd = decoder_data(decoder, is,
cmd = decoder_data(client, is,
interleaved_buffer, block_size,
sample_rate / 1000);
++i;
@ -299,11 +299,11 @@ dsf_decode_chunk(Decoder &decoder, InputStream &is,
}
static void
dsf_stream_decode(Decoder &decoder, InputStream &is)
dsf_stream_decode(DecoderClient &client, InputStream &is)
{
/* check if it is a proper DSF file */
DsfMetaData metadata;
if (!dsf_read_metadata(&decoder, is, &metadata))
if (!dsf_read_metadata(&client, is, &metadata))
return;
auto audio_format = CheckAudioFormat(metadata.sample_rate / 8,
@ -316,9 +316,9 @@ dsf_stream_decode(Decoder &decoder, InputStream &is)
audio_format.sample_rate);
/* success: file was recognized */
decoder_initialized(decoder, audio_format, is.IsSeekable(), songtime);
decoder_initialized(client, audio_format, is.IsSeekable(), songtime);
dsf_decode_chunk(decoder, is, metadata.channels,
dsf_decode_chunk(client, is, metadata.channels,
metadata.sample_rate,
n_blocks,
metadata.bitreverse);

View File

@ -324,7 +324,7 @@ faad_get_file_time(InputStream &is)
}
static void
faad_stream_decode(Decoder &mpd_decoder, InputStream &is,
faad_stream_decode(DecoderClient &client, InputStream &is,
DecoderBuffer &buffer, const NeAACDecHandle decoder)
{
const auto total_time = faad_song_duration(buffer, is);
@ -339,7 +339,7 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is,
/* initialize the MPD core */
decoder_initialized(mpd_decoder, audio_format, false, total_time);
decoder_initialized(client, audio_format, false, total_time);
/* the decoder loop */
@ -393,16 +393,16 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is,
/* send PCM samples to MPD */
cmd = decoder_data(mpd_decoder, is, decoded,
cmd = decoder_data(client, is, decoded,
(size_t)frame_info.samples * 2,
bit_rate);
} while (cmd != DecoderCommand::STOP);
}
static void
faad_stream_decode(Decoder &mpd_decoder, InputStream &is)
faad_stream_decode(DecoderClient &client, InputStream &is)
{
DecoderBuffer buffer(&mpd_decoder, is,
DecoderBuffer buffer(&client, is,
FAAD_MIN_STREAMSIZE * MAX_CHANNELS);
/* create the libfaad decoder */
@ -410,7 +410,7 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is)
const NeAACDecHandle decoder = faad_decoder_new();
AtScopeExit(decoder) { NeAACDecClose(decoder); };
faad_stream_decode(mpd_decoder, is, buffer, decoder);
faad_stream_decode(client, is, buffer, decoder);
}
static bool

View File

@ -221,7 +221,7 @@ PtsToPcmFrame(uint64_t pts, const AVStream &stream,
* Invoke decoder_data() with the contents of an #AVFrame.
*/
static DecoderCommand
FfmpegSendFrame(Decoder &decoder, InputStream &is,
FfmpegSendFrame(DecoderClient &client, InputStream &is,
AVCodecContext &codec_context,
const AVFrame &frame,
size_t &skip_bytes,
@ -250,7 +250,7 @@ FfmpegSendFrame(Decoder &decoder, InputStream &is,
skip_bytes = 0;
}
return decoder_data(decoder, is,
return decoder_data(client, is,
output_buffer.data, output_buffer.size,
codec_context.bit_rate / 1000);
}
@ -258,7 +258,7 @@ FfmpegSendFrame(Decoder &decoder, InputStream &is,
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 0)
static DecoderCommand
FfmpegReceiveFrames(Decoder &decoder, InputStream &is,
FfmpegReceiveFrames(DecoderClient &client, InputStream &is,
AVCodecContext &codec_context,
AVFrame &frame,
size_t &skip_bytes,
@ -271,7 +271,7 @@ FfmpegReceiveFrames(Decoder &decoder, InputStream &is,
int err = avcodec_receive_frame(&codec_context, &frame);
switch (err) {
case 0:
cmd = FfmpegSendFrame(decoder, is, codec_context,
cmd = FfmpegSendFrame(client, is, codec_context,
frame, skip_bytes,
buffer);
if (cmd != DecoderCommand::NONE)
@ -312,7 +312,7 @@ FfmpegReceiveFrames(Decoder &decoder, InputStream &is,
* desired time stamp has been reached
*/
static DecoderCommand
ffmpeg_send_packet(Decoder &decoder, InputStream &is,
ffmpeg_send_packet(DecoderClient &client, InputStream &is,
AVPacket &&packet,
AVCodecContext &codec_context,
const AVStream &stream,
@ -330,7 +330,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is,
if (cur_frame < min_frame)
skip_bytes = pcm_frame_size * (min_frame - cur_frame);
} else
decoder_timestamp(decoder,
decoder_timestamp(client,
FfmpegTimeToDouble(pts,
stream.time_base));
}
@ -358,7 +358,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is,
return DecoderCommand::NONE;
}
auto cmd = FfmpegReceiveFrames(decoder, is, codec_context,
auto cmd = FfmpegReceiveFrames(client, is, codec_context,
frame,
skip_bytes, buffer, eof);
@ -383,7 +383,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is,
if (!got_frame || frame.nb_samples <= 0)
continue;
cmd = FfmpegSendFrame(decoder, is, codec_context,
cmd = FfmpegSendFrame(client, is, codec_context,
frame, skip_bytes,
buffer);
}
@ -393,7 +393,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is,
}
static DecoderCommand
ffmpeg_send_packet(Decoder &decoder, InputStream &is,
ffmpeg_send_packet(DecoderClient &client, InputStream &is,
const AVPacket &packet,
AVCodecContext &codec_context,
const AVStream &stream,
@ -401,7 +401,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is,
uint64_t min_frame, size_t pcm_frame_size,
FfmpegBuffer &buffer)
{
return ffmpeg_send_packet(decoder, is,
return ffmpeg_send_packet(client, is,
/* copy the AVPacket, because FFmpeg
< 3.0 requires this */
AVPacket(packet),
@ -446,13 +446,13 @@ ffmpeg_sample_format(enum AVSampleFormat sample_fmt)
}
static AVInputFormat *
ffmpeg_probe(Decoder *decoder, InputStream &is)
ffmpeg_probe(DecoderClient *client, InputStream &is)
{
constexpr size_t BUFFER_SIZE = 16384;
constexpr size_t PADDING = 16;
unsigned char buffer[BUFFER_SIZE];
size_t nbytes = decoder_read(decoder, is, buffer, BUFFER_SIZE);
size_t nbytes = decoder_read(client, is, buffer, BUFFER_SIZE);
if (nbytes <= PADDING)
return nullptr;
@ -528,7 +528,7 @@ FfmpegParseMetaData(const AVFormatContext &format_context, int audio_stream,
}
static void
FfmpegParseMetaData(Decoder &decoder,
FfmpegParseMetaData(DecoderClient &client,
const AVFormatContext &format_context, int audio_stream)
{
ReplayGainInfo rg;
@ -540,10 +540,10 @@ FfmpegParseMetaData(Decoder &decoder,
FfmpegParseMetaData(format_context, audio_stream, rg, mr);
if (rg.IsDefined())
decoder_replay_gain(decoder, &rg);
decoder_replay_gain(client, &rg);
if (mr.IsDefined())
decoder_mixramp(decoder, std::move(mr));
decoder_mixramp(client, std::move(mr));
}
static void
@ -579,7 +579,7 @@ FfmpegScanTag(const AVFormatContext &format_context, int audio_stream,
* decoder_tag().
*/
static void
FfmpegCheckTag(Decoder &decoder, InputStream &is,
FfmpegCheckTag(DecoderClient &client, InputStream &is,
AVFormatContext &format_context, int audio_stream)
{
AVStream &stream = *format_context.streams[audio_stream];
@ -593,13 +593,13 @@ FfmpegCheckTag(Decoder &decoder, InputStream &is,
TagBuilder tag;
FfmpegScanTag(format_context, audio_stream, tag);
if (!tag.IsEmpty())
decoder_tag(decoder, is, tag.Commit());
decoder_tag(client, is, tag.Commit());
}
#endif
static void
FfmpegDecode(Decoder &decoder, InputStream &input,
FfmpegDecode(DecoderClient &client, InputStream &input,
AVFormatContext &format_context)
{
const int find_result =
@ -689,10 +689,10 @@ FfmpegDecode(Decoder &decoder, InputStream &input,
const SignedSongTime total_time =
FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base);
decoder_initialized(decoder, audio_format,
decoder_initialized(client, audio_format,
input.IsSeekable(), total_time);
FfmpegParseMetaData(decoder, format_context, audio_stream);
FfmpegParseMetaData(client, format_context, audio_stream);
#if LIBAVUTIL_VERSION_MAJOR >= 53
AVFrame *frame = av_frame_alloc();
@ -718,11 +718,11 @@ FfmpegDecode(Decoder &decoder, InputStream &input,
uint64_t min_frame = 0;
DecoderCommand cmd = decoder_get_command(decoder);
DecoderCommand cmd = decoder_get_command(client);
while (cmd != DecoderCommand::STOP) {
if (cmd == DecoderCommand::SEEK) {
int64_t where =
ToFfmpegTime(decoder_seek_time(decoder),
ToFfmpegTime(decoder_seek_time(client),
av_stream.time_base) +
start_time_fallback(av_stream);
@ -731,11 +731,11 @@ FfmpegDecode(Decoder &decoder, InputStream &input,
stamp, not after */
if (av_seek_frame(&format_context, audio_stream, where,
AVSEEK_FLAG_ANY|AVSEEK_FLAG_BACKWARD) < 0)
decoder_seek_error(decoder);
decoder_seek_error(client);
else {
avcodec_flush_buffers(codec_context);
min_frame = decoder_seek_where_frame(decoder);
decoder_command_finished(decoder);
min_frame = decoder_seek_where_frame(client);
decoder_command_finished(client);
}
}
@ -745,11 +745,11 @@ FfmpegDecode(Decoder &decoder, InputStream &input,
break;
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
FfmpegCheckTag(decoder, input, format_context, audio_stream);
FfmpegCheckTag(client, input, format_context, audio_stream);
#endif
if (packet.size > 0 && packet.stream_index == audio_stream) {
cmd = ffmpeg_send_packet(decoder, input,
cmd = ffmpeg_send_packet(client, input,
packet,
*codec_context,
av_stream,
@ -758,7 +758,7 @@ FfmpegDecode(Decoder &decoder, InputStream &input,
interleaved_buffer);
min_frame = 0;
} else
cmd = decoder_get_command(decoder);
cmd = decoder_get_command(client);
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 25, 100)
av_packet_unref(&packet);
@ -769,16 +769,16 @@ FfmpegDecode(Decoder &decoder, InputStream &input,
}
static void
ffmpeg_decode(Decoder &decoder, InputStream &input)
ffmpeg_decode(DecoderClient &client, InputStream &input)
{
AVInputFormat *input_format = ffmpeg_probe(&decoder, input);
AVInputFormat *input_format = ffmpeg_probe(&client, input);
if (input_format == nullptr)
return;
FormatDebug(ffmpeg_domain, "detected input format '%s' (%s)",
input_format->name, input_format->long_name);
AvioStream stream(&decoder, input);
AvioStream stream(&client, input);
if (!stream.Open()) {
LogError(ffmpeg_domain, "Failed to open stream");
return;
@ -797,7 +797,7 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
avformat_close_input(&format_context);
};
FfmpegDecode(decoder, input, *format_context);
FfmpegDecode(client, input, *format_context);
}
static bool

View File

@ -38,7 +38,7 @@ AvioStream::~AvioStream()
inline int
AvioStream::Read(void *dest, int size)
{
return decoder_read(decoder, input, dest, size);
return decoder_read(client, input, dest, size);
}
inline int64_t

View File

@ -28,17 +28,17 @@ extern "C" {
#include <stdint.h>
class DecoderClient;
class InputStream;
struct Decoder;
struct AvioStream {
Decoder *const decoder;
DecoderClient *const client;
InputStream &input;
AVIOContext *io;
AvioStream(Decoder *_decoder, InputStream &_input)
:decoder(_decoder), input(_input), io(nullptr) {}
AvioStream(DecoderClient *_client, InputStream &_input)
:client(_client), input(_input), io(nullptr) {}
~AvioStream();

View File

@ -52,7 +52,7 @@ FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample,
audio_format.sample_rate)
: SignedSongTime::Negative();
decoder_initialized(*GetDecoder(), audio_format,
decoder_initialized(*GetClient(), audio_format,
GetInputStream().IsSeekable(),
duration);
@ -77,9 +77,9 @@ FlacDecoder::OnVorbisComment(const FLAC__StreamMetadata_VorbisComment &vc)
{
ReplayGainInfo rgi;
if (flac_parse_replay_gain(rgi, vc))
decoder_replay_gain(*GetDecoder(), &rgi);
decoder_replay_gain(*GetClient(), &rgi);
decoder_mixramp(*GetDecoder(), flac_parse_mixramp(vc));
decoder_mixramp(*GetClient(), flac_parse_mixramp(vc));
tag = flac_vorbis_comments_to_tag(&vc);
}
@ -148,7 +148,7 @@ FlacDecoder::OnWrite(const FLAC__Frame &frame,
unsigned bit_rate = nbytes * 8 * frame.header.sample_rate /
(1000 * frame.header.blocksize);
auto cmd = decoder_data(*GetDecoder(), GetInputStream(),
auto cmd = decoder_data(*GetClient(), GetInputStream(),
data.data, data.size,
bit_rate);
switch (cmd) {

View File

@ -51,8 +51,8 @@ struct FlacDecoder : public FlacInput {
Tag tag;
FlacDecoder(Decoder &_decoder, InputStream &_input_stream)
:FlacInput(_input_stream, &_decoder) {}
FlacDecoder(DecoderClient &_client, InputStream &_input_stream)
:FlacInput(_input_stream, &_client) {}
/**
* Wrapper for decoder_initialized().

View File

@ -142,25 +142,25 @@ flac_decoder_initialize(FlacDecoder *data, FLAC__StreamDecoder *sd)
static void
flac_decoder_loop(FlacDecoder *data, FLAC__StreamDecoder *flac_dec)
{
Decoder &decoder = *data->GetDecoder();
DecoderClient &client = *data->GetClient();
while (true) {
DecoderCommand cmd;
if (!data->tag.IsEmpty()) {
cmd = decoder_tag(decoder, data->GetInputStream(),
cmd = decoder_tag(client, data->GetInputStream(),
std::move(data->tag));
data->tag.Clear();
} else
cmd = decoder_get_command(decoder);
cmd = decoder_get_command(client);
if (cmd == DecoderCommand::SEEK) {
FLAC__uint64 seek_sample =
decoder_seek_where_frame(decoder);
decoder_seek_where_frame(client);
if (FLAC__stream_decoder_seek_absolute(flac_dec, seek_sample)) {
data->position = 0;
decoder_command_finished(decoder);
decoder_command_finished(client);
} else
decoder_seek_error(decoder);
decoder_seek_error(client);
} else if (cmd == DecoderCommand::STOP)
break;
@ -198,7 +198,7 @@ flac_decoder_loop(FlacDecoder *data, FLAC__StreamDecoder *flac_dec)
}
if (!FLAC__stream_decoder_process_single(flac_dec) &&
decoder_get_command(decoder) == DecoderCommand::NONE) {
decoder_get_command(client) == DecoderCommand::NONE) {
/* a failure that was not triggered by a
decoder command */
flacPrintErroredState(FLAC__stream_decoder_get_state(flac_dec));
@ -264,7 +264,7 @@ FlacInitAndDecode(FlacDecoder &data, FLAC__StreamDecoder *sd, bool is_ogg)
}
static void
flac_decode_internal(Decoder &decoder,
flac_decode_internal(DecoderClient &client,
InputStream &input_stream,
bool is_ogg)
{
@ -272,15 +272,15 @@ flac_decode_internal(Decoder &decoder,
if (!flac_dec)
return;
FlacDecoder data(decoder, input_stream);
FlacDecoder data(client, input_stream);
FlacInitAndDecode(data, flac_dec.get(), is_ogg);
}
static void
flac_decode(Decoder &decoder, InputStream &input_stream)
flac_decode(DecoderClient &client, InputStream &input_stream)
{
flac_decode_internal(decoder, input_stream, false);
flac_decode_internal(client, input_stream, false);
}
static bool
@ -322,9 +322,9 @@ oggflac_scan_stream(InputStream &is,
}
static void
oggflac_decode(Decoder &decoder, InputStream &input_stream)
oggflac_decode(DecoderClient &client, InputStream &input_stream)
{
if (ogg_codec_detect(&decoder, input_stream) != OGG_CODEC_FLAC)
if (ogg_codec_detect(&client, input_stream) != OGG_CODEC_FLAC)
return;
/* rewind the stream, because ogg_codec_detect() has
@ -334,7 +334,7 @@ oggflac_decode(Decoder &decoder, InputStream &input_stream)
} catch (const std::runtime_error &) {
}
flac_decode_internal(decoder, input_stream, true);
flac_decode_internal(client, input_stream, true);
}
static const char *const oggflac_suffixes[] = { "ogg", "oga", nullptr };

View File

@ -30,13 +30,13 @@
FLAC__StreamDecoderReadStatus
FlacInput::Read(FLAC__byte buffer[], size_t *bytes)
{
size_t r = decoder_read(decoder, input_stream, (void *)buffer, *bytes);
size_t r = decoder_read(client, input_stream, (void *)buffer, *bytes);
*bytes = r;
if (r == 0) {
if (input_stream.LockIsEOF() ||
(decoder != nullptr &&
decoder_get_command(*decoder) != DecoderCommand::NONE))
(client != nullptr &&
decoder_get_command(*client) != DecoderCommand::NONE))
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
else
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
@ -83,17 +83,17 @@ FlacInput::Length(FLAC__uint64 *stream_length)
FLAC__bool
FlacInput::Eof()
{
return (decoder != nullptr &&
decoder_get_command(*decoder) != DecoderCommand::NONE &&
decoder_get_command(*decoder) != DecoderCommand::SEEK) ||
return (client != nullptr &&
decoder_get_command(*client) != DecoderCommand::NONE &&
decoder_get_command(*client) != DecoderCommand::SEEK) ||
input_stream.LockIsEOF();
}
void
FlacInput::Error(FLAC__StreamDecoderErrorStatus status)
{
if (decoder == nullptr ||
decoder_get_command(*decoder) != DecoderCommand::STOP)
if (client == nullptr ||
decoder_get_command(*client) != DecoderCommand::STOP)
LogWarning(flac_domain,
FLAC__StreamDecoderErrorStatusString[status]);
}

View File

@ -22,7 +22,7 @@
#include <FLAC/stream_decoder.h>
struct Decoder;
class DecoderClient;
class InputStream;
/**
@ -30,17 +30,17 @@ class InputStream;
* callbacks.
*/
class FlacInput {
Decoder *const decoder;
DecoderClient *const client;
InputStream &input_stream;
public:
FlacInput(InputStream &_input_stream,
Decoder *_decoder=nullptr)
:decoder(_decoder), input_stream(_input_stream) {}
DecoderClient *_client=nullptr)
:client(_client), input_stream(_input_stream) {}
Decoder *GetDecoder() {
return decoder;
DecoderClient *GetClient() {
return client;
}
InputStream &GetInputStream() {

View File

@ -87,7 +87,7 @@ fluidsynth_init(const ConfigBlock &block)
}
static void
fluidsynth_file_decode(Decoder &decoder, Path path_fs)
fluidsynth_file_decode(DecoderClient &client, Path path_fs)
{
char setting_sample_rate[] = "synth.sample-rate";
/*
@ -160,7 +160,7 @@ fluidsynth_file_decode(Decoder &decoder, Path path_fs)
MPD core */
const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
decoder_initialized(decoder, audio_format, false,
decoder_initialized(client, audio_format, false,
SignedSongTime::Negative());
DecoderCommand cmd;
@ -177,7 +177,7 @@ fluidsynth_file_decode(Decoder &decoder, Path path_fs)
if (ret != 0)
break;
cmd = decoder_data(decoder, nullptr, buffer, sizeof(buffer),
cmd = decoder_data(client, nullptr, buffer, sizeof(buffer),
0);
if (cmd != DecoderCommand::NONE)
break;

View File

@ -129,7 +129,7 @@ gme_container_scan(Path path_fs, const unsigned int tnum)
}
static void
gme_file_decode(Decoder &decoder, Path path_fs)
gme_file_decode(DecoderClient &client, Path path_fs)
{
const auto container = ParseContainerPath(path_fs);
@ -171,7 +171,7 @@ gme_file_decode(Decoder &decoder, Path path_fs)
SampleFormat::S16,
GME_CHANNELS);
decoder_initialized(decoder, audio_format, true, song_len);
decoder_initialized(client, audio_format, true, song_len);
gme_err = gme_start_track(emu, container.track);
if (gme_err != nullptr)
@ -190,15 +190,15 @@ gme_file_decode(Decoder &decoder, Path path_fs)
return;
}
cmd = decoder_data(decoder, nullptr, buf, sizeof(buf), 0);
cmd = decoder_data(client, nullptr, buf, sizeof(buf), 0);
if (cmd == DecoderCommand::SEEK) {
unsigned where = decoder_seek_time(decoder).ToMS();
unsigned where = decoder_seek_time(client).ToMS();
gme_err = gme_seek(emu, where);
if (gme_err != nullptr) {
LogWarning(gme_domain, gme_err);
decoder_seek_error(decoder);
decoder_seek_error(client);
} else
decoder_command_finished(decoder);
decoder_command_finished(client);
}
if (gme_track_ended(emu))

View File

@ -141,11 +141,11 @@ struct MadDecoder {
bool found_first_frame = false;
bool decoded_first_frame = false;
unsigned long bit_rate;
Decoder *const decoder;
DecoderClient *const client;
InputStream &input_stream;
enum mad_layer layer = mad_layer(0);
MadDecoder(Decoder *decoder, InputStream &input_stream);
MadDecoder(DecoderClient *client, InputStream &input_stream);
~MadDecoder();
bool Seek(long offset);
@ -195,9 +195,9 @@ struct MadDecoder {
bool Read();
};
MadDecoder::MadDecoder(Decoder *_decoder,
MadDecoder::MadDecoder(DecoderClient *_client,
InputStream &_input_stream)
:decoder(_decoder), input_stream(_input_stream)
:client(_client), input_stream(_input_stream)
{
mad_stream_init(&stream);
mad_stream_options(&stream, MAD_OPTION_IGNORECRC);
@ -243,7 +243,7 @@ MadDecoder::FillBuffer()
if (length == 0)
return false;
length = decoder_read(decoder, input_stream, dest, length);
length = decoder_read(client, input_stream, dest, length);
if (length == 0)
return false;
@ -333,7 +333,7 @@ MadDecoder::ParseId3(size_t tagsize, Tag **mpd_tag)
memcpy(allocated, stream.this_frame, count);
mad_stream_skip(&(stream), count);
if (!decoder_read_full(decoder, input_stream,
if (!decoder_read_full(client, input_stream,
allocated + count, tagsize - count)) {
LogDebug(mad_domain, "error parsing ID3 tag");
delete[] allocated;
@ -357,15 +357,15 @@ MadDecoder::ParseId3(size_t tagsize, Tag **mpd_tag)
}
}
if (decoder != nullptr) {
if (client != nullptr) {
ReplayGainInfo rgi;
if (parse_id3_replay_gain_info(rgi, id3_tag)) {
decoder_replay_gain(*decoder, &rgi);
decoder_replay_gain(*client, &rgi);
found_replay_gain = true;
}
decoder_mixramp(*decoder, parse_id3_mixramp(id3_tag));
decoder_mixramp(*client, parse_id3_mixramp(id3_tag));
}
id3_tag_delete(id3_tag);
@ -383,7 +383,7 @@ MadDecoder::ParseId3(size_t tagsize, Tag **mpd_tag)
mad_stream_skip(&stream, tagsize);
} else {
mad_stream_skip(&stream, count);
decoder_skip(decoder, input_stream, tagsize - count);
decoder_skip(client, input_stream, tagsize - count);
}
#endif
}
@ -800,13 +800,13 @@ MadDecoder::DecodeFirstFrame(Tag **tag)
/* Album gain isn't currently used. See comment in
* parse_lame() for details. -- jat */
if (decoder != nullptr && !found_replay_gain &&
if (client != nullptr && !found_replay_gain &&
lame.track_gain) {
ReplayGainInfo rgi;
rgi.Clear();
rgi.tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain;
rgi.tuples[REPLAY_GAIN_TRACK].peak = lame.peak;
decoder_replay_gain(*decoder, &rgi);
decoder_replay_gain(*client, &rgi);
}
}
}
@ -903,7 +903,7 @@ MadDecoder::SendPCM(unsigned i, unsigned pcm_length)
MAD_NCHANNELS(&frame.header));
num_samples *= MAD_NCHANNELS(&frame.header);
auto cmd = decoder_data(*decoder, input_stream, output_buffer,
auto cmd = decoder_data(*client, input_stream, output_buffer,
sizeof(output_buffer[0]) * num_samples,
bit_rate / 1000);
if (cmd != DecoderCommand::NONE)
@ -986,17 +986,17 @@ MadDecoder::Read()
assert(input_stream.IsSeekable());
unsigned long j =
TimeToFrame(decoder_seek_time(*decoder));
TimeToFrame(decoder_seek_time(*client));
if (j < highest_frame) {
if (Seek(frame_offsets[j])) {
current_frame = j;
decoder_command_finished(*decoder);
decoder_command_finished(*client);
} else
decoder_seek_error(*decoder);
decoder_seek_error(*client);
} else {
seek_time = decoder_seek_time(*decoder);
seek_time = decoder_seek_time(*client);
mute_frame = MUTEFRAME_SEEK;
decoder_command_finished(*decoder);
decoder_command_finished(*client);
}
} else if (cmd != DecoderCommand::NONE)
return false;
@ -1010,7 +1010,7 @@ MadDecoder::Read()
ret = DecodeNextFrameHeader(&tag);
if (tag != nullptr) {
decoder_tag(*decoder, input_stream,
decoder_tag(*client, input_stream,
std::move(*tag));
delete tag;
}
@ -1034,15 +1034,15 @@ MadDecoder::Read()
}
static void
mp3_decode(Decoder &decoder, InputStream &input_stream)
mp3_decode(DecoderClient &client, InputStream &input_stream)
{
MadDecoder data(&decoder, input_stream);
MadDecoder data(&client, input_stream);
Tag *tag = nullptr;
if (!data.DecodeFirstFrame(&tag)) {
delete tag;
if (decoder_get_command(decoder) == DecoderCommand::NONE)
if (decoder_get_command(client) == DecoderCommand::NONE)
LogError(mad_domain,
"input/Input does not appear to be a mp3 bit stream");
return;
@ -1050,7 +1050,7 @@ mp3_decode(Decoder &decoder, InputStream &input_stream)
data.AllocateBuffers();
decoder_initialized(decoder,
decoder_initialized(client,
CheckAudioFormat(data.frame.header.samplerate,
SampleFormat::S24_P32,
MAD_NCHANNELS(&data.frame.header)),
@ -1058,7 +1058,7 @@ mp3_decode(Decoder &decoder, InputStream &input_stream)
data.total_time);
if (tag != nullptr) {
decoder_tag(decoder, input_stream, std::move(*tag));
decoder_tag(client, input_stream, std::move(*tag));
delete tag;
}

View File

@ -147,7 +147,7 @@ mikmod_decoder_finish(void)
}
static void
mikmod_decoder_file_decode(Decoder &decoder, Path path_fs)
mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
{
/* deconstify the path because libmikmod wants a non-const
string pointer */
@ -170,7 +170,7 @@ mikmod_decoder_file_decode(Decoder &decoder, Path path_fs)
const AudioFormat audio_format(mikmod_sample_rate, SampleFormat::S16, 2);
assert(audio_format.IsValid());
decoder_initialized(decoder, audio_format, false,
decoder_initialized(client, audio_format, false,
SignedSongTime::Negative());
Player_Start(handle);
@ -178,7 +178,7 @@ mikmod_decoder_file_decode(Decoder &decoder, Path path_fs)
DecoderCommand cmd = DecoderCommand::NONE;
while (cmd == DecoderCommand::NONE && Player_Active()) {
ret = VC_WriteBytes(buffer, sizeof(buffer));
cmd = decoder_data(decoder, nullptr, buffer, ret, 0);
cmd = decoder_data(client, nullptr, buffer, ret, 0);
}
Player_Stop();

View File

@ -52,7 +52,7 @@ modplug_decoder_init(const ConfigBlock &block)
}
static WritableBuffer<uint8_t>
mod_loadfile(Decoder *decoder, InputStream &is)
mod_loadfile(DecoderClient *client, InputStream &is)
{
//known/unknown size, preallocate array, lets read in chunks
@ -83,7 +83,7 @@ mod_loadfile(Decoder *decoder, InputStream &is)
uint8_t *p = buffer.begin();
while (true) {
size_t ret = decoder_read(decoder, is, p, end - p);
size_t ret = decoder_read(client, is, p, end - p);
if (ret == 0) {
if (is.LockIsEOF())
/* end of file */
@ -112,9 +112,9 @@ mod_loadfile(Decoder *decoder, InputStream &is)
}
static ModPlugFile *
LoadModPlugFile(Decoder *decoder, InputStream &is)
LoadModPlugFile(DecoderClient *client, InputStream &is)
{
const auto buffer = mod_loadfile(decoder, is);
const auto buffer = mod_loadfile(client, is);
if (buffer.IsNull()) {
LogWarning(modplug_domain, "could not load stream");
return nullptr;
@ -126,7 +126,7 @@ LoadModPlugFile(Decoder *decoder, InputStream &is)
}
static void
mod_decode(Decoder &decoder, InputStream &is)
mod_decode(DecoderClient &client, InputStream &is)
{
ModPlug_Settings settings;
int ret;
@ -142,7 +142,7 @@ mod_decode(Decoder &decoder, InputStream &is)
/* insert more setting changes here */
ModPlug_SetSettings(&settings);
ModPlugFile *f = LoadModPlugFile(&decoder, is);
ModPlugFile *f = LoadModPlugFile(&client, is);
if (f == nullptr) {
LogWarning(modplug_domain, "could not decode stream");
return;
@ -151,7 +151,7 @@ mod_decode(Decoder &decoder, InputStream &is)
static constexpr AudioFormat audio_format(44100, SampleFormat::S16, 2);
assert(audio_format.IsValid());
decoder_initialized(decoder, audio_format,
decoder_initialized(client, audio_format,
is.IsSeekable(),
SongTime::FromMS(ModPlug_GetLength(f)));
@ -161,13 +161,13 @@ mod_decode(Decoder &decoder, InputStream &is)
if (ret <= 0)
break;
cmd = decoder_data(decoder, nullptr,
cmd = decoder_data(client, nullptr,
audio_buffer, ret,
0);
if (cmd == DecoderCommand::SEEK) {
ModPlug_Seek(f, decoder_seek_time(decoder).ToMS());
decoder_command_finished(decoder);
ModPlug_Seek(f, decoder_seek_time(client).ToMS());
decoder_command_finished(client);
}
} while (cmd != DecoderCommand::STOP);

View File

@ -37,10 +37,10 @@
struct mpc_decoder_data {
InputStream &is;
Decoder *decoder;
DecoderClient *client;
mpc_decoder_data(InputStream &_is, Decoder *_decoder)
:is(_is), decoder(_decoder) {}
mpc_decoder_data(InputStream &_is, DecoderClient *_client)
:is(_is), client(_client) {}
};
static constexpr Domain mpcdec_domain("mpcdec");
@ -54,7 +54,7 @@ mpc_read_cb(mpc_reader *reader, void *ptr, mpc_int32_t size)
struct mpc_decoder_data *data =
(struct mpc_decoder_data *)reader->data;
return decoder_read(data->decoder, data->is, ptr, size);
return decoder_read(data->client, data->is, ptr, size);
}
static mpc_bool_t
@ -138,9 +138,9 @@ mpc_to_mpd_buffer(MpcdecSampleTraits::pointer_type dest,
}
static void
mpcdec_decode(Decoder &mpd_decoder, InputStream &is)
mpcdec_decode(DecoderClient &client, InputStream &is)
{
mpc_decoder_data data(is, &mpd_decoder);
mpc_decoder_data data(is, &client);
mpc_reader reader;
reader.read = mpc_read_cb;
@ -152,7 +152,7 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is)
mpc_demux *demux = mpc_demux_init(&reader);
if (demux == nullptr) {
if (decoder_get_command(mpd_decoder) != DecoderCommand::STOP)
if (decoder_get_command(client) != DecoderCommand::STOP)
LogWarning(mpcdec_domain,
"Not a valid musepack stream");
return;
@ -172,9 +172,9 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is)
rgi.tuples[REPLAY_GAIN_TRACK].gain = MPC_OLD_GAIN_REF - (info.gain_title / 256.);
rgi.tuples[REPLAY_GAIN_TRACK].peak = pow(10, info.peak_title / 256. / 20) / 32767;
decoder_replay_gain(mpd_decoder, &rgi);
decoder_replay_gain(client, &rgi);
decoder_initialized(mpd_decoder, audio_format,
decoder_initialized(client, audio_format,
is.IsSeekable(),
SongTime::FromS(mpc_streaminfo_get_length(&info)));
@ -182,15 +182,15 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is)
do {
if (cmd == DecoderCommand::SEEK) {
mpc_int64_t where =
decoder_seek_where_frame(mpd_decoder);
decoder_seek_where_frame(client);
bool success;
success = mpc_demux_seek_sample(demux, where)
== MPC_STATUS_OK;
if (success)
decoder_command_finished(mpd_decoder);
decoder_command_finished(client);
else
decoder_seek_error(mpd_decoder);
decoder_seek_error(client);
}
MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH];
@ -215,7 +215,7 @@ mpcdec_decode(Decoder &mpd_decoder, InputStream &is)
long bit_rate = unsigned(frame.bits) * audio_format.sample_rate
/ (1000 * frame.samples);
cmd = decoder_data(mpd_decoder, is,
cmd = decoder_data(client, is,
chunk, ret * sizeof(chunk[0]),
bit_rate);
} while (cmd != DecoderCommand::STOP);

View File

@ -116,7 +116,7 @@ AddTagItem(TagBuilder &tag, TagType type, const mpg123_string *s)
}
static void
mpd_mpg123_id3v2_tag(Decoder &decoder, const mpg123_id3v2 &id3v2)
mpd_mpg123_id3v2_tag(DecoderClient &client, const mpg123_id3v2 &id3v2)
{
TagBuilder tag;
@ -129,11 +129,11 @@ mpd_mpg123_id3v2_tag(Decoder &decoder, const mpg123_id3v2 &id3v2)
for (size_t i = 0, n = id3v2.comments; i < n; ++i)
AddTagItem(tag, TAG_COMMENT, id3v2.comment_list[i].text);
decoder_tag(decoder, nullptr, tag.Commit());
decoder_tag(client, nullptr, tag.Commit());
}
static void
mpd_mpg123_id3v2_extras(Decoder &decoder, const mpg123_id3v2 &id3v2)
mpd_mpg123_id3v2_extras(DecoderClient &client, const mpg123_id3v2 &id3v2)
{
ReplayGainInfo replay_gain;
replay_gain.Clear();
@ -154,21 +154,21 @@ mpd_mpg123_id3v2_extras(Decoder &decoder, const mpg123_id3v2 &id3v2)
}
if (found_replay_gain)
decoder_replay_gain(decoder, &replay_gain);
decoder_replay_gain(client, &replay_gain);
if (found_mixramp)
decoder_mixramp(decoder, std::move(mix_ramp));
decoder_mixramp(client, std::move(mix_ramp));
}
static void
mpd_mpg123_id3v2(Decoder &decoder, const mpg123_id3v2 &id3v2)
mpd_mpg123_id3v2(DecoderClient &client, const mpg123_id3v2 &id3v2)
{
mpd_mpg123_id3v2_tag(decoder, id3v2);
mpd_mpg123_id3v2_extras(decoder, id3v2);
mpd_mpg123_id3v2_tag(client, id3v2);
mpd_mpg123_id3v2_extras(client, id3v2);
}
static void
mpd_mpg123_meta(Decoder &decoder, mpg123_handle *const handle)
mpd_mpg123_meta(DecoderClient &client, mpg123_handle *const handle)
{
if ((mpg123_meta_check(handle) & MPG123_NEW_ID3) == 0)
return;
@ -179,11 +179,11 @@ mpd_mpg123_meta(Decoder &decoder, mpg123_handle *const handle)
return;
if (v2 != nullptr)
mpd_mpg123_id3v2(decoder, *v2);
mpd_mpg123_id3v2(client, *v2);
}
static void
mpd_mpg123_file_decode(Decoder &decoder, Path path_fs)
mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
{
/* open the file */
@ -210,7 +210,7 @@ mpd_mpg123_file_decode(Decoder &decoder, Path path_fs)
SongTime::FromScale<uint64_t>(num_samples,
audio_format.sample_rate);
decoder_initialized(decoder, audio_format, true, duration);
decoder_initialized(client, audio_format, true, duration);
struct mpg123_frameinfo info;
if (mpg123_info(handle, &info) != MPG123_OK) {
@ -232,7 +232,7 @@ mpd_mpg123_file_decode(Decoder &decoder, Path path_fs)
DecoderCommand cmd;
do {
/* read metadata */
mpd_mpg123_meta(decoder, handle);
mpd_mpg123_meta(client, handle);
/* decode */
@ -257,16 +257,16 @@ mpd_mpg123_file_decode(Decoder &decoder, Path path_fs)
/* send to MPD */
cmd = decoder_data(decoder, nullptr, buffer, nbytes, info.bitrate);
cmd = decoder_data(client, nullptr, buffer, nbytes, info.bitrate);
if (cmd == DecoderCommand::SEEK) {
off_t c = decoder_seek_where_frame(decoder);
off_t c = decoder_seek_where_frame(client);
c = mpg123_seek(handle, c, SEEK_SET);
if (c < 0)
decoder_seek_error(decoder);
decoder_seek_error(client);
else {
decoder_command_finished(decoder);
decoder_timestamp(decoder, c/(double)audio_format.sample_rate);
decoder_command_finished(client);
decoder_timestamp(client, c/(double)audio_format.sample_rate);
}
cmd = DecoderCommand::NONE;

View File

@ -28,13 +28,13 @@
#include <string.h>
enum ogg_codec
ogg_codec_detect(Decoder *decoder, InputStream &is)
ogg_codec_detect(DecoderClient *client, InputStream &is)
{
/* oggflac detection based on code in ogg123 and this post
* http://lists.xiph.org/pipermail/flac/2004-December/000393.html
* ogg123 trunk still doesn't have this patch as of June 2005 */
unsigned char buf[41];
size_t r = decoder_read(decoder, is, buf, sizeof(buf));
size_t r = decoder_read(client, is, buf, sizeof(buf));
if (r < sizeof(buf) || memcmp(buf, "OggS", 4) != 0)
return OGG_CODEC_UNKNOWN;

View File

@ -24,7 +24,7 @@
#ifndef MPD_OGG_CODEC_HXX
#define MPD_OGG_CODEC_HXX
struct Decoder;
class DecoderClient;
class InputStream;
enum ogg_codec {
@ -35,6 +35,6 @@ enum ogg_codec {
};
enum ogg_codec
ogg_codec_detect(Decoder *decoder, InputStream &is);
ogg_codec_detect(DecoderClient *client, InputStream &is);
#endif /* _OGG_COMMON_H */

View File

@ -45,7 +45,7 @@ OggDecoder::LoadEndPacket(ogg_packet &packet) const
bool result;
{
DecoderReader reader(decoder, input_stream);
DecoderReader reader(client, input_stream);
OggSyncState sync2(reader);
OggStreamState stream2(GetSerialNo());
result = OggSeekFindEOS(sync2, stream2, packet,

View File

@ -28,13 +28,13 @@ class OggDecoder : public OggVisitor {
ogg_int64_t end_granulepos;
protected:
Decoder &decoder;
DecoderClient &client;
InputStream &input_stream;
public:
explicit OggDecoder(DecoderReader &reader)
:OggVisitor(reader),
decoder(reader.GetDecoder()),
client(reader.GetClient()),
input_stream(reader.GetInputStream()) {}
bool Seek(OggSyncState &oy, uint64_t where_frame);

View File

@ -175,14 +175,14 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet)
previous_channels = channels;
const AudioFormat audio_format(opus_sample_rate,
SampleFormat::S16, channels);
decoder_initialized(decoder, audio_format,
decoder_initialized(client, audio_format,
eos_granulepos > 0, duration);
frame_size = audio_format.GetFrameSize();
output_buffer = new opus_int16[opus_output_buffer_frames
* audio_format.channels];
auto cmd = decoder_get_command(decoder);
auto cmd = decoder_get_command(client);
if (cmd != DecoderCommand::NONE)
throw cmd;
}
@ -213,10 +213,10 @@ MPDOpusDecoder::HandleTags(const ogg_packet &packet)
&rgi,
add_tag_handler, &tag_builder) &&
!tag_builder.IsEmpty()) {
decoder_replay_gain(decoder, &rgi);
decoder_replay_gain(client, &rgi);
Tag tag = tag_builder.Commit();
auto cmd = decoder_tag(decoder, input_stream, std::move(tag));
auto cmd = decoder_tag(client, input_stream, std::move(tag));
if (cmd != DecoderCommand::NONE)
throw cmd;
}
@ -238,14 +238,14 @@ MPDOpusDecoder::HandleAudio(const ogg_packet &packet)
if (nframes > 0) {
const size_t nbytes = nframes * frame_size;
auto cmd = decoder_data(decoder, input_stream,
auto cmd = decoder_data(client, input_stream,
output_buffer, nbytes,
0);
if (cmd != DecoderCommand::NONE)
throw cmd;
if (packet.granulepos > 0)
decoder_timestamp(decoder,
decoder_timestamp(client,
double(packet.granulepos)
/ opus_sample_rate);
}
@ -269,10 +269,10 @@ MPDOpusDecoder::Seek(uint64_t where_frame)
}
static void
mpd_opus_stream_decode(Decoder &decoder,
mpd_opus_stream_decode(DecoderClient &client,
InputStream &input_stream)
{
if (ogg_codec_detect(&decoder, input_stream) != OGG_CODEC_OPUS)
if (ogg_codec_detect(&client, input_stream) != OGG_CODEC_OPUS)
return;
/* rewind the stream, because ogg_codec_detect() has
@ -282,7 +282,7 @@ mpd_opus_stream_decode(Decoder &decoder,
} catch (const std::runtime_error &) {
}
DecoderReader reader(decoder, input_stream);
DecoderReader reader(client, input_stream);
MPDOpusDecoder d(reader);
@ -292,10 +292,10 @@ mpd_opus_stream_decode(Decoder &decoder,
break;
} catch (DecoderCommand cmd) {
if (cmd == DecoderCommand::SEEK) {
if (d.Seek(decoder_seek_where_frame(decoder)))
decoder_command_finished(decoder);
if (d.Seek(decoder_seek_where_frame(client)))
decoder_command_finished(client);
else
decoder_seek_error(decoder);
decoder_seek_error(client);
} else if (cmd != DecoderCommand::NONE)
break;
}

View File

@ -39,13 +39,13 @@ static constexpr Domain pcm_decoder_domain("pcm_decoder");
template<typename B>
static bool
FillBuffer(Decoder &decoder, InputStream &is, B &buffer)
FillBuffer(DecoderClient &client, InputStream &is, B &buffer)
{
buffer.Shift();
auto w = buffer.Write();
assert(!w.IsEmpty());
size_t nbytes = decoder_read(decoder, is, w.data, w.size);
size_t nbytes = decoder_read(client, is, w.data, w.size);
if (nbytes == 0 && is.LockIsEOF())
return false;
@ -54,7 +54,7 @@ FillBuffer(Decoder &decoder, InputStream &is, B &buffer)
}
static void
pcm_stream_decode(Decoder &decoder, InputStream &is)
pcm_stream_decode(DecoderClient &client, InputStream &is)
{
AudioFormat audio_format = {
44100,
@ -143,14 +143,14 @@ pcm_stream_decode(Decoder &decoder, InputStream &is)
audio_format.sample_rate)
: SignedSongTime::Negative();
decoder_initialized(decoder, audio_format,
decoder_initialized(client, audio_format,
is.IsSeekable(), total_time);
StaticFifoBuffer<uint8_t, 4096> buffer;
DecoderCommand cmd;
do {
if (!FillBuffer(decoder, is, buffer))
if (!FillBuffer(client, is, buffer))
break;
auto r = buffer.Read();
@ -166,19 +166,19 @@ pcm_stream_decode(Decoder &decoder, InputStream &is)
(uint16_t *)(r.data + r.size));
cmd = !r.IsEmpty()
? decoder_data(decoder, is, r.data, r.size, 0)
: decoder_get_command(decoder);
? decoder_data(client, is, r.data, r.size, 0)
: decoder_get_command(client);
if (cmd == DecoderCommand::SEEK) {
uint64_t frame = decoder_seek_where_frame(decoder);
uint64_t frame = decoder_seek_where_frame(client);
offset_type offset = frame * frame_size;
try {
is.LockSeek(offset);
buffer.Clear();
decoder_command_finished(decoder);
decoder_command_finished(client);
} catch (const std::runtime_error &e) {
LogError(e);
decoder_seek_error(decoder);
decoder_seek_error(client);
}
cmd = DecoderCommand::NONE;

View File

@ -179,7 +179,7 @@ get_song_length(SidTuneMod &tune)
#endif
static void
sidplay_file_decode(Decoder &decoder, Path path_fs)
sidplay_file_decode(DecoderClient &client, Path path_fs)
{
int channels;
@ -337,7 +337,7 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
const AudioFormat audio_format(48000, SampleFormat::S16, channels);
assert(audio_format.IsValid());
decoder_initialized(decoder, audio_format, true, duration);
decoder_initialized(client, audio_format, true, duration);
/* .. and play */
@ -366,14 +366,14 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
const size_t nbytes = result;
#endif
decoder_timestamp(decoder, (double)player.time() / timebase);
decoder_timestamp(client, (double)player.time() / timebase);
cmd = decoder_data(decoder, nullptr, buffer, nbytes, 0);
cmd = decoder_data(client, nullptr, buffer, nbytes, 0);
if (cmd == DecoderCommand::SEEK) {
unsigned data_time = player.time();
unsigned target_time =
decoder_seek_time(decoder).ToScale(timebase);
decoder_seek_time(client).ToScale(timebase);
/* can't rewind so return to zero and seek forward */
if(target_time<data_time) {
@ -386,7 +386,7 @@ sidplay_file_decode(Decoder &decoder, Path path_fs)
player.play(buffer, ARRAY_SIZE(buffer)) > 0)
data_time = player.time();
decoder_command_finished(decoder);
decoder_command_finished(client);
}
if (end > 0 && player.time() >= end)

View File

@ -40,13 +40,13 @@ sndfile_init(gcc_unused const ConfigBlock &block)
}
struct SndfileInputStream {
Decoder *const decoder;
DecoderClient *const client;
InputStream &is;
size_t Read(void *buffer, size_t size) {
/* libsndfile chokes on partial reads; therefore
always force full reads */
return decoder_read_full(decoder, is, buffer, size)
return decoder_read_full(client, is, buffer, size)
? size
: 0;
}
@ -186,13 +186,13 @@ sndfile_read_frames(SNDFILE *sf, SampleFormat format,
}
static void
sndfile_stream_decode(Decoder &decoder, InputStream &is)
sndfile_stream_decode(DecoderClient &client, InputStream &is)
{
SF_INFO info;
info.format = 0;
SndfileInputStream sis{&decoder, is};
SndfileInputStream sis{&client, is};
SNDFILE *const sf = sf_open_virtual(&vio, SFM_READ, &info, &sis);
if (sf == nullptr) {
FormatWarning(sndfile_domain, "sf_open_virtual() failed: %s",
@ -205,7 +205,7 @@ sndfile_stream_decode(Decoder &decoder, InputStream &is)
sndfile_sample_format(info),
info.channels);
decoder_initialized(decoder, audio_format, info.seekable,
decoder_initialized(client, audio_format, info.seekable,
sndfile_duration(info));
char buffer[16384];
@ -222,16 +222,16 @@ sndfile_stream_decode(Decoder &decoder, InputStream &is)
if (num_frames <= 0)
break;
cmd = decoder_data(decoder, is,
cmd = decoder_data(client, is,
buffer, num_frames * frame_size,
0);
if (cmd == DecoderCommand::SEEK) {
sf_count_t c = decoder_seek_where_frame(decoder);
sf_count_t c = decoder_seek_where_frame(client);
c = sf_seek(sf, c, SEEK_SET);
if (c < 0)
decoder_seek_error(decoder);
decoder_seek_error(client);
else
decoder_command_finished(decoder);
decoder_command_finished(client);
cmd = DecoderCommand::NONE;
}
} while (cmd == DecoderCommand::NONE);

View File

@ -149,14 +149,14 @@ VorbisDecoder::OnOggBeginning(const ogg_packet &_packet)
}
static void
vorbis_send_comments(Decoder &decoder, InputStream &is,
vorbis_send_comments(DecoderClient &client, InputStream &is,
char **comments)
{
Tag *tag = vorbis_comments_to_tag(comments);
if (!tag)
return;
decoder_tag(decoder, is, std::move(*tag));
decoder_tag(client, is, std::move(*tag));
delete tag;
}
@ -175,7 +175,7 @@ VorbisDecoder::SubmitInit()
audio_format.sample_rate)
: SignedSongTime::Negative();
decoder_initialized(decoder, audio_format,
decoder_initialized(client, audio_format,
eos_granulepos > 0, duration);
}
@ -212,7 +212,7 @@ VorbisDecoder::SubmitSomePcm()
vorbis_synthesis_read(&dsp, n_frames);
const size_t nbytes = n_frames * frame_size;
auto cmd = decoder_data(decoder, input_stream,
auto cmd = decoder_data(client, input_stream,
buffer, nbytes,
0);
if (cmd != DecoderCommand::NONE)
@ -249,11 +249,11 @@ VorbisDecoder::OnOggPacket(const ogg_packet &_packet)
} else
SubmitInit();
vorbis_send_comments(decoder, input_stream, vc.user_comments);
vorbis_send_comments(client, input_stream, vc.user_comments);
ReplayGainInfo rgi;
if (vorbis_comments_to_replay_gain(rgi, vc.user_comments))
decoder_replay_gain(decoder, &rgi);
decoder_replay_gain(client, &rgi);
} else {
if (!dsp_initialized) {
dsp_initialized = true;
@ -265,7 +265,7 @@ VorbisDecoder::OnOggPacket(const ogg_packet &_packet)
if (vorbis_synthesis(&block, &packet) != 0) {
/* ignore bad packets, but give the MPD core a
chance to stop us */
auto cmd = decoder_get_command(decoder);
auto cmd = decoder_get_command(client);
if (cmd != DecoderCommand::NONE)
throw cmd;
return;
@ -278,7 +278,7 @@ VorbisDecoder::OnOggPacket(const ogg_packet &_packet)
#ifndef HAVE_TREMOR
if (packet.granulepos > 0)
decoder_timestamp(decoder,
decoder_timestamp(client,
vorbis_granule_time(&dsp, packet.granulepos));
#endif
}
@ -301,10 +301,10 @@ vorbis_init(gcc_unused const ConfigBlock &block)
}
static void
vorbis_stream_decode(Decoder &decoder,
vorbis_stream_decode(DecoderClient &client,
InputStream &input_stream)
{
if (ogg_codec_detect(&decoder, input_stream) != OGG_CODEC_VORBIS)
if (ogg_codec_detect(&client, input_stream) != OGG_CODEC_VORBIS)
return;
/* rewind the stream, because ogg_codec_detect() has
@ -314,7 +314,7 @@ vorbis_stream_decode(Decoder &decoder,
} catch (const std::runtime_error &) {
}
DecoderReader reader(decoder, input_stream);
DecoderReader reader(client, input_stream);
VorbisDecoder d(reader);
while (true) {
@ -323,10 +323,10 @@ vorbis_stream_decode(Decoder &decoder,
break;
} catch (DecoderCommand cmd) {
if (cmd == DecoderCommand::SEEK) {
if (d.Seek(decoder_seek_where_frame(decoder)))
decoder_command_finished(decoder);
if (d.Seek(decoder_seek_where_frame(client)))
decoder_command_finished(client);
else
decoder_seek_error(decoder);
decoder_seek_error(client);
} else if (cmd != DecoderCommand::NONE)
break;
}

View File

@ -141,7 +141,7 @@ wavpack_bits_to_sample_format(bool is_float, int bytes_per_sample)
* Requires an already opened WavpackContext.
*/
static void
wavpack_decode(Decoder &decoder, WavpackContext *wpc, bool can_seek)
wavpack_decode(DecoderClient &client, WavpackContext *wpc, bool can_seek)
{
bool is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0;
SampleFormat sample_format =
@ -168,21 +168,21 @@ wavpack_decode(Decoder &decoder, WavpackContext *wpc, bool can_seek)
const uint32_t samples_requested = ARRAY_SIZE(chunk) /
audio_format.channels;
decoder_initialized(decoder, audio_format, can_seek, total_time);
decoder_initialized(client, audio_format, can_seek, total_time);
DecoderCommand cmd = decoder_get_command(decoder);
DecoderCommand cmd = decoder_get_command(client);
while (cmd != DecoderCommand::STOP) {
if (cmd == DecoderCommand::SEEK) {
if (can_seek) {
auto where = decoder_seek_where_frame(decoder);
auto where = decoder_seek_where_frame(client);
if (WavpackSeekSample(wpc, where)) {
decoder_command_finished(decoder);
decoder_command_finished(client);
} else {
decoder_seek_error(decoder);
decoder_seek_error(client);
}
} else {
decoder_seek_error(decoder);
decoder_seek_error(client);
}
}
@ -196,7 +196,7 @@ wavpack_decode(Decoder &decoder, WavpackContext *wpc, bool can_seek)
format_samples(bytes_per_sample, chunk,
samples_got * audio_format.channels);
cmd = decoder_data(decoder, nullptr, chunk,
cmd = decoder_data(client, nullptr, chunk,
samples_got * output_sample_size,
bitrate);
}
@ -323,13 +323,13 @@ wavpack_scan_file(Path path_fs,
/* This struct is needed for per-stream last_byte storage. */
struct WavpackInput {
Decoder &decoder;
DecoderClient &client;
InputStream &is;
/* Needed for push_back_byte() */
int last_byte;
constexpr WavpackInput(Decoder &_decoder, InputStream &_is)
:decoder(_decoder), is(_is), last_byte(EOF) {}
constexpr WavpackInput(DecoderClient &_client, InputStream &_is)
:client(_client), is(_is), last_byte(EOF) {}
int32_t ReadBytes(void *data, size_t bcount);
};
@ -366,7 +366,7 @@ WavpackInput::ReadBytes(void *data, size_t bcount)
/* wavpack fails if we return a partial read, so we just wait
until the buffer is full */
while (bcount > 0) {
size_t nbytes = decoder_read(&decoder, is, buf, bcount);
size_t nbytes = decoder_read(&client, is, buf, bcount);
if (nbytes == 0) {
/* EOF, error or a decoder command */
break;
@ -481,7 +481,7 @@ static WavpackStreamReader mpd_is_reader = {
};
static InputStreamPtr
wavpack_open_wvc(Decoder &decoder, const char *uri)
wavpack_open_wvc(DecoderClient &client, const char *uri)
{
/*
* As we use dc->utf8url, this function will be bad for
@ -496,7 +496,7 @@ wavpack_open_wvc(Decoder &decoder, const char *uri)
};
try {
return decoder_open_uri(decoder, uri);
return decoder_open_uri(client, uri);
} catch (const std::runtime_error &) {
return nullptr;
}
@ -506,25 +506,25 @@ wavpack_open_wvc(Decoder &decoder, const char *uri)
* Decodes a stream.
*/
static void
wavpack_streamdecode(Decoder &decoder, InputStream &is)
wavpack_streamdecode(DecoderClient &client, InputStream &is)
{
int open_flags = OPEN_NORMALIZE;
bool can_seek = is.IsSeekable();
std::unique_ptr<WavpackInput> wvc;
auto is_wvc = wavpack_open_wvc(decoder, is.GetURI());
auto is_wvc = wavpack_open_wvc(client, is.GetURI());
if (is_wvc) {
open_flags |= OPEN_WVC;
can_seek &= wvc->is.IsSeekable();
wvc.reset(new WavpackInput(decoder, *is_wvc));
wvc.reset(new WavpackInput(client, *is_wvc));
}
if (!can_seek) {
open_flags |= OPEN_STREAMING;
}
WavpackInput isp(decoder, is);
WavpackInput isp(client, is);
char error[ERRORLEN];
WavpackContext *wpc =
@ -541,14 +541,14 @@ wavpack_streamdecode(Decoder &decoder, InputStream &is)
WavpackCloseFile(wpc);
};
wavpack_decode(decoder, wpc, can_seek);
wavpack_decode(client, wpc, can_seek);
}
/*
* Decodes a file.
*/
static void
wavpack_filedecode(Decoder &decoder, Path path_fs)
wavpack_filedecode(DecoderClient &client, Path path_fs)
{
char error[ERRORLEN];
WavpackContext *wpc = WavpackOpenFileInput(path_fs.c_str(), error,
@ -563,9 +563,9 @@ wavpack_filedecode(Decoder &decoder, Path path_fs)
ReplayGainInfo rgi;
if (wavpack_replaygain(rgi, wpc))
decoder_replay_gain(decoder, &rgi);
decoder_replay_gain(client, &rgi);
wavpack_decode(decoder, wpc, true);
wavpack_decode(client, wpc, true);
WavpackCloseFile(wpc);
}

View File

@ -61,7 +61,7 @@ wildmidi_finish(void)
}
static DecoderCommand
wildmidi_output(Decoder &decoder, midi *wm)
wildmidi_output(DecoderClient &client, midi *wm)
{
#ifdef LIBWILDMIDI_VER_MAJOR
/* WildMidi 0.4 has switched from "char*" to "int8_t*" */
@ -75,11 +75,11 @@ wildmidi_output(Decoder &decoder, midi *wm)
if (length <= 0)
return DecoderCommand::STOP;
return decoder_data(decoder, nullptr, buffer, length, 0);
return decoder_data(client, nullptr, buffer, length, 0);
}
static void
wildmidi_file_decode(Decoder &decoder, Path path_fs)
wildmidi_file_decode(DecoderClient &client, Path path_fs)
{
static constexpr AudioFormat audio_format = {
WILDMIDI_SAMPLE_RATE,
@ -103,7 +103,7 @@ wildmidi_file_decode(Decoder &decoder, Path path_fs)
SongTime::FromScale<uint64_t>(info->approx_total_samples,
WILDMIDI_SAMPLE_RATE);
decoder_initialized(decoder, audio_format, true, duration);
decoder_initialized(client, audio_format, true, duration);
DecoderCommand cmd;
do {
@ -111,14 +111,14 @@ wildmidi_file_decode(Decoder &decoder, Path path_fs)
if (info == nullptr)
break;
cmd = wildmidi_output(decoder, wm);
cmd = wildmidi_output(client, wm);
if (cmd == DecoderCommand::SEEK) {
unsigned long seek_where =
decoder_seek_where_frame(decoder);
decoder_seek_where_frame(client);
WildMidi_FastSeek(wm, &seek_where);
decoder_command_finished(decoder);
decoder_command_finished(client);
cmd = DecoderCommand::NONE;
}

View File

@ -29,11 +29,12 @@
#include <stdio.h>
void
decoder_initialized(Decoder &decoder,
decoder_initialized(DecoderClient &client,
const AudioFormat audio_format,
gcc_unused bool seekable,
SignedSongTime duration)
{
auto &decoder = (FakeDecoder &)client;
struct audio_format_string af_string;
assert(!decoder.initialized);
@ -47,41 +48,42 @@ decoder_initialized(Decoder &decoder,
}
DecoderCommand
decoder_get_command(gcc_unused Decoder &decoder)
decoder_get_command(gcc_unused DecoderClient &client)
{
return DecoderCommand::NONE;
}
void
decoder_command_finished(gcc_unused Decoder &decoder)
decoder_command_finished(gcc_unused DecoderClient &client)
{
}
SongTime
decoder_seek_time(gcc_unused Decoder &decoder)
decoder_seek_time(gcc_unused DecoderClient &client)
{
return SongTime();
}
uint64_t
decoder_seek_where_frame(gcc_unused Decoder &decoder)
decoder_seek_where_frame(gcc_unused DecoderClient &client)
{
return 1;
}
void
decoder_seek_error(gcc_unused Decoder &decoder)
decoder_seek_error(gcc_unused DecoderClient &client)
{
}
InputStreamPtr
decoder_open_uri(Decoder &decoder, const char *uri)
decoder_open_uri(DecoderClient &client, const char *uri)
{
auto &decoder = (FakeDecoder &)client;
return InputStream::OpenReady(uri, decoder.mutex, decoder.cond);
}
size_t
decoder_read(gcc_unused Decoder *decoder,
decoder_read(gcc_unused DecoderClient *client,
InputStream &is,
void *buffer, size_t length)
{
@ -93,13 +95,13 @@ decoder_read(gcc_unused Decoder *decoder,
}
bool
decoder_read_full(Decoder *decoder, InputStream &is,
decoder_read_full(DecoderClient *client, InputStream &is,
void *_buffer, size_t size)
{
uint8_t *buffer = (uint8_t *)_buffer;
while (size > 0) {
size_t nbytes = decoder_read(decoder, is, buffer, size);
size_t nbytes = decoder_read(client, is, buffer, size);
if (nbytes == 0)
return false;
@ -111,11 +113,11 @@ decoder_read_full(Decoder *decoder, InputStream &is,
}
bool
decoder_skip(Decoder *decoder, InputStream &is, size_t size)
decoder_skip(DecoderClient *client, InputStream &is, size_t size)
{
while (size > 0) {
char buffer[1024];
size_t nbytes = decoder_read(decoder, is, buffer,
size_t nbytes = decoder_read(client, is, buffer,
std::min(sizeof(buffer), size));
if (nbytes == 0)
return false;
@ -127,13 +129,13 @@ decoder_skip(Decoder *decoder, InputStream &is, size_t size)
}
void
decoder_timestamp(gcc_unused Decoder &decoder,
decoder_timestamp(gcc_unused DecoderClient &client,
gcc_unused double t)
{
}
DecoderCommand
decoder_data(gcc_unused Decoder &decoder,
decoder_data(gcc_unused DecoderClient &client,
gcc_unused InputStream *is,
const void *data, size_t datalen,
gcc_unused uint16_t kbit_rate)
@ -149,7 +151,7 @@ decoder_data(gcc_unused Decoder &decoder,
}
DecoderCommand
decoder_tag(gcc_unused Decoder &decoder,
decoder_tag(gcc_unused DecoderClient &client,
gcc_unused InputStream *is,
Tag &&tag)
{
@ -162,7 +164,7 @@ decoder_tag(gcc_unused Decoder &decoder,
}
void
decoder_replay_gain(gcc_unused Decoder &decoder,
decoder_replay_gain(gcc_unused DecoderClient &client,
const ReplayGainInfo *rgi)
{
const ReplayGainTuple *tuple = &rgi->tuples[REPLAY_GAIN_ALBUM];
@ -177,7 +179,7 @@ decoder_replay_gain(gcc_unused Decoder &decoder,
}
void
decoder_mixramp(gcc_unused Decoder &decoder, gcc_unused MixRampInfo &&mix_ramp)
decoder_mixramp(gcc_unused DecoderClient &client, gcc_unused MixRampInfo &&mix_ramp)
{
fprintf(stderr, "MixRamp: start='%s' end='%s'\n",
mix_ramp.GetStart(), mix_ramp.GetEnd());

View File

@ -21,17 +21,15 @@
#define FAKE_DECODER_API_HXX
#include "check.h"
#include "decoder/Client.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
struct Decoder {
struct FakeDecoder final : DecoderClient {
Mutex mutex;
Cond cond;
bool initialized;
Decoder()
:initialized(false) {}
bool initialized = false;
};
#endif

View File

@ -42,7 +42,7 @@ try {
return EXIT_FAILURE;
}
Decoder decoder;
FakeDecoder decoder;
const char *const decoder_name = argv[1];
const char *const uri = argv[2];