diff --git a/homeassistant/components/media_player/gpmdp.py b/homeassistant/components/media_player/gpmdp.py index 85f697cb1e7..4fcdff872e2 100644 --- a/homeassistant/components/media_player/gpmdp.py +++ b/homeassistant/components/media_player/gpmdp.py @@ -11,17 +11,22 @@ import socket from homeassistant.components.media_player import ( MEDIA_TYPE_MUSIC, SUPPORT_NEXT_TRACK, SUPPORT_PREVIOUS_TRACK, - SUPPORT_PAUSE, MediaPlayerDevice) + SUPPORT_PAUSE, SUPPORT_VOLUME_SET, SUPPORT_SEEK, MediaPlayerDevice) from homeassistant.const import ( STATE_PLAYING, STATE_PAUSED, STATE_OFF) from homeassistant.loader import get_component _LOGGER = logging.getLogger(__name__) 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' _CONFIGURING = {} +PLAYBACK_DICT = {'0': STATE_PAUSED, # Stopped + '1': STATE_PAUSED, + '2': STATE_PLAYING} + def request_configuration(hass, config, url, add_devices_callback): """Request configuration steps from the user.""" @@ -162,6 +167,7 @@ class GPMDP(MediaPlayerDevice): self._albumart = None self._seek_position = None self._duration = None + self._volume = None self._request_id = 0 self.update() @@ -180,7 +186,7 @@ class GPMDP(MediaPlayerDevice): self._ws = None 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.""" from websocket import _exceptions try: @@ -188,38 +194,42 @@ class GPMDP(MediaPlayerDevice): if websocket is None: self._status = STATE_OFF return - else: - self._request_id += 1 - websocket.send(json.dumps({'namespace': 'playback', - 'method': method, - 'requestID': self._request_id})) - while True: - msg = json.loads(websocket.recv()) - if 'requestID' in msg: - if msg['requestID'] == self._request_id: - return msg - except (_exceptions.WebSocketTimeoutException, + self._request_id += 1 + websocket.send(json.dumps({'namespace': namespace, + 'method': method, + 'requestID': self._request_id})) + if not with_id: + return + while True: + msg = json.loads(websocket.recv()) + if 'requestID' in msg: + if msg['requestID'] == self._request_id: + return msg + except (ConnectionRefusedError, ConnectionResetError, + _exceptions.WebSocketTimeoutException, _exceptions.WebSocketProtocolException, - _exceptions.WebSocketPayloadException): - return + _exceptions.WebSocketPayloadException, + _exceptions.WebSocketConnectionClosedException): + self._ws = None def update(self): """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: return - self._status = STATE_PLAYING if playstate['value'] else STATE_PAUSED - time_data = self.send_msg_with_req_id('getCurrentTime') - if time_data is None: - return - self._seek_position = int(time_data['value'] / 1000) - track_data = self.send_msg_with_req_id('getCurrentTrack') - if track_data is None: - return - self._title = track_data['value']['title'] - self._artist = track_data['value']['artist'] - self._albumart = track_data['value']['albumArt'] - self._duration = int(track_data['value']['duration'] / 1000) + self._status = PLAYBACK_DICT[str(playstate['value'])] + time_data = self.send_gpmdp_msg('playback', 'getCurrentTime') + if time_data is not None: + self._seek_position = int(time_data['value'] / 1000) + track_data = self.send_gpmdp_msg('playback', 'getCurrentTrack') + if track_data is not None: + self._title = track_data['value']['title'] + self._artist = track_data['value']['artist'] + self._albumart = track_data['value']['albumArt'] + self._duration = int(track_data['value']['duration'] / 1000) + volume_data = self.send_gpmdp_msg('volume', 'getVolume') + if volume_data is not None: + self._volume = volume_data['value'] / 100 @property def media_content_type(self): @@ -256,6 +266,11 @@ class GPMDP(MediaPlayerDevice): """Time in seconds of current song duration.""" return self._duration + @property + def volume_level(self): + """Volume level of the media player (0..1).""" + return self._volume + @property def name(self): """Return the name of the device.""" @@ -268,32 +283,56 @@ class GPMDP(MediaPlayerDevice): def media_next_track(self): """Send media_next command to media player.""" - websocket = self.get_ws() - if websocket is None: - return - websocket.send('{"namespace": "playback", "method": "forward"}') + self.send_gpmdp_msg('playback', 'forward', False) def media_previous_track(self): """Send media_previous command to media player.""" - websocket = self.get_ws() - if websocket is None: - return - websocket.send('{"namespace": "playback", "method": "rewind"}') + self.send_gpmdp_msg('playback', 'rewind', False) def media_play(self): """Send media_play command to media player.""" - websocket = self.get_ws() - if websocket is None: - return - websocket.send('{"namespace": "playback", "method": "playPause"}') + self.send_gpmdp_msg('playback', 'playPause', False) self._status = STATE_PLAYING self.update_ha_state() def media_pause(self): """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() if websocket is None: return - websocket.send('{"namespace": "playback", "method": "playPause"}') - self._status = STATE_PAUSED + websocket.send(json.dumps({"namespace": "playback", + "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()