[player/outputs] Implement changed output interfaces in most backends

Still missing cast, alsa and pulseaudio, but these can so far just be
disabled with configure.

Otherwise still mostly untested.
This commit is contained in:
ejurgensen
2019-02-10 23:27:29 +01:00
parent 14a6d318f0
commit e99f20992e
12 changed files with 429 additions and 529 deletions

View File

@@ -287,6 +287,8 @@ playback_abort(void);
static void
playback_suspend(void);
static int
player_get_current_pos(uint64_t *pos, struct timespec *ts, int commit);
/* ----------------------------- Volume helpers ----------------------------- */
@@ -1009,7 +1011,7 @@ source_switch(int nbytes)
}
static void
session_init(struct player_session *session, struct media_quality *quality)
session_reset(struct player_session *session, struct media_quality *quality)
{
session->samples_written = 0;
session->quality = *quality;
@@ -1033,7 +1035,7 @@ session_init(struct player_session *session, struct media_quality *quality)
}
static void
session_deinit(struct player_session *session)
session_clear(struct player_session *session)
{
free(session->buffer);
memset(session, 0, sizeof(struct player_session));
@@ -1083,7 +1085,9 @@ source_read(uint8_t *buf, int len)
else if (flags & INPUT_FLAG_QUALITY)
{
input_quality_get(&quality);
session_init(&pb_session, &quality);
if (!quality_is_equal(&quality, &pb_session.quality))
session_reset(&pb_session, &quality);
}
// We pad the output buffer with silence if we don't have enough data for a
@@ -1171,7 +1175,7 @@ playback_cb(int fd, short what, void *arg)
}
nsamples = BTOS(got, pb_session.quality.bits_per_sample, pb_session.quality.channels);
outputs_write2(pb_session.buffer, pb_session.bufsize, &pb_session.quality, nsamples, &pb_session.pts);
outputs_write(pb_session.buffer, pb_session.bufsize, &pb_session.quality, nsamples, &pb_session.pts);
pb_session.samples_written += nsamples;
if (got < pb_session.bufsize)
@@ -1468,11 +1472,11 @@ device_metadata_send(void *arg, int *retval)
/* -------- Output device callbacks executed in the player thread ----------- */
static void
device_streaming_cb(struct output_device *device, struct output_session *session, enum output_device_state status)
device_streaming_cb(struct output_device *device, enum output_device_state status)
{
int ret;
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_streaming_cb\n", outputs_name(device->type));
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_streaming_cb (status %d)\n", outputs_name(device->type), status);
ret = device_check(device);
if (ret < 0)
@@ -1492,8 +1496,6 @@ device_streaming_cb(struct output_device *device, struct output_session *session
if (player_state == PLAY_PLAYING)
speaker_deselect_output(device);
device->session = NULL;
if (!device->advertised)
device_remove(device);
@@ -1506,24 +1508,22 @@ device_streaming_cb(struct output_device *device, struct output_session *session
output_sessions--;
device->session = NULL;
if (!device->advertised)
device_remove(device);
}
else
outputs_status_cb(session, device_streaming_cb);
outputs_device_set_cb(device, device_streaming_cb);
}
static void
device_command_cb(struct output_device *device, struct output_session *session, enum output_device_state status)
device_command_cb(struct output_device *device, enum output_device_state status)
{
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_command_cb\n", outputs_name(device->type));
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_command_cb (status %d)\n", outputs_name(device->type), status);
outputs_status_cb(session, device_streaming_cb);
outputs_device_set_cb(device, device_streaming_cb);
if (status == OUTPUT_STATE_FAILED)
device_streaming_cb(device, session, status);
device_streaming_cb(device, status);
// Used by playback_suspend - is basically the bottom half
if (player_flush_pending > 0)
@@ -1537,12 +1537,12 @@ device_command_cb(struct output_device *device, struct output_session *session,
}
static void
device_shutdown_cb(struct output_device *device, struct output_session *session, enum output_device_state status)
device_shutdown_cb(struct output_device *device, enum output_device_state status)
{
int retval;
int ret;
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_shutdown_cb\n", outputs_name(device->type));
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_shutdown_cb (status %d)\n", outputs_name(device->type), status);
if (output_sessions)
output_sessions--;
@@ -1558,8 +1558,6 @@ device_shutdown_cb(struct output_device *device, struct output_session *session,
goto out;
}
device->session = NULL;
if (!device->advertised)
device_remove(device);
@@ -1572,9 +1570,9 @@ device_shutdown_cb(struct output_device *device, struct output_session *session,
}
static void
device_lost_cb(struct output_device *device, struct output_session *session, enum output_device_state status)
device_lost_cb(struct output_device *device, enum output_device_state status)
{
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_lost_cb\n", outputs_name(device->type));
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_lost_cb (status %d)\n", outputs_name(device->type), status);
// We lost that device during startup for some reason, not much we can do here
if (status == OUTPUT_STATE_FAILED)
@@ -1584,12 +1582,12 @@ device_lost_cb(struct output_device *device, struct output_session *session, enu
}
static void
device_activate_cb(struct output_device *device, struct output_session *session, enum output_device_state status)
device_activate_cb(struct output_device *device, enum output_device_state status)
{
int retval;
int ret;
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_activate_cb\n", outputs_name(device->type));
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_activate_cb (status %d)\n", outputs_name(device->type), status);
retval = commands_exec_returnvalue(cmdbase);
ret = device_check(device);
@@ -1597,8 +1595,7 @@ device_activate_cb(struct output_device *device, struct output_session *session,
{
DPRINTF(E_WARN, L_PLAYER, "Output device disappeared during startup!\n");
outputs_status_cb(session, device_lost_cb);
outputs_device_stop(session);
outputs_device_stop(device, device_lost_cb);
if (retval != -2)
retval = -1;
@@ -1623,11 +1620,9 @@ device_activate_cb(struct output_device *device, struct output_session *session,
goto out;
}
device->session = session;
output_sessions++;
outputs_status_cb(session, device_streaming_cb);
outputs_device_set_cb(device, device_streaming_cb);
out:
/* cur_cmd->ret already set
@@ -1639,12 +1634,12 @@ device_activate_cb(struct output_device *device, struct output_session *session,
}
static void
device_probe_cb(struct output_device *device, struct output_session *session, enum output_device_state status)
device_probe_cb(struct output_device *device, enum output_device_state status)
{
int retval;
int ret;
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_probe_cb\n", outputs_name(device->type));
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_probe_cb (status %d)\n", outputs_name(device->type), status);
retval = commands_exec_returnvalue(cmdbase);
ret = device_check(device);
@@ -1685,12 +1680,12 @@ device_probe_cb(struct output_device *device, struct output_session *session, en
}
static void
device_restart_cb(struct output_device *device, struct output_session *session, enum output_device_state status)
device_restart_cb(struct output_device *device, enum output_device_state status)
{
int retval;
int ret;
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_restart_cb\n", outputs_name(device->type));
DPRINTF(E_DBG, L_PLAYER, "Callback from %s to device_restart_cb (status %d)\n", outputs_name(device->type), status);
retval = commands_exec_returnvalue(cmdbase);
ret = device_check(device);
@@ -1698,8 +1693,7 @@ device_restart_cb(struct output_device *device, struct output_session *session,
{
DPRINTF(E_WARN, L_PLAYER, "Output device disappeared during restart!\n");
outputs_status_cb(session, device_lost_cb);
outputs_device_stop(session);
outputs_device_stop(device, device_lost_cb);
if (retval != -2)
retval = -1;
@@ -1724,10 +1718,8 @@ device_restart_cb(struct output_device *device, struct output_session *session,
goto out;
}
device->session = session;
output_sessions++;
outputs_status_cb(session, device_streaming_cb);
outputs_device_set_cb(device, device_streaming_cb);
out:
commands_exec_end(cmdbase, retval);
@@ -1786,19 +1778,30 @@ playback_timer_stop(void)
if (ret < 0)
{
DPRINTF(E_LOG, L_PLAYER, "Could not disarm playback timer: %s\n", strerror(errno));
return -1;
}
return 0;
}
static int
pb_session_stop(void)
{
int ret;
ret = playback_timer_stop();
session_clear(&pb_session);
return ret;
}
static void
playback_abort(void)
{
outputs_playback_stop();
playback_timer_stop();
pb_session_stop();
source_stop();
@@ -1815,9 +1818,9 @@ playback_abort(void)
static void
playback_suspend(void)
{
player_flush_pending = outputs_flush2(device_command_cb);
player_flush_pending = outputs_flush(device_command_cb);
playback_timer_stop();
pb_session_stop();
status_update(PLAY_PAUSED);
@@ -1949,9 +1952,9 @@ playback_stop(void *arg, int *retval)
// We may be restarting very soon, so we don't bring the devices to a full
// stop just yet; this saves time when restarting, which is nicer for the user
*retval = outputs_flush2(device_command_cb);
*retval = outputs_flush(device_command_cb);
playback_timer_stop();
pb_session_stop();
ps_playing = source_now_playing();
if (ps_playing)
@@ -1975,7 +1978,6 @@ playback_stop(void *arg, int *retval)
static enum command_state
playback_start_bh(void *arg, int *retval)
{
struct timespec ts;
int ret;
// initialize the packet timer to the same relative time that we have
@@ -1989,10 +1991,6 @@ playback_start_bh(void *arg, int *retval)
// pb_buffer_offset = 0;
pb_read_deficit = 0;
ret = clock_gettime_with_res(CLOCK_MONOTONIC, &ts, &player_timer_res);
if (ret < 0)
goto out_fail;
ret = playback_timer_start();
if (ret < 0)
goto out_fail;
@@ -2098,7 +2096,7 @@ playback_start_item(void *arg, int *retval)
{
if (device->selected && !device->session)
{
ret = outputs_device_start2(device, device_restart_cb);
ret = outputs_device_start(device, device_restart_cb);
if (ret < 0)
{
DPRINTF(E_LOG, L_PLAYER, "Could not start selected %s device '%s'\n", device->type_name, device->name);
@@ -2118,7 +2116,7 @@ playback_start_item(void *arg, int *retval)
continue;
speaker_select_output(device);
ret = outputs_device_start(device, device_restart_cb, TEMP_NEXT_RTPTIME);
ret = outputs_device_start(device, device_restart_cb);
if (ret < 0)
{
DPRINTF(E_DBG, L_PLAYER, "Could not autoselect %s device '%s'\n", device->type_name, device->name);
@@ -2420,9 +2418,9 @@ playback_pause(void *arg, int *retval)
return COMMAND_END;
}
*retval = outputs_flush2(device_command_cb);
*retval = outputs_flush(device_command_cb);
playback_timer_stop();
pb_session_stop();
source_pause(pos);
@@ -2530,7 +2528,7 @@ speaker_activate(struct output_device *device)
{
DPRINTF(E_DBG, L_PLAYER, "Activating %s device '%s'\n", device->type_name, device->name);
ret = outputs_device_start2(device, device_activate_cb);
ret = outputs_device_start(device, device_activate_cb);
if (ret < 0)
{
DPRINTF(E_LOG, L_PLAYER, "Could not start %s device '%s'\n", device->type_name, device->name);
@@ -2568,8 +2566,7 @@ speaker_deactivate(struct output_device *device)
if (!device->session)
return 0;
outputs_status_cb(device->session, device_shutdown_cb);
outputs_device_stop(device->session);
outputs_device_stop(device, device_shutdown_cb);
return 1;
}
@@ -2996,7 +2993,8 @@ playerqueue_plid(void *arg, int *retval)
/* ------------------------------- Player API ------------------------------- */
int
// TODO no longer part of API
static int
player_get_current_pos(uint64_t *pos, struct timespec *ts, int commit)
{
uint64_t delta;
@@ -3039,21 +3037,6 @@ player_get_current_pos(uint64_t *pos, struct timespec *ts, int commit)
return 0;
}
int
player_get_time(struct timespec *ts)
{
int ret;
ret = clock_gettime_with_res(CLOCK_MONOTONIC, ts, &player_timer_res);
if (ret < 0)
{
DPRINTF(E_LOG, L_PLAYER, "Couldn't get clock: %s\n", strerror(errno));
return -1;
}
return 0;
}
int
player_get_status(struct player_status *status)
{
@@ -3491,7 +3474,6 @@ player(void *arg)
int
player_init(void)
{
struct media_quality default_quality = { 44100, 16, 2 };
uint64_t interval;
uint32_t rnd;
int ret;
@@ -3567,8 +3549,6 @@ player_init(void)
goto evnew_fail;
}
session_init(&pb_session, &default_quality);
cmdbase = commands_base_new(evbase_player, NULL);
ret = outputs_init();
@@ -3605,7 +3585,6 @@ player_init(void)
outputs_deinit();
outputs_fail:
commands_base_free(cmdbase);
session_deinit(&pb_session);
evnew_fail:
event_base_free(evbase_player);
evbase_fail:
@@ -3638,7 +3617,7 @@ player_deinit(void)
player_exit = 1;
commands_base_destroy(cmdbase);
session_deinit(&pb_session);
session_clear(&pb_session);
ret = pthread_join(tid_player, NULL);
if (ret != 0)