parautenbach / hass-shairport-sync

A custom media player for Home Assistant that allows you to control and get updates from a Shairport Sync installation using MQTT.
Apache License 2.0
69 stars 12 forks source link

State Off and State Paused #5

Closed UMB8998 closed 5 days ago

UMB8998 commented 2 years ago

Hello, Thank you for the amazing program, I'm implementing it with Snapcast to have a multiroom system with Airplay and a Full Song Info. Because we have multiple source inputs, I want the lovelace card to disappear when there is nothing connected to this specific airplay source, I tried to do it with the sensor you already implemented on the program but the card would disappear the moment you press pause, I was thinking about using the "active_end" and "active_start" messages as a new sensor, there is any way to implement it in the code? (I saw that you have commented some kind of state sensor) Thanks!

parautenbach commented 2 years ago

Thank you for the feedback!

Unfortunately, I don't think it's possible if I remember what I saw in the ShairportSync logs when writing this: I think I always saw the active_start and play_start commands issued together. I wanted to use active_* to show the player state and the play_* ones to reflect the play states.

You could always try to have another subscription to the active_* topics with a sensor to see if it behaves in the way that you want.

scooter1556 commented 1 year ago

Apologies for dragging this one up again but it seems the MQTT behaviour of Shairport Sync has changed since this was last looked at.

In my testing active_start and active_end aren't that useful for clearing the media player metadata because active_end will fire when paused after a configurable timeout (10 seconds by default). However, play_end does seem to only publish on song change or session end so should be reliable to use for play control.

My thinking is that play_end can be used to put the player into a STOPPED state or similar as it doesn't fire when paused. If there is no subsequent play_start and active_end is published we can assume metadata can be cleared.

parautenbach commented 1 year ago

No problem.

I haven't been in a position to spend much time on this, unfortunately. I understand there is an issue for you.

I will hopefully have some things running again soon and be able to test this again.

Can you in the meantime confirm your SS config and version? Something like this:

3.3.7rc1-alac-OpenSSL-Avahi-ALSA-pipe-soxr-metadata-mqtt-sysconfdir:/etc.
scooter1556 commented 1 year ago

If it helps I am using the latest official image on Docker Hub

4.1.1-dirty-AirPlay2-alac-OpenSSL-Avahi-ALSA-dummy-stdout-pipe-soxr-convolution-metadata-mqtt-dbus-mpris-sysconfdir:/etc

I may also get some time to do some more testing at some point. If I get there before you I will look to submit a PR.

Appreciate the help.

parautenbach commented 1 year ago

Thanks!

I clearly need to upgrade my SS. :-)

Mind you, have a look at this PR, because it might solve your issue. I'm about to merge it.

Preemptively updated local media player state instead of waiting for the topic. I found that shairport sync does not immediately send an "play_end" but instead a "play_flush" when paused and the lag was annoying.

scooter1556 commented 1 year ago

Unfortunately #11 doesn't resolve the issue for me although it is definitely a nice upgrade :)

I am trying to get the media player card in Home Assistant to clear when the AirPlay session ends. Right now it appears to retain the metadata of the last song that was played but of course because the session has ended hitting "Play" or anything else does nothing.

Depending on how responsive the UI is the card can probably be cleared on play_end as long as the UI is able to keep up with a potential play_start and metadata updates immediately after... I guess this would need some testing. Otherwise the combination of play_end and active_end is probably a safer bet.

mill1000 commented 1 year ago

Changes merged in #13 might solve the issue you are experiencing.

parautenbach commented 1 year ago

Thanks @mill1000! I was actually just now going through old issues to find this and to leave the same comment. You got there quicker than me. :-)

scooter1556 commented 1 year ago

Thanks for your efforts @mill1000 .

The only problem I see with using only active_end is that the player state gets cleared when audio is paused and you can no longer start playback from Home Assistant. If play_end is triggered followed by a subsequent active_end metadata can safely be cleared.

For example:

mill1000 commented 1 year ago

Because we have multiple source inputs, I want the lovelace card to disappear when there is nothing connected to this specific airplay source, I tried to do it with the sensor you already implemented on the program but the card would disappear the moment you press pause,

What condition are you using to hide the card?

I use auto-entites to accomplish a similar goal, and I've configured it to display the card if it's in a "playing" or "paused" state. With this configuration, the card is only hidden when the player enters a stopped or idle state. (e.g. when active_end is received)

The only problem I see with using only active_end is that the player state gets cleared when audio is paused and you can no longer start playback from Home Assistant.

active_end is not sent when the stream is paused. At least not immediately.

play_start -> active_end = Paused

This is impossible given Shairport Sync's implementation (and frankly makes no sense to me). No active_end should be received without first receiving a play_end.

play_start -> play_end -> active_end = Session has finished (clear metadata) play_start -> play_end -> play_start = Track change

This is currently supported by the card.

scooter1556 commented 1 year ago

Thanks for the responses @mill1000

This is impossible given Shairport Sync's implementation (and frankly makes no sense to me). No active_end should be received without first receiving a play_end.

From what I can see when playback is paused active_end is triggered first which in turn triggers play_end which is the opposite way round to any other scenrio like track change or manually ending a session. I appreciate active_end can be configured with a timeout it's just a shame that a session is classed as "inactive" and the media card will clear just because music is paused which means playback can't be resumed from Home Assistant. This seems to be a shairport-sync/AirPlay issue though.

parautenbach commented 1 year ago

the media card will clear just because music is paused which means playback can't be resumed from Home Assistant

Keep in mind that your casting device might've disconnected in the mean time, in which case you can't resume playback anyway. I would suggest setting the timeout sufficiently long, but I haven't spotted a pattern for when (e.g. an iPhone) will drop the cast connection.

scooter1556 commented 1 year ago

Keep in mind that your casting device might've disconnected in the mean time, in which case you can't resume playback anyway. I would suggest setting the timeout sufficiently long, but I haven't spotted a pattern for when (e.g. an iPhone) will drop the cast connection.

Unfortunately shairport-sync still waits for the number of seconds specified in active_state_timeout before firing active_end even if you manually disconnect the AirPlay session on the phone (or it disconnects of it's own accord).

I guess a lot of this stems back to there being no real differentiation between stopping playback and pausing playback in most apps. Pausing playback currently doesn't trigger anything until active_state_timeout is reached so if you pause playback on your phone the state isn't reflected in Home Assistant.

parautenbach commented 1 year ago

Indeed, which is the reason I didn't care originally about making the distinction. ;-) I do think the latest contributions are good – there are just some caveats.

mill1000 commented 1 year ago

From what I can see when playback is paused active_end is triggered first which in turn triggers play_end which is the opposite way round to any other scenrio like track change or manually ending a session. I appreciate active_end can be configured with a timeout it's just a shame that a session is classed as "inactive" and the media card will clear just because music is paused which means playback can't be resumed from Home Assistant. This seems to be a shairport-sync/AirPlay issue though.

Are you sure about that behavior? That's the opposite of what I have witnessed while developing. Are you running the latest version of Shairport Sync? If you are running the latest version and can provide logs, it would be worth opening an issue in the Shairport Repo

scooter1556 commented 1 year ago

I am using the 4.1.1 release. I'll test the development branch and see if behaviour has changed and if not raise an issue on the shairport-sync repo.

mill1000 commented 1 year ago

I don't think that's necessary. I'm just running the latest release.