aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/decoder/FLACCommon.cxx12
-rw-r--r--src/decoder/FLACCommon.hxx7
-rw-r--r--src/decoder/FLACDecoderPlugin.cxx109
-rw-r--r--src/decoder/FLACInput.cxx152
-rw-r--r--src/decoder/FLACInput.hxx72
5 files changed, 242 insertions, 110 deletions
diff --git a/src/decoder/FLACCommon.cxx b/src/decoder/FLACCommon.cxx
index ed9245100..97743f332 100644
--- a/src/decoder/FLACCommon.cxx
+++ b/src/decoder/FLACCommon.cxx
@@ -36,7 +36,8 @@ extern "C" {
flac_data::flac_data(struct decoder *_decoder,
struct input_stream *_input_stream)
- :initialized(false), unsupported(false),
+ :FLACInput(_input_stream, _decoder),
+ initialized(false), unsupported(false),
total_frames(0), first_frame(0), next_frame(0), position(0),
decoder(_decoder), input_stream(_input_stream),
tag(nullptr)
@@ -132,15 +133,6 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
}
}
-void flac_error_common_cb(const FLAC__StreamDecoderErrorStatus status,
- struct flac_data *data)
-{
- if (decoder_get_command(data->decoder) == DECODE_COMMAND_STOP)
- return;
-
- g_warning("%s", FLAC__StreamDecoderErrorStatusString[status]);
-}
-
/**
* This function attempts to call decoder_initialized() in case there
* was no STREAMINFO block. This is allowed for nonseekable streams,
diff --git a/src/decoder/FLACCommon.hxx b/src/decoder/FLACCommon.hxx
index 501c58f62..e9b45976d 100644
--- a/src/decoder/FLACCommon.hxx
+++ b/src/decoder/FLACCommon.hxx
@@ -24,6 +24,8 @@
#ifndef MPD_FLAC_COMMON_HXX
#define MPD_FLAC_COMMON_HXX
+#include "FLACInput.hxx"
+
extern "C" {
#include "decoder_api.h"
#include "pcm_buffer.h"
@@ -35,7 +37,7 @@ extern "C" {
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "flac"
-struct flac_data {
+struct flac_data : public FLACInput {
struct pcm_buffer buffer;
/**
@@ -91,9 +93,6 @@ struct flac_data {
void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
struct flac_data *data);
-void flac_error_common_cb(FLAC__StreamDecoderErrorStatus status,
- struct flac_data *data);
-
FLAC__StreamDecoderWriteStatus
flac_common_write(struct flac_data *data, const FLAC__Frame * frame,
const FLAC__int32 *const buf[],
diff --git a/src/decoder/FLACDecoderPlugin.cxx b/src/decoder/FLACDecoderPlugin.cxx
index 3795f515b..cfe5e5680 100644
--- a/src/decoder/FLACDecoderPlugin.cxx
+++ b/src/decoder/FLACDecoderPlugin.cxx
@@ -38,92 +38,6 @@ extern "C" {
#error libFLAC is too old
#endif
-/* this code was based on flac123, from flac-tools */
-
-static FLAC__StreamDecoderReadStatus
-flac_read_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__byte buf[], size_t *bytes,
- void *fdata)
-{
- struct flac_data *data = (struct flac_data *)fdata;
- size_t r;
-
- r = decoder_read(data->decoder, data->input_stream,
- (void *)buf, *bytes);
- *bytes = r;
-
- if (r == 0) {
- if (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE ||
- input_stream_lock_eof(data->input_stream))
- return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
- else
- return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
- }
-
- return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
-}
-
-static FLAC__StreamDecoderSeekStatus
-flac_seek_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__uint64 offset, void *fdata)
-{
- struct flac_data *data = (struct flac_data *) fdata;
-
- if (!data->input_stream->seekable)
- return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
-
- if (!input_stream_lock_seek(data->input_stream, offset, SEEK_SET,
- nullptr))
- return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
-
- return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
-}
-
-static FLAC__StreamDecoderTellStatus
-flac_tell_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__uint64 * offset, void *fdata)
-{
- struct flac_data *data = (struct flac_data *) fdata;
-
- if (!data->input_stream->seekable)
- return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
-
- *offset = (long)(data->input_stream->offset);
-
- return FLAC__STREAM_DECODER_TELL_STATUS_OK;
-}
-
-static FLAC__StreamDecoderLengthStatus
-flac_length_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__uint64 * length, void *fdata)
-{
- struct flac_data *data = (struct flac_data *) fdata;
-
- if (data->input_stream->size < 0)
- return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
-
- *length = (size_t) (data->input_stream->size);
-
- return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
-}
-
-static FLAC__bool
-flac_eof_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd, void *fdata)
-{
- struct flac_data *data = (struct flac_data *) fdata;
-
- return (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE &&
- decoder_get_command(data->decoder) != DECODE_COMMAND_SEEK) ||
- input_stream_lock_eof(data->input_stream);
-}
-
-static void
-flac_error_cb(G_GNUC_UNUSED const FLAC__StreamDecoder *fd,
- FLAC__StreamDecoderErrorStatus status, void *fdata)
-{
- flac_error_common_cb(status, (struct flac_data *) fdata);
-}
-
static void flacPrintErroredState(FLAC__StreamDecoderState state)
{
switch (state) {
@@ -280,14 +194,14 @@ static FLAC__StreamDecoderInitStatus
stream_init_oggflac(FLAC__StreamDecoder *flac_dec, struct flac_data *data)
{
return FLAC__stream_decoder_init_ogg_stream(flac_dec,
- flac_read_cb,
- flac_seek_cb,
- flac_tell_cb,
- flac_length_cb,
- flac_eof_cb,
+ FLACInput::Read,
+ FLACInput::Seek,
+ FLACInput::Tell,
+ FLACInput::Length,
+ FLACInput::Eof,
flac_write_cb,
flacMetadata,
- flac_error_cb,
+ FLACInput::Error,
data);
}
@@ -295,11 +209,14 @@ static FLAC__StreamDecoderInitStatus
stream_init_flac(FLAC__StreamDecoder *flac_dec, struct flac_data *data)
{
return FLAC__stream_decoder_init_stream(flac_dec,
- flac_read_cb, flac_seek_cb,
- flac_tell_cb, flac_length_cb,
- flac_eof_cb, flac_write_cb,
+ FLACInput::Read,
+ FLACInput::Seek,
+ FLACInput::Tell,
+ FLACInput::Length,
+ FLACInput::Eof,
+ flac_write_cb,
flacMetadata,
- flac_error_cb,
+ FLACInput::Error,
data);
}
diff --git a/src/decoder/FLACInput.cxx b/src/decoder/FLACInput.cxx
new file mode 100644
index 000000000..0383ac4ff
--- /dev/null
+++ b/src/decoder/FLACInput.cxx
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2003-2012 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.
+ */
+
+#include "config.h"
+#include "FLACInput.hxx"
+#include "gcc.h"
+
+extern "C" {
+#include "input_stream.h"
+#include "decoder_api.h"
+}
+
+FLAC__StreamDecoderReadStatus
+FLACInput::Read(FLAC__byte buffer[], size_t *bytes)
+{
+ size_t r = decoder_read(decoder, input_stream, (void *)buffer, *bytes);
+ *bytes = r;
+
+ if (r == 0) {
+ if (input_stream_lock_eof(input_stream) ||
+ (decoder != nullptr &&
+ decoder_get_command(decoder) != DECODE_COMMAND_NONE))
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+ else
+ return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+ }
+
+ return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+}
+
+FLAC__StreamDecoderSeekStatus
+FLACInput::Seek(FLAC__uint64 absolute_byte_offset)
+{
+ if (!input_stream->seekable)
+ return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
+
+ if (!input_stream_lock_seek(input_stream,
+ absolute_byte_offset, SEEK_SET,
+ nullptr))
+ return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+
+ return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+FLAC__StreamDecoderTellStatus
+FLACInput::Tell(FLAC__uint64 *absolute_byte_offset)
+{
+ if (!input_stream->seekable)
+ return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
+
+ *absolute_byte_offset = (FLAC__uint64)input_stream->offset;
+ return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+}
+
+FLAC__StreamDecoderLengthStatus
+FLACInput::Length(FLAC__uint64 *stream_length)
+{
+ if (input_stream->size < 0)
+ return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+
+ *stream_length = (FLAC__uint64)input_stream->size;
+ return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+}
+
+FLAC__bool
+FLACInput::Eof()
+{
+ return (decoder != nullptr &&
+ decoder_get_command(decoder) != DECODE_COMMAND_NONE &&
+ decoder_get_command(decoder) != DECODE_COMMAND_SEEK) ||
+ input_stream_lock_eof(input_stream);
+}
+
+void
+FLACInput::Error(FLAC__StreamDecoderErrorStatus status)
+{
+ if (decoder == nullptr ||
+ decoder_get_command(decoder) != DECODE_COMMAND_STOP)
+ g_warning("%s", FLAC__StreamDecoderErrorStatusString[status]);
+}
+
+FLAC__StreamDecoderReadStatus
+FLACInput::Read(gcc_unused const FLAC__StreamDecoder *flac_decoder,
+ FLAC__byte buffer[], size_t *bytes,
+ void *client_data)
+{
+ FLACInput *i = (FLACInput *)client_data;
+
+ return i->Read(buffer, bytes);
+}
+
+FLAC__StreamDecoderSeekStatus
+FLACInput::Seek(gcc_unused const FLAC__StreamDecoder *flac_decoder,
+ FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+ FLACInput *i = (FLACInput *)client_data;
+
+ return i->Seek(absolute_byte_offset);
+}
+
+FLAC__StreamDecoderTellStatus
+FLACInput::Tell(gcc_unused const FLAC__StreamDecoder *flac_decoder,
+ FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+ FLACInput *i = (FLACInput *)client_data;
+
+ return i->Tell(absolute_byte_offset);
+}
+
+FLAC__StreamDecoderLengthStatus
+FLACInput::Length(gcc_unused const FLAC__StreamDecoder *flac_decoder,
+ FLAC__uint64 *stream_length, void *client_data)
+{
+ FLACInput *i = (FLACInput *)client_data;
+
+ return i->Length(stream_length);
+}
+
+FLAC__bool
+FLACInput::Eof(gcc_unused const FLAC__StreamDecoder *flac_decoder,
+ void *client_data)
+{
+ FLACInput *i = (FLACInput *)client_data;
+
+ return i->Eof();
+}
+
+void
+FLACInput::Error(gcc_unused const FLAC__StreamDecoder *decoder,
+ FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+ FLACInput *i = (FLACInput *)client_data;
+
+ i->Error(status);
+}
+
diff --git a/src/decoder/FLACInput.hxx b/src/decoder/FLACInput.hxx
new file mode 100644
index 000000000..7661567d1
--- /dev/null
+++ b/src/decoder/FLACInput.hxx
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2003-2012 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_FLAC_INPUT_HXX
+#define MPD_FLAC_INPUT_HXX
+
+#include <FLAC/stream_decoder.h>
+
+/**
+ * This class wraps an #input_stream in libFLAC stream decoder
+ * callbacks.
+ */
+class FLACInput {
+ struct decoder *decoder;
+
+ struct input_stream *input_stream;
+
+public:
+ FLACInput(struct input_stream *_input_stream,
+ struct decoder *_decoder=nullptr)
+ :decoder(_decoder), input_stream(_input_stream) {}
+
+protected:
+ FLAC__StreamDecoderReadStatus Read(FLAC__byte buffer[], size_t *bytes);
+ FLAC__StreamDecoderSeekStatus Seek(FLAC__uint64 absolute_byte_offset);
+ FLAC__StreamDecoderTellStatus Tell(FLAC__uint64 *absolute_byte_offset);
+ FLAC__StreamDecoderLengthStatus Length(FLAC__uint64 *stream_length);
+ FLAC__bool Eof();
+ void Error(FLAC__StreamDecoderErrorStatus status);
+
+public:
+ static FLAC__StreamDecoderReadStatus
+ Read(const FLAC__StreamDecoder *flac_decoder,
+ FLAC__byte buffer[], size_t *bytes, void *client_data);
+
+ static FLAC__StreamDecoderSeekStatus
+ Seek(const FLAC__StreamDecoder *flac_decoder,
+ FLAC__uint64 absolute_byte_offset, void *client_data);
+
+ static FLAC__StreamDecoderTellStatus
+ Tell(const FLAC__StreamDecoder *flac_decoder,
+ FLAC__uint64 *absolute_byte_offset, void *client_data);
+
+ static FLAC__StreamDecoderLengthStatus
+ Length(const FLAC__StreamDecoder *flac_decoder,
+ FLAC__uint64 *stream_length, void *client_data);
+
+ static FLAC__bool
+ Eof(const FLAC__StreamDecoder *flac_decoder, void *client_data);
+
+ static void
+ Error(const FLAC__StreamDecoder *decoder,
+ FLAC__StreamDecoderErrorStatus status, void *client_data);
+};
+
+#endif