mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Support for media_position property on media_player (#4172)
* Added support for media_position property to media_player + implementation for sonos. * Pla yback progress now updates without needed state transitions in HA. * Linting fixes * media_position_update_at property is now a datetime. * Minor fix. * Linting fixes.
This commit is contained in:
parent
d4bc8e23af
commit
92c6cee2a1
@ -59,6 +59,8 @@ ATTR_MEDIA_SEEK_POSITION = 'seek_position'
|
|||||||
ATTR_MEDIA_CONTENT_ID = 'media_content_id'
|
ATTR_MEDIA_CONTENT_ID = 'media_content_id'
|
||||||
ATTR_MEDIA_CONTENT_TYPE = 'media_content_type'
|
ATTR_MEDIA_CONTENT_TYPE = 'media_content_type'
|
||||||
ATTR_MEDIA_DURATION = 'media_duration'
|
ATTR_MEDIA_DURATION = 'media_duration'
|
||||||
|
ATTR_MEDIA_POSITION = 'media_position'
|
||||||
|
ATTR_MEDIA_POSITION_UPDATED_AT = 'media_position_updated_at'
|
||||||
ATTR_MEDIA_TITLE = 'media_title'
|
ATTR_MEDIA_TITLE = 'media_title'
|
||||||
ATTR_MEDIA_ARTIST = 'media_artist'
|
ATTR_MEDIA_ARTIST = 'media_artist'
|
||||||
ATTR_MEDIA_ALBUM_NAME = 'media_album_name'
|
ATTR_MEDIA_ALBUM_NAME = 'media_album_name'
|
||||||
@ -120,6 +122,8 @@ ATTR_TO_PROPERTY = [
|
|||||||
ATTR_MEDIA_CONTENT_ID,
|
ATTR_MEDIA_CONTENT_ID,
|
||||||
ATTR_MEDIA_CONTENT_TYPE,
|
ATTR_MEDIA_CONTENT_TYPE,
|
||||||
ATTR_MEDIA_DURATION,
|
ATTR_MEDIA_DURATION,
|
||||||
|
ATTR_MEDIA_POSITION,
|
||||||
|
ATTR_MEDIA_POSITION_UPDATED_AT,
|
||||||
ATTR_MEDIA_TITLE,
|
ATTR_MEDIA_TITLE,
|
||||||
ATTR_MEDIA_ARTIST,
|
ATTR_MEDIA_ARTIST,
|
||||||
ATTR_MEDIA_ALBUM_NAME,
|
ATTR_MEDIA_ALBUM_NAME,
|
||||||
@ -447,6 +451,19 @@ class MediaPlayerDevice(Entity):
|
|||||||
"""Duration of current playing media in seconds."""
|
"""Duration of current playing media in seconds."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_position(self):
|
||||||
|
"""Position of current playing media in seconds."""
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_position_updated_at(self):
|
||||||
|
"""When was the position of the current playing media valid.
|
||||||
|
|
||||||
|
Returns value from homeassistant.util.dt.utcnow().
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_image_url(self):
|
def media_image_url(self):
|
||||||
"""Image url of current playing media."""
|
"""Image url of current playing media."""
|
||||||
|
@ -20,6 +20,7 @@ from homeassistant.const import (
|
|||||||
STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_OFF, ATTR_ENTITY_ID)
|
STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_OFF, ATTR_ENTITY_ID)
|
||||||
from homeassistant.config import load_yaml_config_file
|
from homeassistant.config import load_yaml_config_file
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.util.dt import utcnow
|
||||||
|
|
||||||
REQUIREMENTS = ['SoCo==0.12']
|
REQUIREMENTS = ['SoCo==0.12']
|
||||||
|
|
||||||
@ -264,6 +265,8 @@ class SonosDevice(MediaPlayerDevice):
|
|||||||
self._coordinator = None
|
self._coordinator = None
|
||||||
self._media_content_id = None
|
self._media_content_id = None
|
||||||
self._media_duration = None
|
self._media_duration = None
|
||||||
|
self._media_position = None
|
||||||
|
self._media_position_updated_at = None
|
||||||
self._media_image_url = None
|
self._media_image_url = None
|
||||||
self._media_artist = None
|
self._media_artist = None
|
||||||
self._media_album_name = None
|
self._media_album_name = None
|
||||||
@ -404,6 +407,9 @@ class SonosDevice(MediaPlayerDevice):
|
|||||||
media_album_name = track_info.get('album')
|
media_album_name = track_info.get('album')
|
||||||
media_title = track_info.get('title')
|
media_title = track_info.get('title')
|
||||||
|
|
||||||
|
media_position = None
|
||||||
|
media_position_updated_at = None
|
||||||
|
|
||||||
is_radio_stream = \
|
is_radio_stream = \
|
||||||
current_media_uri.startswith('x-sonosapi-stream:') or \
|
current_media_uri.startswith('x-sonosapi-stream:') or \
|
||||||
current_media_uri.startswith('x-rincon-mp3radio:')
|
current_media_uri.startswith('x-rincon-mp3radio:')
|
||||||
@ -425,7 +431,6 @@ class SonosDevice(MediaPlayerDevice):
|
|||||||
media_image_url = None
|
media_image_url = None
|
||||||
|
|
||||||
elif is_radio_stream:
|
elif is_radio_stream:
|
||||||
is_radio_stream = True
|
|
||||||
media_image_url = self._format_media_image_url(
|
media_image_url = self._format_media_image_url(
|
||||||
current_media_uri
|
current_media_uri
|
||||||
)
|
)
|
||||||
@ -489,6 +494,46 @@ class SonosDevice(MediaPlayerDevice):
|
|||||||
support_next_track = True
|
support_next_track = True
|
||||||
support_pause = True
|
support_pause = True
|
||||||
|
|
||||||
|
position_info = self._player.avTransport.GetPositionInfo(
|
||||||
|
[('InstanceID', 0),
|
||||||
|
('Channel', 'Master')]
|
||||||
|
)
|
||||||
|
rel_time = _parse_timespan(
|
||||||
|
position_info.get("RelTime")
|
||||||
|
)
|
||||||
|
|
||||||
|
# player no longer reports position?
|
||||||
|
update_media_position = rel_time is None and \
|
||||||
|
self._media_position is not None
|
||||||
|
|
||||||
|
# player started reporting position?
|
||||||
|
update_media_position |= rel_time is not None and \
|
||||||
|
self._media_position is None
|
||||||
|
|
||||||
|
# position changed?
|
||||||
|
if rel_time is not None and \
|
||||||
|
self._media_position is not None:
|
||||||
|
|
||||||
|
time_diff = utcnow() - self._media_position_updated_at
|
||||||
|
time_diff = time_diff.total_seconds()
|
||||||
|
|
||||||
|
calculated_position = \
|
||||||
|
self._media_position + \
|
||||||
|
time_diff
|
||||||
|
|
||||||
|
update_media_position = \
|
||||||
|
abs(calculated_position - rel_time) > 1.5
|
||||||
|
|
||||||
|
if update_media_position:
|
||||||
|
media_position = rel_time
|
||||||
|
media_position_updated_at = utcnow()
|
||||||
|
else:
|
||||||
|
# don't update media_position (don't want unneeded
|
||||||
|
# state transitions)
|
||||||
|
media_position = self._media_position
|
||||||
|
media_position_updated_at = \
|
||||||
|
self._media_position_updated_at
|
||||||
|
|
||||||
playlist_position = track_info.get('playlist_position')
|
playlist_position = track_info.get('playlist_position')
|
||||||
if playlist_position in ('', 'NOT_IMPLEMENTED', None):
|
if playlist_position in ('', 'NOT_IMPLEMENTED', None):
|
||||||
playlist_position = None
|
playlist_position = None
|
||||||
@ -514,6 +559,8 @@ class SonosDevice(MediaPlayerDevice):
|
|||||||
self._media_duration = _parse_timespan(
|
self._media_duration = _parse_timespan(
|
||||||
track_info.get('duration')
|
track_info.get('duration')
|
||||||
)
|
)
|
||||||
|
self._media_position = media_position
|
||||||
|
self._media_position_updated_at = media_position_updated_at
|
||||||
self._media_image_url = media_image_url
|
self._media_image_url = media_image_url
|
||||||
self._media_artist = media_artist
|
self._media_artist = media_artist
|
||||||
self._media_album_name = media_album_name
|
self._media_album_name = media_album_name
|
||||||
@ -541,6 +588,8 @@ class SonosDevice(MediaPlayerDevice):
|
|||||||
self._coordinator = None
|
self._coordinator = None
|
||||||
self._media_content_id = None
|
self._media_content_id = None
|
||||||
self._media_duration = None
|
self._media_duration = None
|
||||||
|
self._media_position = None
|
||||||
|
self._media_position_updated_at = None
|
||||||
self._media_image_url = None
|
self._media_image_url = None
|
||||||
self._media_artist = None
|
self._media_artist = None
|
||||||
self._media_album_name = None
|
self._media_album_name = None
|
||||||
@ -642,6 +691,25 @@ class SonosDevice(MediaPlayerDevice):
|
|||||||
else:
|
else:
|
||||||
return self._media_duration
|
return self._media_duration
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_position(self):
|
||||||
|
"""Position of current playing media in seconds."""
|
||||||
|
if self._coordinator:
|
||||||
|
return self._coordinator.media_position
|
||||||
|
else:
|
||||||
|
return self._media_position
|
||||||
|
|
||||||
|
@property
|
||||||
|
def media_position_updated_at(self):
|
||||||
|
"""When was the position of the current playing media valid.
|
||||||
|
|
||||||
|
Returns value from homeassistant.util.dt.utcnow().
|
||||||
|
"""
|
||||||
|
if self._coordinator:
|
||||||
|
return self._coordinator.media_position_updated_at
|
||||||
|
else:
|
||||||
|
return self._media_position_updated_at
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_image_url(self):
|
def media_image_url(self):
|
||||||
"""Image url of current playing media."""
|
"""Image url of current playing media."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user