From fd77acc217340aeee3dc80173b6000815ebb709f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 18 Nov 2016 07:13:35 +0100 Subject: [PATCH] decoder/Client: new interface which wraps struct Decoder Prepare for a Decoder API redesign based on an abstract class with virtual methods. --- Makefile.am | 1 + src/decoder/Client.hxx | 31 +++++++ src/decoder/DecoderAPI.cxx | 67 ++++++++++----- src/decoder/DecoderAPI.hxx | 38 +++++---- src/decoder/DecoderBuffer.cxx | 4 +- src/decoder/DecoderBuffer.hxx | 10 +-- src/decoder/DecoderInternal.hxx | 3 +- src/decoder/DecoderPlugin.hxx | 19 ++--- src/decoder/Reader.cxx | 2 +- src/decoder/Reader.hxx | 12 +-- src/decoder/plugins/AdPlugDecoderPlugin.cxx | 6 +- .../plugins/AudiofileDecoderPlugin.cxx | 16 ++-- src/decoder/plugins/DsdLib.cxx | 8 +- src/decoder/plugins/DsdLib.hxx | 6 +- src/decoder/plugins/DsdiffDecoderPlugin.cxx | 82 +++++++++---------- src/decoder/plugins/DsfDecoderPlugin.cxx | 34 ++++---- src/decoder/plugins/FaadDecoderPlugin.cxx | 12 +-- src/decoder/plugins/FfmpegDecoderPlugin.cxx | 64 +++++++-------- src/decoder/plugins/FfmpegIo.cxx | 2 +- src/decoder/plugins/FfmpegIo.hxx | 8 +- src/decoder/plugins/FlacCommon.cxx | 8 +- src/decoder/plugins/FlacCommon.hxx | 4 +- src/decoder/plugins/FlacDecoderPlugin.cxx | 28 +++---- src/decoder/plugins/FlacInput.cxx | 16 ++-- src/decoder/plugins/FlacInput.hxx | 12 +-- .../plugins/FluidsynthDecoderPlugin.cxx | 6 +- src/decoder/plugins/GmeDecoderPlugin.cxx | 12 +-- src/decoder/plugins/MadDecoderPlugin.cxx | 48 +++++------ src/decoder/plugins/MikmodDecoderPlugin.cxx | 6 +- src/decoder/plugins/ModplugDecoderPlugin.cxx | 20 ++--- src/decoder/plugins/MpcdecDecoderPlugin.cxx | 26 +++--- src/decoder/plugins/Mpg123DecoderPlugin.cxx | 36 ++++---- src/decoder/plugins/OggCodec.cxx | 4 +- src/decoder/plugins/OggCodec.hxx | 4 +- src/decoder/plugins/OggDecoder.cxx | 2 +- src/decoder/plugins/OggDecoder.hxx | 4 +- src/decoder/plugins/OpusDecoderPlugin.cxx | 24 +++--- src/decoder/plugins/PcmDecoderPlugin.cxx | 20 ++--- src/decoder/plugins/SidplayDecoderPlugin.cxx | 12 +-- src/decoder/plugins/SndfileDecoderPlugin.cxx | 18 ++-- src/decoder/plugins/VorbisDecoderPlugin.cxx | 28 +++---- src/decoder/plugins/WavpackDecoderPlugin.cxx | 44 +++++----- src/decoder/plugins/WildmidiDecoderPlugin.cxx | 14 ++-- test/FakeDecoderAPI.cxx | 36 ++++---- test/FakeDecoderAPI.hxx | 8 +- test/run_decoder.cxx | 2 +- 46 files changed, 460 insertions(+), 407 deletions(-) create mode 100644 src/decoder/Client.hxx diff --git a/Makefile.am b/Makefile.am index eee560d86..d3a3b0a31 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/src/decoder/Client.hxx b/src/decoder/Client.hxx new file mode 100644 index 000000000..e8d3ea641 --- /dev/null +++ b/src/decoder/Client.hxx @@ -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 diff --git a/src/decoder/DecoderAPI.cxx b/src/decoder/DecoderAPI.cxx index a80ac85be..6c4658dfb 100644 --- a/src/decoder/DecoderAPI.cxx +++ b/src/decoder/DecoderAPI.cxx @@ -38,10 +38,11 @@ #include 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(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)); diff --git a/src/decoder/DecoderAPI.hxx b/src/decoder/DecoderAPI.hxx index 16b63d8e5..0393a9591 100644 --- a/src/decoder/DecoderAPI.hxx +++ b/src/decoder/DecoderAPI.hxx @@ -44,6 +44,8 @@ #include +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 diff --git a/src/decoder/DecoderBuffer.cxx b/src/decoder/DecoderBuffer.cxx index 575e0c92a..4d57e4040 100644 --- a/src/decoder/DecoderBuffer.cxx +++ b/src/decoder/DecoderBuffer.cxx @@ -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); } diff --git a/src/decoder/DecoderBuffer.hxx b/src/decoder/DecoderBuffer.hxx index 1ff4f8387..b836c5469 100644 --- a/src/decoder/DecoderBuffer.hxx +++ b/src/decoder/DecoderBuffer.hxx @@ -27,7 +27,7 @@ #include #include -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 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; diff --git a/src/decoder/DecoderInternal.hxx b/src/decoder/DecoderInternal.hxx index ccf9885f4..91ea7928a 100644 --- a/src/decoder/DecoderInternal.hxx +++ b/src/decoder/DecoderInternal.hxx @@ -20,6 +20,7 @@ #ifndef MPD_DECODER_INTERNAL_HXX #define MPD_DECODER_INTERNAL_HXX +#include "Client.hxx" #include "ReplayGainInfo.hxx" #include @@ -29,7 +30,7 @@ struct MusicChunk; struct DecoderControl; struct Tag; -struct Decoder { +struct Decoder final : DecoderClient { DecoderControl &dc; /** diff --git a/src/decoder/DecoderPlugin.hxx b/src/decoder/DecoderPlugin.hxx index 1c3042a18..c83944b5f 100644 --- a/src/decoder/DecoderPlugin.hxx +++ b/src/decoder/DecoderPlugin.hxx @@ -27,12 +27,7 @@ class InputStream; struct TagHandler; class Path; template 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 - 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); } /** diff --git a/src/decoder/Reader.cxx b/src/decoder/Reader.cxx index c7cfb4607..0574754d7 100644 --- a/src/decoder/Reader.cxx +++ b/src/decoder/Reader.cxx @@ -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); } diff --git a/src/decoder/Reader.hxx b/src/decoder/Reader.hxx index 4cc16d446..cbcf430a4 100644 --- a/src/decoder/Reader.hxx +++ b/src/decoder/Reader.hxx @@ -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() { diff --git a/src/decoder/plugins/AdPlugDecoderPlugin.cxx b/src/decoder/plugins/AdPlugDecoderPlugin.cxx index 703fded55..a94c8530f 100644 --- a/src/decoder/plugins/AdPlugDecoderPlugin.cxx +++ b/src/decoder/plugins/AdPlugDecoderPlugin.cxx @@ -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); diff --git a/src/decoder/plugins/AudiofileDecoderPlugin.cxx b/src/decoder/plugins/AudiofileDecoderPlugin.cxx index 62a81b071..b87ba83b5 100644 --- a/src/decoder/plugins/AudiofileDecoderPlugin.cxx +++ b/src/decoder/plugins/AudiofileDecoderPlugin.cxx @@ -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); diff --git a/src/decoder/plugins/DsdLib.cxx b/src/decoder/plugins/DsdLib.cxx index 44ea7fc4b..9bb023386 100644 --- a/src/decoder/plugins/DsdLib.cxx +++ b/src/decoder/plugins/DsdLib.cxx @@ -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 diff --git a/src/decoder/plugins/DsdLib.hxx b/src/decoder/plugins/DsdLib.hxx index 1b72ca7fd..bcb19c7ae 100644 --- a/src/decoder/plugins/DsdLib.hxx +++ b/src/decoder/plugins/DsdLib.hxx @@ -26,8 +26,8 @@ #include -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); /** diff --git a/src/decoder/plugins/DsdiffDecoderPlugin.cxx b/src/decoder/plugins/DsdiffDecoderPlugin.cxx index 78fda3a12..7bb7f384f 100644 --- a/src/decoder/plugins/DsdiffDecoderPlugin.cxx +++ b/src/decoder/plugins/DsdiffDecoderPlugin.cxx @@ -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); diff --git a/src/decoder/plugins/DsfDecoderPlugin.cxx b/src/decoder/plugins/DsfDecoderPlugin.cxx index 8dce68a3a..11877fdba 100644 --- a/src/decoder/plugins/DsfDecoderPlugin.cxx +++ b/src/decoder/plugins/DsfDecoderPlugin.cxx @@ -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); diff --git a/src/decoder/plugins/FaadDecoderPlugin.cxx b/src/decoder/plugins/FaadDecoderPlugin.cxx index b16d8bc39..d9e24c1b5 100644 --- a/src/decoder/plugins/FaadDecoderPlugin.cxx +++ b/src/decoder/plugins/FaadDecoderPlugin.cxx @@ -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 diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx index 3fd8e4d4d..9346313ec 100644 --- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx +++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx @@ -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 diff --git a/src/decoder/plugins/FfmpegIo.cxx b/src/decoder/plugins/FfmpegIo.cxx index b8c6f918f..d99c21cc5 100644 --- a/src/decoder/plugins/FfmpegIo.cxx +++ b/src/decoder/plugins/FfmpegIo.cxx @@ -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 diff --git a/src/decoder/plugins/FfmpegIo.hxx b/src/decoder/plugins/FfmpegIo.hxx index 2546ce364..71a3890e4 100644 --- a/src/decoder/plugins/FfmpegIo.hxx +++ b/src/decoder/plugins/FfmpegIo.hxx @@ -28,17 +28,17 @@ extern "C" { #include +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(); diff --git a/src/decoder/plugins/FlacCommon.cxx b/src/decoder/plugins/FlacCommon.cxx index fbc336f3a..688f2adc1 100644 --- a/src/decoder/plugins/FlacCommon.cxx +++ b/src/decoder/plugins/FlacCommon.cxx @@ -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) { diff --git a/src/decoder/plugins/FlacCommon.hxx b/src/decoder/plugins/FlacCommon.hxx index b8da9440f..517fc12fe 100644 --- a/src/decoder/plugins/FlacCommon.hxx +++ b/src/decoder/plugins/FlacCommon.hxx @@ -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(). diff --git a/src/decoder/plugins/FlacDecoderPlugin.cxx b/src/decoder/plugins/FlacDecoderPlugin.cxx index 955d41360..b78e98fea 100644 --- a/src/decoder/plugins/FlacDecoderPlugin.cxx +++ b/src/decoder/plugins/FlacDecoderPlugin.cxx @@ -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 }; diff --git a/src/decoder/plugins/FlacInput.cxx b/src/decoder/plugins/FlacInput.cxx index 016c5beb2..e07dbbd12 100644 --- a/src/decoder/plugins/FlacInput.cxx +++ b/src/decoder/plugins/FlacInput.cxx @@ -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]); } diff --git a/src/decoder/plugins/FlacInput.hxx b/src/decoder/plugins/FlacInput.hxx index d1ebaa9ab..699b431e3 100644 --- a/src/decoder/plugins/FlacInput.hxx +++ b/src/decoder/plugins/FlacInput.hxx @@ -22,7 +22,7 @@ #include -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() { diff --git a/src/decoder/plugins/FluidsynthDecoderPlugin.cxx b/src/decoder/plugins/FluidsynthDecoderPlugin.cxx index c40beff8a..1ec7a68eb 100644 --- a/src/decoder/plugins/FluidsynthDecoderPlugin.cxx +++ b/src/decoder/plugins/FluidsynthDecoderPlugin.cxx @@ -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; diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx index e47447c9d..e2b587d5f 100644 --- a/src/decoder/plugins/GmeDecoderPlugin.cxx +++ b/src/decoder/plugins/GmeDecoderPlugin.cxx @@ -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)) diff --git a/src/decoder/plugins/MadDecoderPlugin.cxx b/src/decoder/plugins/MadDecoderPlugin.cxx index cb34aecea..731ae97f7 100644 --- a/src/decoder/plugins/MadDecoderPlugin.cxx +++ b/src/decoder/plugins/MadDecoderPlugin.cxx @@ -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; } diff --git a/src/decoder/plugins/MikmodDecoderPlugin.cxx b/src/decoder/plugins/MikmodDecoderPlugin.cxx index a92f6b2a3..ceacc81b4 100644 --- a/src/decoder/plugins/MikmodDecoderPlugin.cxx +++ b/src/decoder/plugins/MikmodDecoderPlugin.cxx @@ -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(); diff --git a/src/decoder/plugins/ModplugDecoderPlugin.cxx b/src/decoder/plugins/ModplugDecoderPlugin.cxx index 5597fccfa..2bf25a81c 100644 --- a/src/decoder/plugins/ModplugDecoderPlugin.cxx +++ b/src/decoder/plugins/ModplugDecoderPlugin.cxx @@ -52,7 +52,7 @@ modplug_decoder_init(const ConfigBlock &block) } static WritableBuffer -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); diff --git a/src/decoder/plugins/MpcdecDecoderPlugin.cxx b/src/decoder/plugins/MpcdecDecoderPlugin.cxx index 3becac779..bbf850a16 100644 --- a/src/decoder/plugins/MpcdecDecoderPlugin.cxx +++ b/src/decoder/plugins/MpcdecDecoderPlugin.cxx @@ -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); diff --git a/src/decoder/plugins/Mpg123DecoderPlugin.cxx b/src/decoder/plugins/Mpg123DecoderPlugin.cxx index 942398b20..8c1c45daf 100644 --- a/src/decoder/plugins/Mpg123DecoderPlugin.cxx +++ b/src/decoder/plugins/Mpg123DecoderPlugin.cxx @@ -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(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; diff --git a/src/decoder/plugins/OggCodec.cxx b/src/decoder/plugins/OggCodec.cxx index e3a0c2804..49e9898bf 100644 --- a/src/decoder/plugins/OggCodec.cxx +++ b/src/decoder/plugins/OggCodec.cxx @@ -28,13 +28,13 @@ #include 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; diff --git a/src/decoder/plugins/OggCodec.hxx b/src/decoder/plugins/OggCodec.hxx index cc4d01d7b..2bf879ffa 100644 --- a/src/decoder/plugins/OggCodec.hxx +++ b/src/decoder/plugins/OggCodec.hxx @@ -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 */ diff --git a/src/decoder/plugins/OggDecoder.cxx b/src/decoder/plugins/OggDecoder.cxx index b70e8f8f7..c0bf6a8f9 100644 --- a/src/decoder/plugins/OggDecoder.cxx +++ b/src/decoder/plugins/OggDecoder.cxx @@ -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, diff --git a/src/decoder/plugins/OggDecoder.hxx b/src/decoder/plugins/OggDecoder.hxx index 7534653ab..03bf074ff 100644 --- a/src/decoder/plugins/OggDecoder.hxx +++ b/src/decoder/plugins/OggDecoder.hxx @@ -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); diff --git a/src/decoder/plugins/OpusDecoderPlugin.cxx b/src/decoder/plugins/OpusDecoderPlugin.cxx index 6e60fb3cd..880f9d95c 100644 --- a/src/decoder/plugins/OpusDecoderPlugin.cxx +++ b/src/decoder/plugins/OpusDecoderPlugin.cxx @@ -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; } diff --git a/src/decoder/plugins/PcmDecoderPlugin.cxx b/src/decoder/plugins/PcmDecoderPlugin.cxx index ec1a643a0..1948a895d 100644 --- a/src/decoder/plugins/PcmDecoderPlugin.cxx +++ b/src/decoder/plugins/PcmDecoderPlugin.cxx @@ -39,13 +39,13 @@ static constexpr Domain pcm_decoder_domain("pcm_decoder"); template 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 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; diff --git a/src/decoder/plugins/SidplayDecoderPlugin.cxx b/src/decoder/plugins/SidplayDecoderPlugin.cxx index 8cc99cabd..552569996 100644 --- a/src/decoder/plugins/SidplayDecoderPlugin.cxx +++ b/src/decoder/plugins/SidplayDecoderPlugin.cxx @@ -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 0) data_time = player.time(); - decoder_command_finished(decoder); + decoder_command_finished(client); } if (end > 0 && player.time() >= end) diff --git a/src/decoder/plugins/SndfileDecoderPlugin.cxx b/src/decoder/plugins/SndfileDecoderPlugin.cxx index 051166c1c..bca24a6af 100644 --- a/src/decoder/plugins/SndfileDecoderPlugin.cxx +++ b/src/decoder/plugins/SndfileDecoderPlugin.cxx @@ -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); diff --git a/src/decoder/plugins/VorbisDecoderPlugin.cxx b/src/decoder/plugins/VorbisDecoderPlugin.cxx index e63e76039..766107490 100644 --- a/src/decoder/plugins/VorbisDecoderPlugin.cxx +++ b/src/decoder/plugins/VorbisDecoderPlugin.cxx @@ -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; } diff --git a/src/decoder/plugins/WavpackDecoderPlugin.cxx b/src/decoder/plugins/WavpackDecoderPlugin.cxx index 1835525b2..51310eb7d 100644 --- a/src/decoder/plugins/WavpackDecoderPlugin.cxx +++ b/src/decoder/plugins/WavpackDecoderPlugin.cxx @@ -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 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); } diff --git a/src/decoder/plugins/WildmidiDecoderPlugin.cxx b/src/decoder/plugins/WildmidiDecoderPlugin.cxx index d699c4ea6..5194c0113 100644 --- a/src/decoder/plugins/WildmidiDecoderPlugin.cxx +++ b/src/decoder/plugins/WildmidiDecoderPlugin.cxx @@ -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(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; } diff --git a/test/FakeDecoderAPI.cxx b/test/FakeDecoderAPI.cxx index fbd848fac..08e49e401 100644 --- a/test/FakeDecoderAPI.cxx +++ b/test/FakeDecoderAPI.cxx @@ -29,11 +29,12 @@ #include 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()); diff --git a/test/FakeDecoderAPI.hxx b/test/FakeDecoderAPI.hxx index b43698cff..87a58a290 100644 --- a/test/FakeDecoderAPI.hxx +++ b/test/FakeDecoderAPI.hxx @@ -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 diff --git a/test/run_decoder.cxx b/test/run_decoder.cxx index f8f139825..c5066d8a8 100644 --- a/test/run_decoder.cxx +++ b/test/run_decoder.cxx @@ -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];