Add volume and seek control to gpmdp (#2953)

This commit is contained in:
Nolan Gilley 2016-08-24 02:32:00 -04:00 committed by Paulus Schoutsen
parent 52acb2e6f0
commit 61ef2683c5

View File

@ -11,17 +11,22 @@ import socket
from homeassistant.components.media_player import ( from homeassistant.components.media_player import (
MEDIA_TYPE_MUSIC, SUPPORT_NEXT_TRACK, SUPPORT_PREVIOUS_TRACK, MEDIA_TYPE_MUSIC, SUPPORT_NEXT_TRACK, SUPPORT_PREVIOUS_TRACK,
SUPPORT_PAUSE, MediaPlayerDevice) SUPPORT_PAUSE, SUPPORT_VOLUME_SET, SUPPORT_SEEK, MediaPlayerDevice)
from homeassistant.const import ( from homeassistant.const import (
STATE_PLAYING, STATE_PAUSED, STATE_OFF) STATE_PLAYING, STATE_PAUSED, STATE_OFF)
from homeassistant.loader import get_component from homeassistant.loader import get_component
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['websocket-client==0.37.0'] REQUIREMENTS = ['websocket-client==0.37.0']
SUPPORT_GPMDP = SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK SUPPORT_GPMDP = SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \
SUPPORT_SEEK | SUPPORT_VOLUME_SET
GPMDP_CONFIG_FILE = 'gpmpd.conf' GPMDP_CONFIG_FILE = 'gpmpd.conf'
_CONFIGURING = {} _CONFIGURING = {}
PLAYBACK_DICT = {'0': STATE_PAUSED, # Stopped
'1': STATE_PAUSED,
'2': STATE_PLAYING}
def request_configuration(hass, config, url, add_devices_callback): def request_configuration(hass, config, url, add_devices_callback):
"""Request configuration steps from the user.""" """Request configuration steps from the user."""
@ -162,6 +167,7 @@ class GPMDP(MediaPlayerDevice):
self._albumart = None self._albumart = None
self._seek_position = None self._seek_position = None
self._duration = None self._duration = None
self._volume = None
self._request_id = 0 self._request_id = 0
self.update() self.update()
@ -180,7 +186,7 @@ class GPMDP(MediaPlayerDevice):
self._ws = None self._ws = None
return self._ws return self._ws
def send_msg_with_req_id(self, method): def send_gpmdp_msg(self, namespace, method, with_id=True):
"""Send ws messages to GPMDP and verify request id in response.""" """Send ws messages to GPMDP and verify request id in response."""
from websocket import _exceptions from websocket import _exceptions
try: try:
@ -188,38 +194,42 @@ class GPMDP(MediaPlayerDevice):
if websocket is None: if websocket is None:
self._status = STATE_OFF self._status = STATE_OFF
return return
else: self._request_id += 1
self._request_id += 1 websocket.send(json.dumps({'namespace': namespace,
websocket.send(json.dumps({'namespace': 'playback', 'method': method,
'method': method, 'requestID': self._request_id}))
'requestID': self._request_id})) if not with_id:
while True: return
msg = json.loads(websocket.recv()) while True:
if 'requestID' in msg: msg = json.loads(websocket.recv())
if msg['requestID'] == self._request_id: if 'requestID' in msg:
return msg if msg['requestID'] == self._request_id:
except (_exceptions.WebSocketTimeoutException, return msg
except (ConnectionRefusedError, ConnectionResetError,
_exceptions.WebSocketTimeoutException,
_exceptions.WebSocketProtocolException, _exceptions.WebSocketProtocolException,
_exceptions.WebSocketPayloadException): _exceptions.WebSocketPayloadException,
return _exceptions.WebSocketConnectionClosedException):
self._ws = None
def update(self): def update(self):
"""Get the latest details from the player.""" """Get the latest details from the player."""
playstate = self.send_msg_with_req_id('isPlaying') playstate = self.send_gpmdp_msg('playback', 'getPlaybackState')
if playstate is None: if playstate is None:
return return
self._status = STATE_PLAYING if playstate['value'] else STATE_PAUSED self._status = PLAYBACK_DICT[str(playstate['value'])]
time_data = self.send_msg_with_req_id('getCurrentTime') time_data = self.send_gpmdp_msg('playback', 'getCurrentTime')
if time_data is None: if time_data is not None:
return self._seek_position = int(time_data['value'] / 1000)
self._seek_position = int(time_data['value'] / 1000) track_data = self.send_gpmdp_msg('playback', 'getCurrentTrack')
track_data = self.send_msg_with_req_id('getCurrentTrack') if track_data is not None:
if track_data is None: self._title = track_data['value']['title']
return self._artist = track_data['value']['artist']
self._title = track_data['value']['title'] self._albumart = track_data['value']['albumArt']
self._artist = track_data['value']['artist'] self._duration = int(track_data['value']['duration'] / 1000)
self._albumart = track_data['value']['albumArt'] volume_data = self.send_gpmdp_msg('volume', 'getVolume')
self._duration = int(track_data['value']['duration'] / 1000) if volume_data is not None:
self._volume = volume_data['value'] / 100
@property @property
def media_content_type(self): def media_content_type(self):
@ -256,6 +266,11 @@ class GPMDP(MediaPlayerDevice):
"""Time in seconds of current song duration.""" """Time in seconds of current song duration."""
return self._duration return self._duration
@property
def volume_level(self):
"""Volume level of the media player (0..1)."""
return self._volume
@property @property
def name(self): def name(self):
"""Return the name of the device.""" """Return the name of the device."""
@ -268,32 +283,56 @@ class GPMDP(MediaPlayerDevice):
def media_next_track(self): def media_next_track(self):
"""Send media_next command to media player.""" """Send media_next command to media player."""
websocket = self.get_ws() self.send_gpmdp_msg('playback', 'forward', False)
if websocket is None:
return
websocket.send('{"namespace": "playback", "method": "forward"}')
def media_previous_track(self): def media_previous_track(self):
"""Send media_previous command to media player.""" """Send media_previous command to media player."""
websocket = self.get_ws() self.send_gpmdp_msg('playback', 'rewind', False)
if websocket is None:
return
websocket.send('{"namespace": "playback", "method": "rewind"}')
def media_play(self): def media_play(self):
"""Send media_play command to media player.""" """Send media_play command to media player."""
websocket = self.get_ws() self.send_gpmdp_msg('playback', 'playPause', False)
if websocket is None:
return
websocket.send('{"namespace": "playback", "method": "playPause"}')
self._status = STATE_PLAYING self._status = STATE_PLAYING
self.update_ha_state() self.update_ha_state()
def media_pause(self): def media_pause(self):
"""Send media_pause command to media player.""" """Send media_pause command to media player."""
self.send_gpmdp_msg('playback', 'playPause', False)
self._status = STATE_PAUSED
self.update_ha_state()
def media_seek(self, position):
"""Send media_seek command to media player."""
websocket = self.get_ws() websocket = self.get_ws()
if websocket is None: if websocket is None:
return return
websocket.send('{"namespace": "playback", "method": "playPause"}') websocket.send(json.dumps({"namespace": "playback",
self._status = STATE_PAUSED "method": "setCurrentTime",
"arguments": [position*1000]}))
self.update_ha_state()
def volume_up(self):
"""Send volume_up command to media player."""
websocket = self.get_ws()
if websocket is None:
return
websocket.send('{"namespace": "volume", "method": "increaseVolume"}')
self.update_ha_state()
def volume_down(self):
"""Send volume_down command to media player."""
websocket = self.get_ws()
if websocket is None:
return
websocket.send('{"namespace": "volume", "method": "decreaseVolume"}')
self.update_ha_state()
def set_volume_level(self, volume):
"""Set volume on media player, range(0..1)."""
websocket = self.get_ws()
if websocket is None:
return
websocket.send(json.dumps({"namespace": "volume",
"method": "setVolume",
"arguments": [volume*100]}))
self.update_ha_state() self.update_ha_state()