decoder/Client: add virtual method Ready()
Replaces decoder_initialized().
This commit is contained in:
parent
fd77acc217
commit
66fb352cca
@ -21,11 +21,27 @@
|
||||
#define MPD_DECODER_CLIENT_HXX
|
||||
|
||||
#include "check.h"
|
||||
#include "Chrono.hxx"
|
||||
|
||||
struct AudioFormat;
|
||||
|
||||
/**
|
||||
* An interface between the decoder plugin and the MPD core.
|
||||
*/
|
||||
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
|
||||
|
@ -38,21 +38,18 @@
|
||||
#include <math.h>
|
||||
|
||||
void
|
||||
decoder_initialized(DecoderClient &client,
|
||||
const AudioFormat audio_format,
|
||||
bool seekable, SignedSongTime duration)
|
||||
Decoder::Ready(const AudioFormat audio_format,
|
||||
bool seekable, SignedSongTime duration)
|
||||
{
|
||||
auto &decoder = (Decoder &)client;
|
||||
DecoderControl &dc = decoder.dc;
|
||||
struct audio_format_string af_string;
|
||||
|
||||
assert(dc.state == DecoderState::START);
|
||||
assert(dc.pipe != nullptr);
|
||||
assert(dc.pipe->IsEmpty());
|
||||
assert(decoder.convert == nullptr);
|
||||
assert(decoder.stream_tag == nullptr);
|
||||
assert(decoder.decoder_tag == nullptr);
|
||||
assert(!decoder.seeking);
|
||||
assert(convert == nullptr);
|
||||
assert(stream_tag == nullptr);
|
||||
assert(decoder_tag == nullptr);
|
||||
assert(!seeking);
|
||||
assert(audio_format.IsDefined());
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
@ -71,13 +68,13 @@ decoder_initialized(DecoderClient &client,
|
||||
audio_format_to_string(dc.out_audio_format,
|
||||
&af_string));
|
||||
|
||||
decoder.convert = new PcmConvert();
|
||||
convert = new PcmConvert();
|
||||
|
||||
try {
|
||||
decoder.convert->Open(dc.in_audio_format,
|
||||
convert->Open(dc.in_audio_format,
|
||||
dc.out_audio_format);
|
||||
} catch (...) {
|
||||
decoder.error = std::current_exception();
|
||||
error = std::current_exception();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
// IWYU pragma: begin_exports
|
||||
|
||||
#include "check.h"
|
||||
#include "Client.hxx"
|
||||
#include "input/Ptr.hxx"
|
||||
#include "DecoderCommand.hxx"
|
||||
#include "DecoderPlugin.hxx"
|
||||
@ -53,22 +54,6 @@ class DecoderClient;
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -116,6 +116,10 @@ struct Decoder final : DecoderClient {
|
||||
* Caller must not lock the #DecoderControl object.
|
||||
*/
|
||||
void FlushChunk();
|
||||
|
||||
/* virtual methods from DecoderClient */
|
||||
void Ready(AudioFormat audio_format,
|
||||
bool seekable, SignedSongTime duration) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -61,8 +61,8 @@ adplug_file_decode(DecoderClient &client, Path path_fs)
|
||||
const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
decoder_initialized(client, audio_format, false,
|
||||
SongTime::FromMS(player->songlength()));
|
||||
client.Ready(audio_format, false,
|
||||
SongTime::FromMS(player->songlength()));
|
||||
|
||||
DecoderCommand cmd;
|
||||
|
||||
|
@ -210,7 +210,7 @@ audiofile_stream_decode(DecoderClient &client, InputStream &is)
|
||||
const unsigned frame_size = (unsigned)
|
||||
afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, true);
|
||||
|
||||
decoder_initialized(client, audio_format, true, total_time);
|
||||
client.Ready(audio_format, true, total_time);
|
||||
|
||||
DecoderCommand cmd;
|
||||
do {
|
||||
|
@ -437,7 +437,7 @@ dsdiff_stream_decode(DecoderClient &client, InputStream &is)
|
||||
audio_format.sample_rate);
|
||||
|
||||
/* 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"
|
||||
chunk from a DFF file */
|
||||
|
@ -316,7 +316,7 @@ dsf_stream_decode(DecoderClient &client, InputStream &is)
|
||||
audio_format.sample_rate);
|
||||
|
||||
/* 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,
|
||||
metadata.sample_rate,
|
||||
|
@ -339,7 +339,7 @@ faad_stream_decode(DecoderClient &client, InputStream &is,
|
||||
|
||||
/* initialize the MPD core */
|
||||
|
||||
decoder_initialized(client, audio_format, false, total_time);
|
||||
client.Ready(audio_format, false, total_time);
|
||||
|
||||
/* the decoder loop */
|
||||
|
||||
|
@ -689,8 +689,7 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
|
||||
const SignedSongTime total_time =
|
||||
FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base);
|
||||
|
||||
decoder_initialized(client, audio_format,
|
||||
input.IsSeekable(), total_time);
|
||||
client.Ready(audio_format, input.IsSeekable(), total_time);
|
||||
|
||||
FfmpegParseMetaData(client, format_context, audio_stream);
|
||||
|
||||
|
@ -52,9 +52,9 @@ FlacDecoder::Initialize(unsigned sample_rate, unsigned bits_per_sample,
|
||||
audio_format.sample_rate)
|
||||
: SignedSongTime::Negative();
|
||||
|
||||
decoder_initialized(*GetClient(), audio_format,
|
||||
GetInputStream().IsSeekable(),
|
||||
duration);
|
||||
GetClient()->Ready(audio_format,
|
||||
GetInputStream().IsSeekable(),
|
||||
duration);
|
||||
|
||||
initialized = true;
|
||||
return true;
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
struct FlacDecoder : public FlacInput {
|
||||
/**
|
||||
* Has decoder_initialized() been called yet?
|
||||
* Has DecoderClient::Ready() been called yet?
|
||||
*/
|
||||
bool initialized = false;
|
||||
|
||||
@ -55,7 +55,7 @@ struct FlacDecoder : public FlacInput {
|
||||
:FlacInput(_input_stream, &_client) {}
|
||||
|
||||
/**
|
||||
* Wrapper for decoder_initialized().
|
||||
* Wrapper for DecoderClient::Ready().
|
||||
*/
|
||||
bool Initialize(unsigned sample_rate, unsigned bits_per_sample,
|
||||
unsigned channels, FLAC__uint64 total_frames);
|
||||
@ -77,7 +77,7 @@ private:
|
||||
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,
|
||||
* where the server sends us only a part of the file, without
|
||||
* providing the STREAMINFO block from the beginning of the file
|
||||
|
@ -160,8 +160,7 @@ fluidsynth_file_decode(DecoderClient &client, Path path_fs)
|
||||
MPD core */
|
||||
|
||||
const AudioFormat audio_format(sample_rate, SampleFormat::S16, 2);
|
||||
decoder_initialized(client, audio_format, false,
|
||||
SignedSongTime::Negative());
|
||||
client.Ready(audio_format, false, SignedSongTime::Negative());
|
||||
|
||||
DecoderCommand cmd;
|
||||
while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) {
|
||||
|
@ -171,7 +171,7 @@ gme_file_decode(DecoderClient &client, Path path_fs)
|
||||
SampleFormat::S16,
|
||||
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);
|
||||
if (gme_err != nullptr)
|
||||
|
@ -1050,12 +1050,11 @@ mp3_decode(DecoderClient &client, InputStream &input_stream)
|
||||
|
||||
data.AllocateBuffers();
|
||||
|
||||
decoder_initialized(client,
|
||||
CheckAudioFormat(data.frame.header.samplerate,
|
||||
SampleFormat::S24_P32,
|
||||
MAD_NCHANNELS(&data.frame.header)),
|
||||
input_stream.IsSeekable(),
|
||||
data.total_time);
|
||||
client.Ready(CheckAudioFormat(data.frame.header.samplerate,
|
||||
SampleFormat::S24_P32,
|
||||
MAD_NCHANNELS(&data.frame.header)),
|
||||
input_stream.IsSeekable(),
|
||||
data.total_time);
|
||||
|
||||
if (tag != nullptr) {
|
||||
decoder_tag(client, input_stream, std::move(*tag));
|
||||
|
@ -170,8 +170,7 @@ mikmod_decoder_file_decode(DecoderClient &client, Path path_fs)
|
||||
const AudioFormat audio_format(mikmod_sample_rate, SampleFormat::S16, 2);
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
decoder_initialized(client, audio_format, false,
|
||||
SignedSongTime::Negative());
|
||||
client.Ready(audio_format, false, SignedSongTime::Negative());
|
||||
|
||||
Player_Start(handle);
|
||||
|
||||
|
@ -151,9 +151,8 @@ mod_decode(DecoderClient &client, InputStream &is)
|
||||
static constexpr AudioFormat audio_format(44100, SampleFormat::S16, 2);
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
decoder_initialized(client, audio_format,
|
||||
is.IsSeekable(),
|
||||
SongTime::FromMS(ModPlug_GetLength(f)));
|
||||
client.Ready(audio_format, is.IsSeekable(),
|
||||
SongTime::FromMS(ModPlug_GetLength(f)));
|
||||
|
||||
DecoderCommand cmd;
|
||||
do {
|
||||
|
@ -174,9 +174,8 @@ mpcdec_decode(DecoderClient &client, InputStream &is)
|
||||
|
||||
decoder_replay_gain(client, &rgi);
|
||||
|
||||
decoder_initialized(client, audio_format,
|
||||
is.IsSeekable(),
|
||||
SongTime::FromS(mpc_streaminfo_get_length(&info)));
|
||||
client.Ready(audio_format, is.IsSeekable(),
|
||||
SongTime::FromS(mpc_streaminfo_get_length(&info)));
|
||||
|
||||
DecoderCommand cmd = DecoderCommand::NONE;
|
||||
do {
|
||||
|
@ -210,7 +210,7 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
|
||||
SongTime::FromScale<uint64_t>(num_samples,
|
||||
audio_format.sample_rate);
|
||||
|
||||
decoder_initialized(client, audio_format, true, duration);
|
||||
client.Ready(audio_format, true, duration);
|
||||
|
||||
struct mpg123_frameinfo info;
|
||||
if (mpg123_info(handle, &info) != MPG123_OK) {
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
~MPDOpusDecoder();
|
||||
|
||||
/**
|
||||
* Has decoder_initialized() been called yet?
|
||||
* Has DecoderClient::Ready() been called yet?
|
||||
*/
|
||||
bool IsInitialized() const {
|
||||
return previous_channels != 0;
|
||||
@ -175,8 +175,7 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet)
|
||||
previous_channels = channels;
|
||||
const AudioFormat audio_format(opus_sample_rate,
|
||||
SampleFormat::S16, channels);
|
||||
decoder_initialized(client, audio_format,
|
||||
eos_granulepos > 0, duration);
|
||||
client.Ready(audio_format, eos_granulepos > 0, duration);
|
||||
frame_size = audio_format.GetFrameSize();
|
||||
|
||||
output_buffer = new opus_int16[opus_output_buffer_frames
|
||||
|
@ -143,8 +143,7 @@ pcm_stream_decode(DecoderClient &client, InputStream &is)
|
||||
audio_format.sample_rate)
|
||||
: SignedSongTime::Negative();
|
||||
|
||||
decoder_initialized(client, audio_format,
|
||||
is.IsSeekable(), total_time);
|
||||
client.Ready(audio_format, is.IsSeekable(), total_time);
|
||||
|
||||
StaticFifoBuffer<uint8_t, 4096> buffer;
|
||||
|
||||
|
@ -337,7 +337,7 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
|
||||
const AudioFormat audio_format(48000, SampleFormat::S16, channels);
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
decoder_initialized(client, audio_format, true, duration);
|
||||
client.Ready(audio_format, true, duration);
|
||||
|
||||
/* .. and play */
|
||||
|
||||
|
@ -205,8 +205,7 @@ sndfile_stream_decode(DecoderClient &client, InputStream &is)
|
||||
sndfile_sample_format(info),
|
||||
info.channels);
|
||||
|
||||
decoder_initialized(client, audio_format, info.seekable,
|
||||
sndfile_duration(info));
|
||||
client.Ready(audio_format, info.seekable, sndfile_duration(info));
|
||||
|
||||
char buffer[16384];
|
||||
|
||||
|
@ -175,8 +175,7 @@ VorbisDecoder::SubmitInit()
|
||||
audio_format.sample_rate)
|
||||
: SignedSongTime::Negative();
|
||||
|
||||
decoder_initialized(client, audio_format,
|
||||
eos_granulepos > 0, duration);
|
||||
client.Ready(audio_format, eos_granulepos > 0, duration);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -168,7 +168,7 @@ wavpack_decode(DecoderClient &client, WavpackContext *wpc, bool can_seek)
|
||||
const uint32_t samples_requested = ARRAY_SIZE(chunk) /
|
||||
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);
|
||||
while (cmd != DecoderCommand::STOP) {
|
||||
|
@ -103,7 +103,7 @@ wildmidi_file_decode(DecoderClient &client, Path path_fs)
|
||||
SongTime::FromScale<uint64_t>(info->approx_total_samples,
|
||||
WILDMIDI_SAMPLE_RATE);
|
||||
|
||||
decoder_initialized(client, audio_format, true, duration);
|
||||
client.Ready(audio_format, true, duration);
|
||||
|
||||
DecoderCommand cmd;
|
||||
do {
|
||||
|
@ -29,22 +29,20 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
decoder_initialized(DecoderClient &client,
|
||||
const AudioFormat audio_format,
|
||||
gcc_unused bool seekable,
|
||||
SignedSongTime duration)
|
||||
FakeDecoder::Ready(const AudioFormat audio_format,
|
||||
gcc_unused bool seekable,
|
||||
SignedSongTime duration)
|
||||
{
|
||||
auto &decoder = (FakeDecoder &)client;
|
||||
struct audio_format_string af_string;
|
||||
|
||||
assert(!decoder.initialized);
|
||||
assert(!initialized);
|
||||
assert(audio_format.IsValid());
|
||||
|
||||
fprintf(stderr, "audio_format=%s duration=%f\n",
|
||||
audio_format_to_string(audio_format, &af_string),
|
||||
duration.ToDoubleS());
|
||||
|
||||
decoder.initialized = true;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
DecoderCommand
|
||||
|
@ -30,6 +30,10 @@ struct FakeDecoder final : DecoderClient {
|
||||
Cond cond;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
/* virtual methods from DecoderClient */
|
||||
void Ready(AudioFormat audio_format,
|
||||
bool seekable, SignedSongTime duration) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user