[player/outputs] Fix for speaker selection and volume adj (closes #1011)

* Make sure that vol_adjust() bases adjustments on the same speakers that the
  user sees as active
* If a speaker fails during activation we unselect it, so that we don't keep
  trying to start it, so we find a new master volume if required, and so it is
  possible for the user to reselect it.
This commit is contained in:
ejurgensen 2020-05-27 22:53:11 +02:00
parent a9a6f4b584
commit 5d22f11b0e
3 changed files with 14 additions and 8 deletions

View File

@ -515,7 +515,7 @@ vol_adjust(void)
for (device = output_device_list; device; device = device->next)
{
if (device->selected && (device->volume > selected_highest))
if (OUTPUTS_DEVICE_DISPLAY_SELECTED(device) && (device->volume > selected_highest))
selected_highest = device->volume;
if (device->volume > all_highest)
@ -526,7 +526,7 @@ vol_adjust(void)
for (device = output_device_list; device; device = device->next)
{
if (!device->selected && (device->volume > outputs_master_volume))
if (!OUTPUTS_DEVICE_DISPLAY_SELECTED(device) && (device->volume > outputs_master_volume))
device->volume = outputs_master_volume;
device->relvol = vol_to_rel(device->volume, outputs_master_volume);
@ -537,7 +537,7 @@ vol_adjust(void)
for (device = output_device_list; device; device = device->next)
{
DPRINTF(E_DBG, L_PLAYER, "*** %s: abs %d rel %d selected %d\n", device->name, device->volume, device->relvol, device->selected);
DPRINTF(E_DBG, L_PLAYER, "*** %s: abs %d rel %d selected %d\n", device->name, device->volume, device->relvol, OUTPUTS_DEVICE_DISPLAY_SELECTED(device));
}
#endif
}

View File

@ -41,6 +41,12 @@
// different values can only do so within a limited range (maybe max 3 secs)
#define OUTPUTS_BUFFER_DURATION 2
// Whether the device should be *displayed* as selected is not given by
// device->selected, since that means "has the user selected the device",
// without taking into account whether it is working or available. This macro
// is a compound of the factors that determine how to display speaker selection.
#define OUTPUTS_DEVICE_DISPLAY_SELECTED(device) ((device)->selected && (device)->state >= OUTPUT_STATE_STOPPED && !(device)->busy && !(device)->prevent_playback)
// Forward declarations
struct output_device;
struct output_metadata;

View File

@ -1582,6 +1582,8 @@ device_activate_cb(struct output_device *device, enum output_device_state status
{
DPRINTF(E_LOG, L_PLAYER, "The %s device '%s' requires a valid PIN or password\n", device->type_name, device->name);
outputs_device_deselect(device);
retval = -2;
goto out;
}
@ -1590,6 +1592,8 @@ device_activate_cb(struct output_device *device, enum output_device_state status
{
DPRINTF(E_LOG, L_PLAYER, "The %s device '%s' failed to activate\n", device->type_name, device->name);
outputs_device_deselect(device);
if (retval != -2)
retval = -1;
goto out;
@ -2453,11 +2457,7 @@ device_to_speaker_info(struct player_speaker_info *spk, struct output_device *de
spk->relvol = device->relvol;
spk->absvol = device->volume;
// We can't map device->selected directly to spk->selected, since the former
// means "has the user selected the device" (even if it isn't working or is
// unavailable), while clients that get the latter just want to know if the
// speaker plays or will be playing.
spk->selected = (device->selected && device->state >= OUTPUT_STATE_STOPPED && !device->busy && !device->prevent_playback);
spk->selected = OUTPUTS_DEVICE_DISPLAY_SELECTED(device);
spk->has_password = device->has_password;
spk->has_video = device->has_video;