[inputs/player] Fixup part 1

This commit is contained in:
ejurgensen 2019-02-17 10:41:11 +01:00
parent d008e241cf
commit b7add1d0fa
4 changed files with 55 additions and 18 deletions

View File

@ -236,7 +236,7 @@ stop(void *arg, int *retval)
type = input_now_reading.type;
if (inputs[type]->stop)
if (inputs[type]->stop && input_now_reading.open)
inputs[type]->stop(&input_now_reading);
flush(&flags);
@ -491,10 +491,18 @@ input_write(struct evbuffer *evbuf, struct media_quality *quality, short flags)
if (flags)
{
if (input_buffer.bytes_written > INPUT_BUFFER_THRESHOLD)
marker_add(input_buffer.bytes_written - INPUT_BUFFER_THRESHOLD, INPUT_FLAG_START_NEXT);
else
marker_add(input_buffer.bytes_written, INPUT_FLAG_START_NEXT);
if (read_end)
{
input_now_reading.open = false;
// This controls when the player will open the next track in the queue
if (input_buffer.bytes_read + INPUT_BUFFER_THRESHOLD < input_buffer.bytes_written)
// The player's read is behind, tell it to open when it reaches where
// we are minus the buffer size
marker_add(input_buffer.bytes_written - INPUT_BUFFER_THRESHOLD, INPUT_FLAG_START_NEXT);
else
// The player's read is close to our write, so open right away
marker_add(input_buffer.bytes_read, INPUT_FLAG_START_NEXT);
}
// Note this marker is added at the post-write position, since EOF, error
// and metadata belong there.
@ -578,7 +586,10 @@ play(evutil_socket_t fd, short flags, void *arg)
// loop any more. input_write() will pass the message to the player.
ret = inputs[input_now_reading.type]->play(&input_now_reading);
if (ret < 0)
return; // Error or EOF, so don't come back
{
input_now_reading.open = false;
return; // Error or EOF, so don't come back
}
event_add(inputev, &tv);
}

View File

@ -69,9 +69,12 @@ stop(struct input_source *source)
struct transcode_ctx *ctx = source->input_ctx;
transcode_cleanup(&ctx);
evbuffer_free(source->evbuf);
if (source->evbuf)
evbuffer_free(source->evbuf);
source->input_ctx = NULL;
source->evbuf = NULL;
return 0;
}

View File

@ -840,7 +840,8 @@ stop(struct input_source *source)
DPRINTF(E_DBG, L_PLAYER, "Stopping pipe\n");
evbuffer_free(source->evbuf);
if (source->evbuf)
evbuffer_free(source->evbuf);
pipe_close(pipe->fd);
@ -858,6 +859,7 @@ stop(struct input_source *source)
pipe_free(pipe);
source->input_ctx = NULL;
source->evbuf = NULL;
return 0;
}

View File

@ -668,7 +668,10 @@ source_next_create(struct player_source *current)
struct db_queue_item *queue_item;
if (!current)
return NULL;
{
DPRINTF(E_LOG, L_PLAYER, "Bug! source_next_create called without a current source\n");
return NULL;
}
queue_item = queue_item_next(current->item_id);
if (!queue_item)
@ -783,7 +786,7 @@ session_update_read_next(void)
{
struct player_source *ps;
ps = source_next_create(pb_session.reading_next);
ps = source_next_create(pb_session.reading_now);
source_free(&pb_session.reading_next);
pb_session.reading_next = ps;
}
@ -799,12 +802,17 @@ session_update_read_eof(void)
pb_session.reading_now = pb_session.reading_next;
pb_session.reading_next = NULL;
// There is nothing else to play
if (!pb_session.reading_now)
return;
// We inherit this because the input will only notify on quality changes, not
// if it the same as the previous track
pb_session.reading_now->quality = pb_session.reading_prev->quality;
pb_session.reading_now->output_buffer_samples = pb_session.reading_prev->output_buffer_samples;
pb_session.reading_now->read_start = pb_session.pos;
pb_session.reading_now->play_start = pb_session.pos + pb_session.reading_now->output_buffer_samples;
}
static void
@ -927,12 +935,14 @@ event_read_error()
event_read_eof();
}
// Kicks of input reading of next source (async), session is not affected by
// this, so there is no session update
// Kicks of input reading of next source (async)
static void
event_read_start_next()
{
DPRINTF(E_DBG, L_PLAYER, "event_start_next()\n");
DPRINTF(E_DBG, L_PLAYER, "event_read_start_next()\n");
// Attaches next item to session as reading_next
session_update_read_next();
source_next();
}
@ -1024,6 +1034,17 @@ source_read(int *nbytes, int *nsamples, struct media_quality *quality, uint8_t *
{
short flags;
// Nothing to read, stream silence until event_read() stops playback
if (!pb_session.reading_now && pb_session.playing_now)
{
memset(buf, 0, len);
*quality = pb_session.playing_now->quality;
*nbytes = len;
*nsamples = BTOS(*nbytes, quality->bits_per_sample, quality->channels);
event_read(*nsamples);
return 0;
}
*quality = pb_session.reading_now->quality;
*nsamples = 0;
*nbytes = input_read(buf, len, &flags);
@ -1110,14 +1131,14 @@ playback_cb(int fd, short what, void *arg)
pb_write_recovery = false;
}
// debug_counter++;
// if (debug_counter % 100 == 0)
// session_dump();
debug_counter++;
if (debug_counter % 100 == 0)
session_dump();
// If there was an overrun, we will try to read/write a corresponding number
// of times so we catch up. The read from the input is non-blocking, so it
// should not bring us further behind, even if there is no data.
for (i = 1 + overrun + pb_read_deficit; i > 0 && pb_session.reading_now; i--)
for (i = 1 + overrun + pb_read_deficit; i > 0; i--)
{
ret = source_read(&nbytes, &nsamples, &quality, pb_session.buffer, pb_session.bufsize);
if (ret < 0)