decoder/Client: add virtual method Ready()

Replaces decoder_initialized().
This commit is contained in:
Max Kellermann 2016-11-18 07:59:01 +01:00
parent fd77acc217
commit 66fb352cca
28 changed files with 73 additions and 79 deletions

View File

@ -21,11 +21,27 @@
#define MPD_DECODER_CLIENT_HXX #define MPD_DECODER_CLIENT_HXX
#include "check.h" #include "check.h"
#include "Chrono.hxx"
struct AudioFormat;
/** /**
* An interface between the decoder plugin and the MPD core. * An interface between the decoder plugin and the MPD core.
*/ */
class DecoderClient { class DecoderClient {
public:
/**
* Notify the client that it has finished initialization and
* that it has read the song's meta data.
*
* @param audio_format the audio format which is going to be
* sent to SubmitData()
* @param seekable true if the song is seekable
* @param duration the total duration of this song; negative if
* unknown
*/
virtual void Ready(AudioFormat audio_format,
bool seekable, SignedSongTime duration) = 0;
}; };
#endif #endif

View File

@ -38,21 +38,18 @@
#include <math.h> #include <math.h>
void void
decoder_initialized(DecoderClient &client, Decoder::Ready(const AudioFormat audio_format,
const AudioFormat audio_format, bool seekable, SignedSongTime duration)
bool seekable, SignedSongTime duration)
{ {
auto &decoder = (Decoder &)client;
DecoderControl &dc = decoder.dc;
struct audio_format_string af_string; struct audio_format_string af_string;
assert(dc.state == DecoderState::START); assert(dc.state == DecoderState::START);
assert(dc.pipe != nullptr); assert(dc.pipe != nullptr);
assert(dc.pipe->IsEmpty()); assert(dc.pipe->IsEmpty());
assert(decoder.convert == nullptr); assert(convert == nullptr);
assert(decoder.stream_tag == nullptr); assert(stream_tag == nullptr);
assert(decoder.decoder_tag == nullptr); assert(decoder_tag == nullptr);
assert(!decoder.seeking); assert(!seeking);
assert(audio_format.IsDefined()); assert(audio_format.IsDefined());
assert(audio_format.IsValid()); assert(audio_format.IsValid());
@ -71,13 +68,13 @@ decoder_initialized(DecoderClient &client,
audio_format_to_string(dc.out_audio_format, audio_format_to_string(dc.out_audio_format,
&af_string)); &af_string));
decoder.convert = new PcmConvert(); convert = new PcmConvert();
try { try {
decoder.convert->Open(dc.in_audio_format, convert->Open(dc.in_audio_format,
dc.out_audio_format); dc.out_audio_format);
} catch (...) { } catch (...) {
decoder.error = std::current_exception(); error = std::current_exception();
} }
} }

View File

@ -30,6 +30,7 @@
// IWYU pragma: begin_exports // IWYU pragma: begin_exports
#include "check.h" #include "check.h"
#include "Client.hxx"
#include "input/Ptr.hxx" #include "input/Ptr.hxx"
#include "DecoderCommand.hxx" #include "DecoderCommand.hxx"
#include "DecoderPlugin.hxx" #include "DecoderPlugin.hxx"
@ -53,22 +54,6 @@ class DecoderClient;
*/ */
class StopDecoder {}; class StopDecoder {};
/**
* Notify the player thread that it has finished initialization and
* that it has read the song's meta data.
*
* @param decoder the decoder object
* @param audio_format the audio format which is going to be sent to
* decoder_data()
* @param seekable true if the song is seekable
* @param duration the total duration of this song; negative if
* unknown
*/
void
decoder_initialized(DecoderClient &decoder,
AudioFormat audio_format,
bool seekable, SignedSongTime duration);
/** /**
* Determines the pending decoder command. * Determines the pending decoder command.
* *

View File

@ -116,6 +116,10 @@ struct Decoder final : DecoderClient {
* Caller must not lock the #DecoderControl object. * Caller must not lock the #DecoderControl object.
*/ */
void FlushChunk(); void FlushChunk();
/* virtual methods from DecoderClient */
void Ready(AudioFormat audio_format,
bool seekable, SignedSongTime duration) override;
}; };
#endif #endif

View File

@ -61,8 +61,8 @@ adplug_file_decode(DecoderClient &client, Path path_fs)
const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2); const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
assert(audio_format.IsValid()); assert(audio_format.IsValid());
decoder_initialized(client, audio_format, false, client.Ready(audio_format, false,
SongTime::FromMS(player->songlength())); SongTime::FromMS(player->songlength()));
DecoderCommand cmd; DecoderCommand cmd;

View File

@ -210,7 +210,7 @@ audiofile_stream_decode(DecoderClient &client, InputStream &is)
const unsigned frame_size = (unsigned) const unsigned frame_size = (unsigned)
afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, true); afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, true);
decoder_initialized(client, audio_format, true, total_time); client.Ready(audio_format, true, total_time);
DecoderCommand cmd; DecoderCommand cmd;
do { do {

View File

@ -437,7 +437,7 @@ dsdiff_stream_decode(DecoderClient &client, InputStream &is)
audio_format.sample_rate); audio_format.sample_rate);
/* success: file was recognized */ /* success: file was recognized */
decoder_initialized(client, audio_format, is.IsSeekable(), songtime); client.Ready(audio_format, is.IsSeekable(), songtime);
/* every iteration of the following loop decodes one "DSD" /* every iteration of the following loop decodes one "DSD"
chunk from a DFF file */ chunk from a DFF file */

View File

@ -316,7 +316,7 @@ dsf_stream_decode(DecoderClient &client, InputStream &is)
audio_format.sample_rate); audio_format.sample_rate);
/* success: file was recognized */ /* success: file was recognized */
decoder_initialized(client, audio_format, is.IsSeekable(), songtime); client.Ready(audio_format, is.IsSeekable(), songtime);
dsf_decode_chunk(client, is, metadata.channels, dsf_decode_chunk(client, is, metadata.channels,
metadata.sample_rate, metadata.sample_rate,

View File

@ -339,7 +339,7 @@ faad_stream_decode(DecoderClient &client, InputStream &is,
/* initialize the MPD core */ /* initialize the MPD core */
decoder_initialized(client, audio_format, false, total_time); client.Ready(audio_format, false, total_time);
/* the decoder loop */ /* the decoder loop */

View File

@ -689,8 +689,7 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
const SignedSongTime total_time = const SignedSongTime total_time =
FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base); FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base);
decoder_initialized(client, audio_format, client.Ready(audio_format, input.IsSeekable(), total_time);
input.IsSeekable(), total_time);
FfmpegParseMetaData(client, format_context, audio_stream); FfmpegParseMetaData(client, format_context, audio_stream);

View File

@ -52,9 +52,9 @@ FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample,
audio_format.sample_rate) audio_format.sample_rate)
: SignedSongTime::Negative(); : SignedSongTime::Negative();
decoder_initialized(*GetClient(), audio_format, GetClient()->Ready(audio_format,
GetInputStream().IsSeekable(), GetInputStream().IsSeekable(),
duration); duration);
initialized = true; initialized = true;
return true; return true;

View File

@ -32,7 +32,7 @@
struct FlacDecoder : public FlacInput { struct FlacDecoder : public FlacInput {
/** /**
* Has decoder_initialized() been called yet? * Has DecoderClient::Ready() been called yet?
*/ */
bool initialized = false; bool initialized = false;
@ -55,7 +55,7 @@ struct FlacDecoder : public FlacInput {
:FlacInput(_input_stream, &_client) {} :FlacInput(_input_stream, &_client) {}
/** /**
* Wrapper for decoder_initialized(). * Wrapper for DecoderClient::Ready().
*/ */
bool Initialize(unsigned sample_rate, unsigned bits_per_sample, bool Initialize(unsigned sample_rate, unsigned bits_per_sample,
unsigned channels, FLAC__uint64 total_frames); unsigned channels, FLAC__uint64 total_frames);
@ -77,7 +77,7 @@ private:
void OnVorbisComment(const FLAC__StreamMetadata_VorbisComment &vc); void OnVorbisComment(const FLAC__StreamMetadata_VorbisComment &vc);
/** /**
* This function attempts to call decoder_initialized() in case there * This function attempts to call DecoderClient::Ready() in case there
* was no STREAMINFO block. This is allowed for nonseekable streams, * was no STREAMINFO block. This is allowed for nonseekable streams,
* where the server sends us only a part of the file, without * where the server sends us only a part of the file, without
* providing the STREAMINFO block from the beginning of the file * providing the STREAMINFO block from the beginning of the file

View File

@ -160,8 +160,7 @@ fluidsynth_file_decode(DecoderClient &client, Path path_fs)
MPD core */ MPD core */
const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2); const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
decoder_initialized(client, audio_format, false, client.Ready(audio_format, false, SignedSongTime::Negative());
SignedSongTime::Negative());
DecoderCommand cmd; DecoderCommand cmd;
while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) { while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) {

View File

@ -171,7 +171,7 @@ gme_file_decode(DecoderClient &client, Path path_fs)
SampleFormat::S16, SampleFormat::S16,
GME_CHANNELS); GME_CHANNELS);
decoder_initialized(client, audio_format, true, song_len); client.Ready(audio_format, true, song_len);
gme_err = gme_start_track(emu, container.track); gme_err = gme_start_track(emu, container.track);
if (gme_err != nullptr) if (gme_err != nullptr)

View File

@ -1050,12 +1050,11 @@ mp3_decode(DecoderClient &client, InputStream &input_stream)
data.AllocateBuffers(); data.AllocateBuffers();
decoder_initialized(client, client.Ready(CheckAudioFormat(data.frame.header.samplerate,
CheckAudioFormat(data.frame.header.samplerate, SampleFormat::S24_P32,
SampleFormat::S24_P32, MAD_NCHANNELS(&data.frame.header)),
MAD_NCHANNELS(&data.frame.header)), input_stream.IsSeekable(),
input_stream.IsSeekable(), data.total_time);
data.total_time);
if (tag != nullptr) { if (tag != nullptr) {
decoder_tag(client, input_stream, std::move(*tag)); decoder_tag(client, input_stream, std::move(*tag));

View File

@ -170,8 +170,7 @@ mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
const AudioFormat audio_format(mikmod_sample_rate, SampleFormat::S16, 2); const AudioFormat audio_format(mikmod_sample_rate, SampleFormat::S16, 2);
assert(audio_format.IsValid()); assert(audio_format.IsValid());
decoder_initialized(client, audio_format, false, client.Ready(audio_format, false, SignedSongTime::Negative());
SignedSongTime::Negative());
Player_Start(handle); Player_Start(handle);

View File

@ -151,9 +151,8 @@ mod_decode(DecoderClient &client, InputStream &is)
static constexpr AudioFormat audio_format(44100, SampleFormat::S16, 2); static constexpr AudioFormat audio_format(44100, SampleFormat::S16, 2);
assert(audio_format.IsValid()); assert(audio_format.IsValid());
decoder_initialized(client, audio_format, client.Ready(audio_format, is.IsSeekable(),
is.IsSeekable(), SongTime::FromMS(ModPlug_GetLength(f)));
SongTime::FromMS(ModPlug_GetLength(f)));
DecoderCommand cmd; DecoderCommand cmd;
do { do {

View File

@ -174,9 +174,8 @@ mpcdec_decode(DecoderClient &client, InputStream &is)
decoder_replay_gain(client, &rgi); decoder_replay_gain(client, &rgi);
decoder_initialized(client, audio_format, client.Ready(audio_format, is.IsSeekable(),
is.IsSeekable(), SongTime::FromS(mpc_streaminfo_get_length(&info)));
SongTime::FromS(mpc_streaminfo_get_length(&info)));
DecoderCommand cmd = DecoderCommand::NONE; DecoderCommand cmd = DecoderCommand::NONE;
do { do {

View File

@ -210,7 +210,7 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
SongTime::FromScale<uint64_t>(num_samples, SongTime::FromScale<uint64_t>(num_samples,
audio_format.sample_rate); audio_format.sample_rate);
decoder_initialized(client, audio_format, true, duration); client.Ready(audio_format, true, duration);
struct mpg123_frameinfo info; struct mpg123_frameinfo info;
if (mpg123_info(handle, &info) != MPG123_OK) { if (mpg123_info(handle, &info) != MPG123_OK) {

View File

@ -93,7 +93,7 @@ public:
~MPDOpusDecoder(); ~MPDOpusDecoder();
/** /**
* Has decoder_initialized() been called yet? * Has DecoderClient::Ready() been called yet?
*/ */
bool IsInitialized() const { bool IsInitialized() const {
return previous_channels != 0; return previous_channels != 0;
@ -175,8 +175,7 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet)
previous_channels = channels; previous_channels = channels;
const AudioFormat audio_format(opus_sample_rate, const AudioFormat audio_format(opus_sample_rate,
SampleFormat::S16, channels); SampleFormat::S16, channels);
decoder_initialized(client, audio_format, client.Ready(audio_format, eos_granulepos > 0, duration);
eos_granulepos > 0, duration);
frame_size = audio_format.GetFrameSize(); frame_size = audio_format.GetFrameSize();
output_buffer = new opus_int16[opus_output_buffer_frames output_buffer = new opus_int16[opus_output_buffer_frames

View File

@ -143,8 +143,7 @@ pcm_stream_decode(DecoderClient &client, InputStream &is)
audio_format.sample_rate) audio_format.sample_rate)
: SignedSongTime::Negative(); : SignedSongTime::Negative();
decoder_initialized(client, audio_format, client.Ready(audio_format, is.IsSeekable(), total_time);
is.IsSeekable(), total_time);
StaticFifoBuffer<uint8_t, 4096> buffer; StaticFifoBuffer<uint8_t, 4096> buffer;

View File

@ -337,7 +337,7 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
const AudioFormat audio_format(48000, SampleFormat::S16, channels); const AudioFormat audio_format(48000, SampleFormat::S16, channels);
assert(audio_format.IsValid()); assert(audio_format.IsValid());
decoder_initialized(client, audio_format, true, duration); client.Ready(audio_format, true, duration);
/* .. and play */ /* .. and play */

View File

@ -205,8 +205,7 @@ sndfile_stream_decode(DecoderClient &client, InputStream &is)
sndfile_sample_format(info), sndfile_sample_format(info),
info.channels); info.channels);
decoder_initialized(client, audio_format, info.seekable, client.Ready(audio_format, info.seekable, sndfile_duration(info));
sndfile_duration(info));
char buffer[16384]; char buffer[16384];

View File

@ -175,8 +175,7 @@ VorbisDecoder::SubmitInit()
audio_format.sample_rate) audio_format.sample_rate)
: SignedSongTime::Negative(); : SignedSongTime::Negative();
decoder_initialized(client, audio_format, client.Ready(audio_format, eos_granulepos > 0, duration);
eos_granulepos > 0, duration);
} }
bool bool

View File

@ -168,7 +168,7 @@ wavpack_decode(DecoderClient &client, WavpackContext *wpc, bool can_seek)
const uint32_t samples_requested = ARRAY_SIZE(chunk) / const uint32_t samples_requested = ARRAY_SIZE(chunk) /
audio_format.channels; audio_format.channels;
decoder_initialized(client, audio_format, can_seek, total_time); client.Ready(audio_format, can_seek, total_time);
DecoderCommand cmd = decoder_get_command(client); DecoderCommand cmd = decoder_get_command(client);
while (cmd != DecoderCommand::STOP) { while (cmd != DecoderCommand::STOP) {

View File

@ -103,7 +103,7 @@ wildmidi_file_decode(DecoderClient &client, Path path_fs)
SongTime::FromScale<uint64_t>(info->approx_total_samples, SongTime::FromScale<uint64_t>(info->approx_total_samples,
WILDMIDI_SAMPLE_RATE); WILDMIDI_SAMPLE_RATE);
decoder_initialized(client, audio_format, true, duration); client.Ready(audio_format, true, duration);
DecoderCommand cmd; DecoderCommand cmd;
do { do {

View File

@ -29,22 +29,20 @@
#include <stdio.h> #include <stdio.h>
void void
decoder_initialized(DecoderClient &client, FakeDecoder::Ready(const AudioFormat audio_format,
const AudioFormat audio_format, gcc_unused bool seekable,
gcc_unused bool seekable, SignedSongTime duration)
SignedSongTime duration)
{ {
auto &decoder = (FakeDecoder &)client;
struct audio_format_string af_string; struct audio_format_string af_string;
assert(!decoder.initialized); assert(!initialized);
assert(audio_format.IsValid()); assert(audio_format.IsValid());
fprintf(stderr, "audio_format=%s duration=%f\n", fprintf(stderr, "audio_format=%s duration=%f\n",
audio_format_to_string(audio_format, &af_string), audio_format_to_string(audio_format, &af_string),
duration.ToDoubleS()); duration.ToDoubleS());
decoder.initialized = true; initialized = true;
} }
DecoderCommand DecoderCommand

View File

@ -30,6 +30,10 @@ struct FakeDecoder final : DecoderClient {
Cond cond; Cond cond;
bool initialized = false; bool initialized = false;
/* virtual methods from DecoderClient */
void Ready(AudioFormat audio_format,
bool seekable, SignedSongTime duration) override;
}; };
#endif #endif