summaryrefslogtreecommitdiff
path: root/src/decoder
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-02-13 09:53:05 +0100
committerMax Kellermann <max@musicpd.org>2018-02-13 09:53:05 +0100
commit61f2ce67ddcd3d1e1f99395dee54c813b5ea9519 (patch)
treef16b60180ff2a9c105696acd314307ed3d3176bd /src/decoder
parent60dbf1bea05beadb03e5a9c34c0476bd44a06724 (diff)
decoder/HybridDSD: implement seeking
Diffstat (limited to 'src/decoder')
-rw-r--r--src/decoder/plugins/HybridDsdDecoderPlugin.cxx32
1 files changed, 26 insertions, 6 deletions
diff --git a/src/decoder/plugins/HybridDsdDecoderPlugin.cxx b/src/decoder/plugins/HybridDsdDecoderPlugin.cxx
index ee738fe07..ec04aee9d 100644
--- a/src/decoder/plugins/HybridDsdDecoderPlugin.cxx
+++ b/src/decoder/plugins/HybridDsdDecoderPlugin.cxx
@@ -177,30 +177,33 @@ HybridDsdDecode(DecoderClient &client, InputStream &input)
streams */
return;
- offset_type remaining_bytes;
+ uint64_t total_frames;
size_t frame_size;
unsigned kbit_rate;
try {
auto result = FindHybridDsdData(client, input);
auto duration = SignedSongTime::FromS(result.second / result.first.GetTimeToSize());
- client.Ready(result.first,
- /* TODO: implement seeking */ false,
- duration);
+ client.Ready(result.first, true, duration);
frame_size = result.first.GetFrameSize();
kbit_rate = frame_size * result.first.sample_rate /
(1024u / 8u);
- remaining_bytes = result.second;
+ total_frames = result.second / frame_size;
} catch (UnsupportedFile) {
/* not a Hybrid-DSD file; let the next decoder plugin
(e.g. FFmpeg) handle it */
return;
}
+ const offset_type start_offset = input.GetOffset();
+ offset_type remaining_bytes = total_frames * frame_size;
+
StaticFifoBuffer<uint8_t, 16384> buffer;
auto cmd = client.GetCommand();
while (remaining_bytes > 0) {
+ uint64_t seek_frame;
+
switch (cmd) {
case DecoderCommand::NONE:
case DecoderCommand::START:
@@ -210,7 +213,24 @@ HybridDsdDecode(DecoderClient &client, InputStream &input)
return;
case DecoderCommand::SEEK:
- // TODO: implement seeking
+ seek_frame = client.GetSeekFrame();
+ if (seek_frame >= total_frames) {
+ /* seeking past the end */
+ client.CommandFinished();
+ return;
+ }
+
+ try {
+ input.LockSeek(start_offset + seek_frame * frame_size);
+ remaining_bytes = (total_frames - seek_frame) * frame_size;
+ buffer.Clear();
+ client.CommandFinished();
+ } catch (...) {
+ LogError(std::current_exception());
+ client.SeekError();
+ }
+
+ cmd = DecoderCommand::NONE;
break;
}