Clean up Sonos attributes for radio streams (#33063)

This commit is contained in:
Anders Melchiorsen 2020-03-21 20:17:00 +01:00 committed by GitHub
parent 5893f6b14b
commit 699ca44260
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 97 deletions

View file

@ -336,6 +336,7 @@ homeassistant/components/solax/* @squishykid
homeassistant/components/soma/* @ratsept
homeassistant/components/somfy/* @tetienne
homeassistant/components/songpal/* @rytilahti
homeassistant/components/sonos/* @amelchio
homeassistant/components/spaceapi/* @fabaff
homeassistant/components/speedtestdotnet/* @rohankapoorcom
homeassistant/components/spider/* @peternijssen

View file

@ -3,12 +3,12 @@
"name": "Sonos",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/sonos",
"requirements": ["pysonos==0.0.24"],
"requirements": ["pysonos==0.0.25"],
"dependencies": [],
"ssdp": [
{
"st": "urn:schemas-upnp-org:device:ZonePlayer:1"
}
],
"codeowners": []
"codeowners": ["@amelchio"]
}

View file

@ -4,12 +4,12 @@ import datetime
import functools as ft
import logging
import socket
import urllib
import async_timeout
import pysonos
from pysonos import alarms
from pysonos.exceptions import SoCoException, SoCoUPnPException
import pysonos.music_library
import pysonos.snapshot
import voluptuous as vol
@ -338,19 +338,6 @@ def _timespan_secs(timespan):
return sum(60 ** x[0] * int(x[1]) for x in enumerate(reversed(timespan.split(":"))))
def _is_radio_uri(uri):
"""Return whether the URI is a stream (not a playlist)."""
radio_schemes = (
"x-rincon-mp3radio:",
"x-sonosapi-stream:",
"x-sonosapi-radio:",
"x-sonosapi-hls:",
"hls-radio:",
"x-rincon-stream:",
)
return uri.startswith(radio_schemes)
class SonosEntity(MediaPlayerDevice):
"""Representation of a Sonos entity."""
@ -515,17 +502,6 @@ class SonosEntity(MediaPlayerDevice):
# Skip unknown types
_LOGGER.error("Unhandled favorite '%s': %s", fav.title, ex)
def _radio_artwork(self, url):
"""Return the private URL with artwork for a radio stream."""
if url in UNAVAILABLE_VALUES:
return None
if url.find("tts_proxy") > 0:
# If the content is a tts don't try to fetch an image from it.
return None
return f"http://{self.soco.ip_address}:1400/getaa?s=1&u={urllib.parse.quote(url, safe='')}"
def _attach_player(self):
"""Get basic information and add event subscriptions."""
try:
@ -576,6 +552,14 @@ class SonosEntity(MediaPlayerDevice):
self._shuffle = self.soco.shuffle
self._uri = None
self._media_duration = None
self._media_position = None
self._media_position_updated_at = None
self._media_image_url = None
self._media_artist = None
self._media_album_name = None
self._media_title = None
self._source_name = None
update_position = new_status != self._status
self._status = new_status
@ -587,8 +571,11 @@ class SonosEntity(MediaPlayerDevice):
else:
track_info = self.soco.get_current_track_info()
self._uri = track_info["uri"]
self._media_artist = track_info.get("artist")
self._media_album_name = track_info.get("album")
self._media_title = track_info.get("title")
if _is_radio_uri(track_info["uri"]):
if self.soco.is_radio_uri(track_info["uri"]):
variables = event and event.variables
self.update_media_radio(variables, track_info)
else:
@ -604,74 +591,29 @@ class SonosEntity(MediaPlayerDevice):
def update_media_linein(self, source):
"""Update state when playing from line-in/tv."""
self._media_duration = None
self._media_position = None
self._media_position_updated_at = None
self._media_image_url = None
self._media_artist = None
self._media_album_name = None
self._media_title = source
self._source_name = source
def update_media_radio(self, variables, track_info):
"""Update state when streaming radio."""
self._media_duration = None
self._media_position = None
self._media_position_updated_at = None
try:
library = pysonos.music_library.MusicLibrary(self.soco)
album_art_uri = variables["current_track_meta_data"].album_art_uri
self._media_image_url = library.build_album_art_full_uri(album_art_uri)
except (TypeError, KeyError, AttributeError):
pass
media_info = self.soco.avTransport.GetMediaInfo([("InstanceID", 0)])
self._media_image_url = self._radio_artwork(media_info["CurrentURI"])
self._media_artist = track_info.get("artist")
self._media_album_name = None
self._media_title = track_info.get("title")
if self._media_artist and self._media_title:
# artist and album name are in the data, concatenate
# that do display as artist.
# "Information" field in the sonos pc app
self._media_artist = "{artist} - {title}".format(
artist=self._media_artist, title=self._media_title
)
elif variables:
# "On Now" field in the sonos pc app
current_track_metadata = variables.get("current_track_meta_data")
if current_track_metadata:
self._media_artist = current_track_metadata.radio_show.split(",")[0]
# For radio streams we set the radio station name as the title.
current_uri_metadata = media_info["CurrentURIMetaData"]
if current_uri_metadata not in UNAVAILABLE_VALUES:
# currently soco does not have an API for this
current_uri_metadata = pysonos.xml.XML.fromstring(
pysonos.utils.really_utf8(current_uri_metadata)
)
md_title = current_uri_metadata.findtext(
".//{http://purl.org/dc/elements/1.1/}title"
)
if md_title not in UNAVAILABLE_VALUES:
self._media_title = md_title
if self._media_artist and self._media_title:
# some radio stations put their name into the artist
# name, e.g.:
# media_title = "Station"
# media_artist = "Station - Artist - Title"
# detect this case and trim from the front of
# media_artist for cosmetics
trim = f"{self._media_title} - "
chars = min(len(self._media_artist), len(trim))
if self._media_artist[:chars].upper() == trim[:chars].upper():
self._media_artist = self._media_artist[chars:]
# Radios without tagging can have the radio URI as title. Non-playing
# radios will not have a current title. In these cases we try to use
# the radio name instead.
try:
if self.soco.is_radio_uri(self._media_title) or self.state != STATE_PLAYING:
self._media_title = variables["enqueued_transport_uri_meta_data"].title
except (TypeError, KeyError, AttributeError):
pass
# Check if currently playing radio station is in favorites
self._source_name = None
media_info = self.soco.avTransport.GetMediaInfo([("InstanceID", 0)])
for fav in self._favorites:
if fav.reference.get_uri() == media_info["CurrentURI"]:
self._source_name = fav.title
@ -710,12 +652,6 @@ class SonosEntity(MediaPlayerDevice):
self._media_image_url = track_info.get("album_art")
self._media_artist = track_info.get("artist")
self._media_album_name = track_info.get("album")
self._media_title = track_info.get("title")
self._source_name = None
def update_volume(self, event=None):
"""Update information about currently volume settings."""
if event:
@ -936,7 +872,7 @@ class SonosEntity(MediaPlayerDevice):
if len(fav) == 1:
src = fav.pop()
uri = src.reference.get_uri()
if _is_radio_uri(uri):
if self.soco.is_radio_uri(uri):
self.soco.play_uri(uri, title=source)
else:
self.soco.clear_queue()

View file

@ -1543,7 +1543,7 @@ pysnmp==4.4.12
pysoma==0.0.10
# homeassistant.components.sonos
pysonos==0.0.24
pysonos==0.0.25
# homeassistant.components.spc
pyspcwebgw==0.4.0

View file

@ -583,7 +583,7 @@ pysmartthings==0.7.0
pysoma==0.0.10
# homeassistant.components.sonos
pysonos==0.0.24
pysonos==0.0.25
# homeassistant.components.spc
pyspcwebgw==0.4.0