From 140d8547c7cd7432e4acb1acc18dc5235eef0bef Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 4 Feb 2020 21:46:50 +0100 Subject: [PATCH] test/run_decoder: add option --seek --- test/run_decoder.cxx | 94 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 5 deletions(-) diff --git a/test/run_decoder.cxx b/test/run_decoder.cxx index 43c8ee4b3..0a31fe28b 100644 --- a/test/run_decoder.cxx +++ b/test/run_decoder.cxx @@ -47,16 +47,20 @@ struct CommandLine { Path config_path = nullptr; bool verbose = false; + + SongTime seek_where{}; }; enum Option { OPTION_CONFIG, OPTION_VERBOSE, + OPTION_SEEK, }; static constexpr OptionDef option_defs[] = { {"config", 0, true, "Load a MPD configuration file"}, {"verbose", 'v', false, "Verbose logging"}, + {"seek", 0, true, "Seek to this position"}, }; static CommandLine @@ -74,6 +78,10 @@ ParseCommandLine(int argc, char **argv) case OPTION_VERBOSE: c.verbose = true; break; + + case OPTION_SEEK: + c.seek_where = SongTime::FromS(strtod(o.value, nullptr)); + break; } } @@ -102,6 +110,85 @@ public: } }; +class MyDecoderClient final : public DumpDecoderClient { + SongTime seek_where; + + unsigned sample_rate; + + bool seekable, seek_error = false; + +public: + explicit MyDecoderClient(SongTime _seek_where) noexcept + :seek_where(_seek_where) {} + + void Finish() { + if (!IsInitialized()) + throw "Unrecognized file"; + + if (seek_error) + throw "Seek error"; + + if (seek_where != SongTime{}) { + if (!seekable) + throw "Not seekable"; + + throw "Did not seek"; + } + } + + /* virtual methods from DecoderClient */ + void Ready(AudioFormat audio_format, + bool _seekable, SignedSongTime duration) noexcept override { + assert(!IsInitialized()); + + DumpDecoderClient::Ready(audio_format, _seekable, duration); + sample_rate = audio_format.sample_rate; + seekable = _seekable; + } + + DecoderCommand GetCommand() noexcept override { + assert(IsInitialized()); + + if (seek_where != SongTime{}) { + if (!seekable) + return DecoderCommand::STOP; + + return DecoderCommand::SEEK; + } else if (seek_error) + return DecoderCommand::STOP; + else + return DumpDecoderClient::GetCommand(); + } + + void CommandFinished() noexcept override { + assert(!seek_error); + + if (seek_where != SongTime{}) + seek_where = {}; + else + DumpDecoderClient::CommandFinished(); + } + + SongTime GetSeekTime() noexcept override { + assert(seek_where != SongTime{}); + + return seek_where; + } + + uint64_t GetSeekFrame() noexcept override { + assert(seek_where != SongTime{}); + + return GetSeekTime().ToScale(sample_rate); + } + + void SeekError() noexcept override { + assert(seek_where != SongTime{}); + + seek_error = true; + seek_where = {}; + } +}; + int main(int argc, char **argv) try { const auto c = ParseCommandLine(argc, argv); @@ -115,7 +202,7 @@ try { return EXIT_FAILURE; } - DumpDecoderClient client; + MyDecoderClient client(c.seek_where); if (plugin->file_decode != nullptr) { try { plugin->FileDecode(client, Path::FromFS(c.uri)); @@ -132,10 +219,7 @@ try { return EXIT_FAILURE; } - if (!client.IsInitialized()) { - fprintf(stderr, "Decoding failed\n"); - return EXIT_FAILURE; - } + client.Finish(); return EXIT_SUCCESS; } catch (...) {