aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/decoder_api.c61
-rw-r--r--src/decoder_control.c3
-rw-r--r--src/decoder_control.h20
-rw-r--r--src/decoder_thread.c2
4 files changed, 70 insertions, 16 deletions
diff --git a/src/decoder_api.c b/src/decoder_api.c
index a34e19b1a..311f1f31b 100644
--- a/src/decoder_api.c
+++ b/src/decoder_api.c
@@ -77,30 +77,54 @@ decoder_initialized(struct decoder *decoder,
}
/**
- * Returns the current decoder command. May return a "virtual"
- * synthesized command, e.g. to seek to the beginning of the CUE
- * track.
+ * Checks if we need an "initial seek". If so, then the initial seek
+ * is prepared, and the function returns true.
*/
G_GNUC_PURE
-static enum decoder_command
-decoder_get_virtual_command(struct decoder *decoder)
+static bool
+decoder_prepare_initial_seek(struct decoder *decoder)
{
const struct decoder_control *dc = decoder->dc;
assert(dc->pipe != NULL);
if (decoder->initial_seek_running)
- return DECODE_COMMAND_SEEK;
+ /* initial seek has already begun - override any other
+ command */
+ return true;
if (decoder->initial_seek_pending) {
if (dc->command == DECODE_COMMAND_NONE) {
+ /* begin initial seek */
+
decoder->initial_seek_pending = false;
decoder->initial_seek_running = true;
- return DECODE_COMMAND_SEEK;
+ return true;
}
+ /* skip initial seek when there's another command
+ (e.g. STOP) */
+
decoder->initial_seek_pending = false;
}
+ return false;
+}
+
+/**
+ * Returns the current decoder command. May return a "virtual"
+ * synthesized command, e.g. to seek to the beginning of the CUE
+ * track.
+ */
+G_GNUC_PURE
+static enum decoder_command
+decoder_get_virtual_command(struct decoder *decoder)
+{
+ const struct decoder_control *dc = decoder->dc;
+ assert(dc->pipe != NULL);
+
+ if (decoder_prepare_initial_seek(decoder))
+ return DECODE_COMMAND_SEEK;
+
return dc->command;
}
@@ -130,7 +154,7 @@ decoder_command_finished(struct decoder *decoder)
assert(music_pipe_empty(dc->pipe));
decoder->initial_seek_running = false;
- decoder->timestamp = dc->song->start_ms / 1000.;
+ decoder->timestamp = dc->start_ms / 1000.;
decoder_unlock(dc);
return;
}
@@ -162,7 +186,7 @@ double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder)
assert(dc->pipe != NULL);
if (decoder->initial_seek_running)
- return dc->song->start_ms / 1000.;
+ return dc->start_ms / 1000.;
assert(dc->command == DECODE_COMMAND_SEEK);
@@ -177,10 +201,12 @@ void decoder_seek_error(struct decoder * decoder)
assert(dc->pipe != NULL);
- if (decoder->initial_seek_running)
+ if (decoder->initial_seek_running) {
/* d'oh, we can't seek to the sub-song start position,
what now? - no idea, ignoring the problem for now. */
+ decoder->initial_seek_running = false;
return;
+ }
assert(dc->command == DECODE_COMMAND_SEEK);
@@ -424,8 +450,8 @@ decoder_data(struct decoder *decoder,
decoder->timestamp += (double)nbytes /
audio_format_time_to_size(&dc->out_audio_format);
- if (dc->song->end_ms > 0 &&
- decoder->timestamp >= dc->song->end_ms / 1000.0)
+ if (dc->end_ms > 0 &&
+ decoder->timestamp >= dc->end_ms / 1000.0)
/* the end of this range has been reached:
stop decoding */
return DECODE_COMMAND_STOP;
@@ -455,6 +481,14 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is,
update_stream_tag(decoder, is);
+ /* check if we're seeking */
+
+ if (decoder_prepare_initial_seek(decoder))
+ /* during initial seek, no music chunk must be created
+ until seeking is finished; skip the rest of the
+ function here */
+ return DECODE_COMMAND_SEEK;
+
/* send tag to music pipe */
if (decoder->stream_tag != NULL) {
@@ -468,9 +502,6 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is,
/* send only the decoder tag */
cmd = do_send_tag(decoder, tag);
- if (cmd == DECODE_COMMAND_NONE)
- cmd = decoder_get_virtual_command(decoder);
-
return cmd;
}
diff --git a/src/decoder_control.c b/src/decoder_control.c
index 685db6c22..70f34b331 100644
--- a/src/decoder_control.c
+++ b/src/decoder_control.c
@@ -96,6 +96,7 @@ dc_command_async(struct decoder_control *dc, enum decoder_command cmd)
void
dc_start(struct decoder_control *dc, struct song *song,
+ unsigned start_ms, unsigned end_ms,
struct music_buffer *buffer, struct music_pipe *pipe)
{
assert(song != NULL);
@@ -104,6 +105,8 @@ dc_start(struct decoder_control *dc, struct song *song,
assert(music_pipe_empty(pipe));
dc->song = song;
+ dc->start_ms = start_ms;
+ dc->end_ms = end_ms;
dc->buffer = buffer;
dc->pipe = pipe;
dc_command(dc, DECODE_COMMAND_START);
diff --git a/src/decoder_control.h b/src/decoder_control.h
index e1a718a59..566b153ee 100644
--- a/src/decoder_control.h
+++ b/src/decoder_control.h
@@ -85,6 +85,23 @@ struct decoder_control {
*/
const struct song *song;
+ /**
+ * The initial seek position (in milliseconds), e.g. to the
+ * start of a sub-track described by a CUE file.
+ *
+ * This attribute is set by dc_start().
+ */
+ unsigned start_ms;
+
+ /**
+ * The decoder will stop when it reaches this position (in
+ * milliseconds). 0 means don't stop before the end of the
+ * file.
+ *
+ * This attribute is set by dc_start().
+ */
+ unsigned end_ms;
+
float total_time;
/** the #music_chunk allocator */
@@ -229,11 +246,14 @@ decoder_current_song(const struct decoder_control *dc)
*
* @param the decoder
* @param song the song to be decoded
+ * @param start_ms see #decoder_control
+ * @param end_ms see #decoder_control
* @param pipe the pipe which receives the decoded chunks (owned by
* the caller)
*/
void
dc_start(struct decoder_control *dc, struct song *song,
+ unsigned start_ms, unsigned end_ms,
struct music_buffer *buffer, struct music_pipe *pipe);
void
diff --git a/src/decoder_thread.c b/src/decoder_thread.c
index dbead655d..c2bb655ea 100644
--- a/src/decoder_thread.c
+++ b/src/decoder_thread.c
@@ -380,7 +380,7 @@ decoder_run_song(struct decoder_control *dc,
{
struct decoder decoder = {
.dc = dc,
- .initial_seek_pending = song->start_ms > 0,
+ .initial_seek_pending = dc->start_ms > 0,
.initial_seek_running = false,
};
int ret;