From e97ad7d9702f9456963242be9bf2f7888a7fd6fe Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Wed, 13 Feb 2019 16:56:17 +0100 Subject: [PATCH] [outputs] Reinstate device->activated, so that mdns flukes can't bring down playback --- src/outputs.c | 11 +++++++++++ src/outputs.h | 2 +- src/player.c | 52 +++++++++++++++++++++++---------------------------- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/outputs.c b/src/outputs.c index 34080528..0fe27e24 100644 --- a/src/outputs.c +++ b/src/outputs.c @@ -103,6 +103,7 @@ struct output_quality_subscription static struct output_quality_subscription output_quality_subscriptions[OUTPUTS_MAX_QUALITY_SUBSCRIPTIONS + 1]; static bool output_got_new_subscription; + /* ------------------------------- MISC HELPERS ----------------------------- */ static void @@ -201,6 +202,14 @@ deferred_cb(int fd, short what, void *arg) memset(&outputs_cb_queue[callback_id], 0, sizeof(struct outputs_callback_queue)); + // The device has left the building (stopped/failed), and the backend + // is not using it any more + if (!device->advertised && !device->session) + { + outputs_device_remove(device); + device = NULL; + } + DPRINTF(E_DBG, L_PLAYER, "Making deferred callback to %s, id was %d\n", player_pmap(cb), callback_id); cb(device, state); @@ -606,6 +615,8 @@ outputs_device_add(struct output_device *add, bool new_deselect, int default_vol device_list_sort(); + device->advertised = 1; + listener_notify(LISTENER_SPEAKER); return 0; diff --git a/src/outputs.h b/src/outputs.h index ef2fddea..e3802e78 100644 --- a/src/outputs.h +++ b/src/outputs.h @@ -114,7 +114,7 @@ struct output_device // Misc device flags unsigned selected:1; -// unsigned advertised:1; + unsigned advertised:1; unsigned has_password:1; unsigned has_video:1; unsigned requires_auth:1; diff --git a/src/player.c b/src/player.c index 6c028316..c5b11300 100644 --- a/src/player.c +++ b/src/player.c @@ -1211,6 +1211,7 @@ device_add(void *arg, int *retval) bool new_deselect; int default_volume; + // Default volume for new devices default_volume = (master_volume >= 0) ? master_volume : PLAYER_DEFAULT_VOLUME; // Never turn on new devices during playback @@ -1260,12 +1261,19 @@ device_remove_family(void *arg, int *retval) if (!device->v4_address && !device->v6_address) { - // Make sure device isn't selected anymore - if (device->selected) - speaker_deselect_output(device); + device->advertised = 0; - // Will also stop sessions on the device, if any - outputs_device_remove(device); + // If there is a session we will keep the device in the list until the + // backend gives us a callback with a failure. Then outputs.c will remove + // the device. If the output backend never gives a callback (can that + // happen?) then the device will never be removed. + if (!device->session) + { + if (device->selected) + speaker_deselect_output(device); + + outputs_device_remove(device); + } } outputs_device_free(remove); @@ -2440,20 +2448,13 @@ speaker_enable(void *arg, int *retval) uint64_t *id = arg; struct output_device *device; - *retval = 0; + device = outputs_device_get(*id); + if (!device) + return COMMAND_END; - DPRINTF(E_DBG, L_PLAYER, "Speaker enable: %" PRIu64 "\n", *id); + DPRINTF(E_DBG, L_PLAYER, "Speaker enable: '%s' (id=%" PRIu64 ")\n", device->name, *id); - *retval = 0; - - for (device = output_device_list; device; device = device->next) - { - if (*id == device->id) - { - *retval = speaker_activate(device); - break; - } - } + *retval = speaker_activate(device); if (*retval > 0) return COMMAND_PENDING; // async @@ -2467,20 +2468,13 @@ speaker_disable(void *arg, int *retval) uint64_t *id = arg; struct output_device *device; - *retval = 0; + device = outputs_device_get(*id); + if (!device) + return COMMAND_END; - DPRINTF(E_DBG, L_PLAYER, "Speaker disable: %" PRIu64 "\n", *id); + DPRINTF(E_DBG, L_PLAYER, "Speaker disable: '%s' (id=%" PRIu64 ")\n", device->name, *id); - *retval = 0; - - for (device = output_device_list; device; device = device->next) - { - if (*id == device->id) - { - *retval = speaker_deactivate(device); - break; - } - } + *retval = speaker_deactivate(device); if (*retval > 0) return COMMAND_PENDING; // async