decoder/mad: make enums strictly-typed

This commit is contained in:
Max Kellermann 2019-06-16 10:02:51 +02:00
parent 97e6ea57c4
commit 22a9e866bc

View File

@ -49,17 +49,17 @@
static constexpr unsigned long FRAMES_CUSHION = 2000; static constexpr unsigned long FRAMES_CUSHION = 2000;
enum mp3_action { enum class MadDecoderAction {
DECODE_SKIP = -3, SKIP,
DECODE_BREAK = -2, BREAK,
DECODE_CONT = -1, CONT,
DECODE_OK = 0 OK
}; };
enum muteframe { enum class MadDecoderMuteFrame {
MUTEFRAME_NONE, NONE,
MUTEFRAME_SKIP, SKIP,
MUTEFRAME_SEEK SEEK
}; };
/* the number of samples of silence the decoder inserts at start */ /* the number of samples of silence the decoder inserts at start */
@ -129,7 +129,7 @@ struct MadDecoder {
SignedSongTime total_time; SignedSongTime total_time;
SongTime elapsed_time; SongTime elapsed_time;
SongTime seek_time; SongTime seek_time;
enum muteframe mute_frame = MUTEFRAME_NONE; MadDecoderMuteFrame mute_frame = MadDecoderMuteFrame::NONE;
long *frame_offsets = nullptr; long *frame_offsets = nullptr;
mad_timer_t *times = nullptr; mad_timer_t *times = nullptr;
unsigned long highest_frame = 0; unsigned long highest_frame = 0;
@ -153,8 +153,8 @@ struct MadDecoder {
bool Seek(long offset); bool Seek(long offset);
bool FillBuffer(); bool FillBuffer();
void ParseId3(size_t tagsize, Tag *tag); void ParseId3(size_t tagsize, Tag *tag);
enum mp3_action DecodeNextFrameHeader(Tag *tag); MadDecoderAction DecodeNextFrameHeader(Tag *tag);
enum mp3_action DecodeNextFrame(); MadDecoderAction DecodeNextFrame();
gcc_pure gcc_pure
offset_type ThisFrameOffset() const noexcept; offset_type ThisFrameOffset() const noexcept;
@ -364,26 +364,26 @@ id3_tag_query(const void *p0, size_t length)
} }
#endif /* !ENABLE_ID3TAG */ #endif /* !ENABLE_ID3TAG */
static enum mp3_action static MadDecoderAction
RecoverFrameError(struct mad_stream &stream) RecoverFrameError(struct mad_stream &stream)
{ {
if (MAD_RECOVERABLE(stream.error)) if (MAD_RECOVERABLE(stream.error))
return DECODE_SKIP; return MadDecoderAction::SKIP;
else if (stream.error == MAD_ERROR_BUFLEN) else if (stream.error == MAD_ERROR_BUFLEN)
return DECODE_CONT; return MadDecoderAction::CONT;
FormatWarning(mad_domain, FormatWarning(mad_domain,
"unrecoverable frame level error: %s", "unrecoverable frame level error: %s",
mad_stream_errorstr(&stream)); mad_stream_errorstr(&stream));
return DECODE_BREAK; return MadDecoderAction::BREAK;
} }
enum mp3_action MadDecoderAction
MadDecoder::DecodeNextFrameHeader(Tag *tag) MadDecoder::DecodeNextFrameHeader(Tag *tag)
{ {
if ((stream.buffer == nullptr || stream.error == MAD_ERROR_BUFLEN) && if ((stream.buffer == nullptr || stream.error == MAD_ERROR_BUFLEN) &&
!FillBuffer()) !FillBuffer())
return DECODE_BREAK; return MadDecoderAction::BREAK;
if (mad_header_decode(&frame.header, &stream)) { if (mad_header_decode(&frame.header, &stream)) {
if (stream.error == MAD_ERROR_LOSTSYNC && stream.this_frame) { if (stream.error == MAD_ERROR_LOSTSYNC && stream.this_frame) {
@ -393,7 +393,7 @@ MadDecoder::DecodeNextFrameHeader(Tag *tag)
if (tagsize > 0) { if (tagsize > 0) {
ParseId3((size_t)tagsize, tag); ParseId3((size_t)tagsize, tag);
return DECODE_CONT; return MadDecoderAction::CONT;
} }
} }
@ -404,24 +404,24 @@ MadDecoder::DecodeNextFrameHeader(Tag *tag)
if (layer == (mad_layer)0) { if (layer == (mad_layer)0) {
if (new_layer != MAD_LAYER_II && new_layer != MAD_LAYER_III) { if (new_layer != MAD_LAYER_II && new_layer != MAD_LAYER_III) {
/* Only layer 2 and 3 have been tested to work */ /* Only layer 2 and 3 have been tested to work */
return DECODE_SKIP; return MadDecoderAction::SKIP;
} }
layer = new_layer; layer = new_layer;
} else if (new_layer != layer) { } else if (new_layer != layer) {
/* Don't decode frames with a different layer than the first */ /* Don't decode frames with a different layer than the first */
return DECODE_SKIP; return MadDecoderAction::SKIP;
} }
return DECODE_OK; return MadDecoderAction::OK;
} }
enum mp3_action MadDecoderAction
MadDecoder::DecodeNextFrame() MadDecoder::DecodeNextFrame()
{ {
if ((stream.buffer == nullptr || stream.error == MAD_ERROR_BUFLEN) && if ((stream.buffer == nullptr || stream.error == MAD_ERROR_BUFLEN) &&
!FillBuffer()) !FillBuffer())
return DECODE_BREAK; return MadDecoderAction::BREAK;
if (mad_frame_decode(&frame, &stream)) { if (mad_frame_decode(&frame, &stream)) {
if (stream.error == MAD_ERROR_LOSTSYNC) { if (stream.error == MAD_ERROR_LOSTSYNC) {
@ -430,14 +430,14 @@ MadDecoder::DecodeNextFrame()
stream.this_frame); stream.this_frame);
if (tagsize > 0) { if (tagsize > 0) {
mad_stream_skip(&stream, tagsize); mad_stream_skip(&stream, tagsize);
return DECODE_CONT; return MadDecoderAction::CONT;
} }
} }
return RecoverFrameError(stream); return RecoverFrameError(stream);
} }
return DECODE_OK; return MadDecoderAction::OK;
} }
/* xing stuff stolen from alsaplayer, and heavily modified by jat */ /* xing stuff stolen from alsaplayer, and heavily modified by jat */
@ -699,20 +699,20 @@ MadDecoder::DecodeFirstFrame(Tag *tag)
struct xing xing; struct xing xing;
while (true) { while (true) {
enum mp3_action ret; MadDecoderAction ret;
do { do {
ret = DecodeNextFrameHeader(tag); ret = DecodeNextFrameHeader(tag);
} while (ret == DECODE_CONT); } while (ret == MadDecoderAction::CONT);
if (ret == DECODE_BREAK) if (ret == MadDecoderAction::BREAK)
return false; return false;
if (ret == DECODE_SKIP) continue; if (ret == MadDecoderAction::SKIP) continue;
do { do {
ret = DecodeNextFrame(); ret = DecodeNextFrame();
} while (ret == DECODE_CONT); } while (ret == MadDecoderAction::CONT);
if (ret == DECODE_BREAK) if (ret == MadDecoderAction::BREAK)
return false; return false;
if (ret == DECODE_OK) break; if (ret == MadDecoderAction::OK) break;
} }
struct mad_bitptr ptr = stream.anc_ptr; struct mad_bitptr ptr = stream.anc_ptr;
@ -724,7 +724,7 @@ MadDecoder::DecodeFirstFrame(Tag *tag)
* if an xing tag exists, use that! * if an xing tag exists, use that!
*/ */
if (parse_xing(&xing, &ptr, &bitlen)) { if (parse_xing(&xing, &ptr, &bitlen)) {
mute_frame = MUTEFRAME_SKIP; mute_frame = MadDecoderMuteFrame::SKIP;
if ((xing.flags & XING_FRAMES) && xing.frames) { if ((xing.flags & XING_FRAMES) && xing.frames) {
mad_timer_t duration = frame.header.duration; mad_timer_t duration = frame.header.duration;
@ -906,14 +906,14 @@ MadDecoder::Read()
switch (mute_frame) { switch (mute_frame) {
DecoderCommand cmd; DecoderCommand cmd;
case MUTEFRAME_SKIP: case MadDecoderMuteFrame::SKIP:
mute_frame = MUTEFRAME_NONE; mute_frame = MadDecoderMuteFrame::NONE;
break; break;
case MUTEFRAME_SEEK: case MadDecoderMuteFrame::SEEK:
if (elapsed_time >= seek_time) if (elapsed_time >= seek_time)
mute_frame = MUTEFRAME_NONE; mute_frame = MadDecoderMuteFrame::NONE;
break; break;
case MUTEFRAME_NONE: case MadDecoderMuteFrame::NONE:
cmd = SyncAndSend(); cmd = SyncAndSend();
if (cmd == DecoderCommand::SEEK) { if (cmd == DecoderCommand::SEEK) {
assert(input_stream.IsSeekable()); assert(input_stream.IsSeekable());
@ -928,7 +928,7 @@ MadDecoder::Read()
client->SeekError(); client->SeekError();
} else { } else {
seek_time = t; seek_time = t;
mute_frame = MUTEFRAME_SEEK; mute_frame = MadDecoderMuteFrame::SEEK;
client->CommandFinished(); client->CommandFinished();
} }
} else if (cmd != DecoderCommand::NONE) } else if (cmd != DecoderCommand::NONE)
@ -936,7 +936,7 @@ MadDecoder::Read()
} }
while (true) { while (true) {
enum mp3_action ret; MadDecoderAction ret;
do { do {
Tag tag; Tag tag;
@ -945,21 +945,21 @@ MadDecoder::Read()
if (!tag.IsEmpty()) if (!tag.IsEmpty())
client->SubmitTag(input_stream, client->SubmitTag(input_stream,
std::move(tag)); std::move(tag));
} while (ret == DECODE_CONT); } while (ret == MadDecoderAction::CONT);
if (ret == DECODE_BREAK) if (ret == MadDecoderAction::BREAK)
return false; return false;
const bool skip = ret == DECODE_SKIP; const bool skip = ret == MadDecoderAction::SKIP;
if (mute_frame == MUTEFRAME_NONE) { if (mute_frame == MadDecoderMuteFrame::NONE) {
do { do {
ret = DecodeNextFrame(); ret = DecodeNextFrame();
} while (ret == DECODE_CONT); } while (ret == MadDecoderAction::CONT);
if (ret == DECODE_BREAK) if (ret == MadDecoderAction::BREAK)
return false; return false;
} }
if (!skip && ret == DECODE_OK) if (!skip && ret == MadDecoderAction::OK)
return true; return true;
} }
} }