FlacInput.cxx 4.06 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2020 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * 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.
 */

20
#include "FlacInput.hxx"
21
#include "FlacDomain.hxx"
22
#include "../DecoderAPI.hxx"
Max Kellermann's avatar
Max Kellermann committed
23
#include "input/InputStream.hxx"
24
#include "Log.hxx"
25
#include "util/Compiler.h"
26

27
#include <exception>
28

29
FLAC__StreamDecoderReadStatus
30
FlacInput::Read(FLAC__byte buffer[], size_t *bytes)
31
{
32
	size_t r = decoder_read(client, input_stream, (void *)buffer, *bytes);
33 34 35
	*bytes = r;

	if (r == 0) {
36
		if (input_stream.LockIsEOF() ||
37
		    (client != nullptr &&
38
		     client->GetCommand() != DecoderCommand::NONE))
39 40 41 42 43 44 45 46 47
			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
48
FlacInput::Seek(FLAC__uint64 absolute_byte_offset)
49
{
50
	if (!input_stream.IsSeekable())
51 52
		return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;

53 54 55
	try {
		input_stream.LockSeek(absolute_byte_offset);
		return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
56 57
	} catch (...) {
		LogError(std::current_exception());
58
		return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
59
	}
60 61 62
}

FLAC__StreamDecoderTellStatus
63
FlacInput::Tell(FLAC__uint64 *absolute_byte_offset)
64
{
65
	if (!input_stream.IsSeekable())
66 67
		return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;

68
	*absolute_byte_offset = (FLAC__uint64)input_stream.GetOffset();
69 70 71 72
	return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}

FLAC__StreamDecoderLengthStatus
73
FlacInput::Length(FLAC__uint64 *stream_length)
74
{
75
	if (!input_stream.KnownSize())
76 77
		return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;

78
	*stream_length = (FLAC__uint64)input_stream.GetSize();
79 80 81 82
	return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}

FLAC__bool
83
FlacInput::Eof()
84
{
85
	return (client != nullptr &&
86 87
		client->GetCommand() != DecoderCommand::NONE &&
		client->GetCommand() != DecoderCommand::SEEK) ||
88
		input_stream.LockIsEOF();
89 90 91
}

void
92
FlacInput::Error(FLAC__StreamDecoderErrorStatus status)
93
{
94
	if (client == nullptr ||
95
	    client->GetCommand() != DecoderCommand::STOP)
96 97
		LogWarning(flac_domain,
			   FLAC__StreamDecoderErrorStatusString[status]);
98 99 100
}

FLAC__StreamDecoderReadStatus
Rosen Penev's avatar
Rosen Penev committed
101
FlacInput::Read([[maybe_unused]] const FLAC__StreamDecoder *flac_decoder,
102 103 104
		FLAC__byte buffer[], size_t *bytes,
		void *client_data)
{
Max Kellermann's avatar
Max Kellermann committed
105
	auto *i = (FlacInput *)client_data;
106 107 108 109 110

	return i->Read(buffer, bytes);
}

FLAC__StreamDecoderSeekStatus
Rosen Penev's avatar
Rosen Penev committed
111
FlacInput::Seek([[maybe_unused]] const FLAC__StreamDecoder *flac_decoder,
112 113
		FLAC__uint64 absolute_byte_offset, void *client_data)
{
Max Kellermann's avatar
Max Kellermann committed
114
	auto *i = (FlacInput *)client_data;
115 116 117 118 119

	return i->Seek(absolute_byte_offset);
}

FLAC__StreamDecoderTellStatus
Rosen Penev's avatar
Rosen Penev committed
120
FlacInput::Tell([[maybe_unused]] const FLAC__StreamDecoder *flac_decoder,
121 122
		FLAC__uint64 *absolute_byte_offset, void *client_data)
{
Max Kellermann's avatar
Max Kellermann committed
123
	auto *i = (FlacInput *)client_data;
124 125 126 127 128

	return i->Tell(absolute_byte_offset);
}

FLAC__StreamDecoderLengthStatus
Rosen Penev's avatar
Rosen Penev committed
129
FlacInput::Length([[maybe_unused]] const FLAC__StreamDecoder *flac_decoder,
130 131
		  FLAC__uint64 *stream_length, void *client_data)
{
Max Kellermann's avatar
Max Kellermann committed
132
	auto *i = (FlacInput *)client_data;
133 134 135 136 137

	return i->Length(stream_length);
}

FLAC__bool
Rosen Penev's avatar
Rosen Penev committed
138
FlacInput::Eof([[maybe_unused]] const FLAC__StreamDecoder *flac_decoder,
139 140
	       void *client_data)
{
Max Kellermann's avatar
Max Kellermann committed
141
	auto *i = (FlacInput *)client_data;
142 143 144 145 146

	return i->Eof();
}

void
Rosen Penev's avatar
Rosen Penev committed
147
FlacInput::Error([[maybe_unused]] const FLAC__StreamDecoder *decoder,
148 149
		 FLAC__StreamDecoderErrorStatus status, void *client_data)
{
Max Kellermann's avatar
Max Kellermann committed
150
	auto *i = (FlacInput *)client_data;
151 152 153 154

	i->Error(status);
}