test/run_decoder: add option --seek
This commit is contained in:
parent
6f579ddc95
commit
140d8547c7
@ -47,16 +47,20 @@ struct CommandLine {
|
|||||||
Path config_path = nullptr;
|
Path config_path = nullptr;
|
||||||
|
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
|
|
||||||
|
SongTime seek_where{};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Option {
|
enum Option {
|
||||||
OPTION_CONFIG,
|
OPTION_CONFIG,
|
||||||
OPTION_VERBOSE,
|
OPTION_VERBOSE,
|
||||||
|
OPTION_SEEK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr OptionDef option_defs[] = {
|
static constexpr OptionDef option_defs[] = {
|
||||||
{"config", 0, true, "Load a MPD configuration file"},
|
{"config", 0, true, "Load a MPD configuration file"},
|
||||||
{"verbose", 'v', false, "Verbose logging"},
|
{"verbose", 'v', false, "Verbose logging"},
|
||||||
|
{"seek", 0, true, "Seek to this position"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static CommandLine
|
static CommandLine
|
||||||
@ -74,6 +78,10 @@ ParseCommandLine(int argc, char **argv)
|
|||||||
case OPTION_VERBOSE:
|
case OPTION_VERBOSE:
|
||||||
c.verbose = true;
|
c.verbose = true;
|
||||||
break;
|
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)
|
int main(int argc, char **argv)
|
||||||
try {
|
try {
|
||||||
const auto c = ParseCommandLine(argc, argv);
|
const auto c = ParseCommandLine(argc, argv);
|
||||||
@ -115,7 +202,7 @@ try {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DumpDecoderClient client;
|
MyDecoderClient client(c.seek_where);
|
||||||
if (plugin->file_decode != nullptr) {
|
if (plugin->file_decode != nullptr) {
|
||||||
try {
|
try {
|
||||||
plugin->FileDecode(client, Path::FromFS(c.uri));
|
plugin->FileDecode(client, Path::FromFS(c.uri));
|
||||||
@ -132,10 +219,7 @@ try {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!client.IsInitialized()) {
|
client.Finish();
|
||||||
fprintf(stderr, "Decoding failed\n");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
Loading…
Reference in New Issue
Block a user