summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-02-04 21:46:50 +0100
committerMax Kellermann <max@musicpd.org>2020-02-04 22:19:21 +0100
commit140d8547c7cd7432e4acb1acc18dc5235eef0bef (patch)
treeee34276d8ad01392f501c9f5aaf55d2b39f166b0 /test
parent6f579ddc95098b5ec54c8885a7e7cff1aae0cd04 (diff)
test/run_decoder: add option --seek
Diffstat (limited to 'test')
-rw-r--r--test/run_decoder.cxx94
1 files 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<uint64_t>(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 (...) {