From 86339eee870de33e2c44e1dc470336a9ca61603f Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Sat, 17 Aug 2019 01:37:39 +0200 Subject: [PATCH] [input] Make input_resume() not reopen tracks that have finished playing If playback was paused during the very last part of the track, the rest of the track would be read into the input buffer and the input would be closed. With this commit the input will not be reopened. Also allow input_flush to be called with null argument. --- src/input.c | 54 ++++++++++++++++++++++++++++++----------------------- src/input.h | 3 ++- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/input.c b/src/input.c index 5e92a023..69cb9bd7 100644 --- a/src/input.c +++ b/src/input.c @@ -115,7 +115,6 @@ struct input_arg { uint32_t item_id; int seek_ms; - bool resume; }; /* --- Globals --- */ @@ -344,18 +343,19 @@ clear(struct input_source *source) } static void -flush(short *flags) +flush(short *flagptr) { struct marker *marker; + short flags; size_t len; pthread_mutex_lock(&input_buffer.mutex); // We will return an OR of all the unread marker flags - *flags = 0; + flags = 0; for (marker = input_buffer.marker_tail; marker; marker = input_buffer.marker_tail) { - *flags |= marker->flag; + flags |= marker->flag; input_buffer.marker_tail = marker->prev; marker_free(marker); } @@ -375,14 +375,16 @@ flush(short *flags) pthread_mutex_unlock(&input_buffer.mutex); #ifdef DEBUG_INPUT - DPRINTF(E_DBG, L_PLAYER, "Flushing %zu bytes with flags %d\n", len, *flags); + DPRINTF(E_DBG, L_PLAYER, "Flushing %zu bytes with flags %d\n", len, flags); #endif + + if (flagptr) + *flagptr = flags; } static void stop(void) { - short flags; int type; event_del(input_open_timeout_ev); @@ -393,7 +395,7 @@ stop(void) if (inputs[type]->stop && input_now_reading.open) inputs[type]->stop(&input_now_reading); - flush(&flags); + flush(NULL); clear(&input_now_reading); } @@ -461,23 +463,12 @@ start(void *arg, int *retval) { struct input_arg *cmdarg = arg; struct db_queue_item *queue_item; - short flags; int ret; // If we are asked to start the item that is currently open we can just seek if (input_now_reading.open && cmdarg->item_id == input_now_reading.item_id) { - // When we resume we don't want to flush & seek, since that has either - // already been done, or it is not desired because we just filled the - // buffer after an underrun. - if (cmdarg->resume) - { - DPRINTF(E_DBG, L_PLAYER, "Resuming input read loop for item '%s' (item id %" PRIu32 ")\n", input_now_reading.path, input_now_reading.item_id); - *retval = cmdarg->seek_ms; - return COMMAND_END; - } - - flush(&flags); + flush(NULL); ret = seek(&input_now_reading, cmdarg->seek_ms); if (ret < 0) @@ -518,6 +509,26 @@ start(void *arg, int *retval) return COMMAND_END; } +// Resume is a no-op if what we are reading now (or just finished reading, hence +// we don't check if input_now_reading.open is true) is the same item as +// requested. We also don't want to flush & seek in this case, since that has +// either already been done, or it is not desired because we just filled the +// buffer after an underrun. +static enum command_state +resume(void *arg, int *retval) +{ + struct input_arg *cmdarg = arg; + + if (cmdarg->item_id == input_now_reading.item_id) + { + DPRINTF(E_DBG, L_PLAYER, "Resuming input read loop for item '%s' (item id %" PRIu32 ")\n", input_now_reading.path, input_now_reading.item_id); + *retval = cmdarg->seek_ms; + return COMMAND_END; + } + + return start(arg, retval); +} + static enum command_state stop_cmd(void *arg, int *retval) { @@ -788,7 +799,6 @@ input_seek(uint32_t item_id, int seek_ms) cmdarg.item_id = item_id; cmdarg.seek_ms = seek_ms; - cmdarg.resume = false; return commands_exec_sync(cmdbase, start, NULL, &cmdarg); } @@ -802,9 +812,8 @@ input_resume(uint32_t item_id, int seek_ms) cmdarg->item_id = item_id; cmdarg->seek_ms = seek_ms; - cmdarg->resume = true; - commands_exec_async(cmdbase, start, cmdarg); + commands_exec_async(cmdbase, resume, cmdarg); } void @@ -816,7 +825,6 @@ input_start(uint32_t item_id) cmdarg->item_id = item_id; cmdarg->seek_ms = 0; - cmdarg->resume = false; commands_exec_async(cmdbase, start, cmdarg); } diff --git a/src/input.h b/src/input.h index 4c3294a6..38635f0e 100644 --- a/src/input.h +++ b/src/input.h @@ -221,7 +221,8 @@ void input_stop(void); /* - * Flush input buffer. Output flags will be the same as input_read(). + * Flush input buffer. Output flags will be the same as input_read(). Call with + * null pointer is valid. */ void input_flush(short *flags);