[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.
This commit is contained in:
ejurgensen 2019-08-17 01:37:39 +02:00
parent 7dfe4c2b65
commit 86339eee87
2 changed files with 33 additions and 24 deletions

View File

@ -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);
}

View File

@ -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);