From 429bf2c1434e4335eb7d58f4253cb85d4f9d46c2 Mon Sep 17 00:00:00 2001 From: Rowan Date: Sat, 14 May 2016 21:28:42 +0100 Subject: [PATCH] Google Play Music Desktop Player component (#1788) * Added GPM Desktop Plaeyr component * Updated requirements_all.txt * Pylint fix * Updated GPMDP.py to include @balloob's comments * Updated to work with the latest version of GPMDP * Removed setting "self._ws.recv()" as a variable * Made line 52 shorter * Updated to check weather it is connected or not * Pylint and @balloob fixes * Updated with simplified code and pylint fix * Made `json.loads` shorter * Pylint fix --- .coveragerc | 1 + .../components/media_player/gpmdp.py | 158 ++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 162 insertions(+) create mode 100644 homeassistant/components/media_player/gpmdp.py diff --git a/.coveragerc b/.coveragerc index 02752a9a361..1ba134b63ff 100644 --- a/.coveragerc +++ b/.coveragerc @@ -114,6 +114,7 @@ omit = homeassistant/components/media_player/cast.py homeassistant/components/media_player/denon.py homeassistant/components/media_player/firetv.py + homeassistant/components/media_player/gpmdp.py homeassistant/components/media_player/itunes.py homeassistant/components/media_player/kodi.py homeassistant/components/media_player/mpd.py diff --git a/homeassistant/components/media_player/gpmdp.py b/homeassistant/components/media_player/gpmdp.py new file mode 100644 index 00000000000..e478cc6e2a5 --- /dev/null +++ b/homeassistant/components/media_player/gpmdp.py @@ -0,0 +1,158 @@ +""" +Support for Google Play Music Desktop Player. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/media_player.gpm_dp/ +""" +import logging +import json +import socket + +from homeassistant.components.media_player import ( + MEDIA_TYPE_MUSIC, SUPPORT_NEXT_TRACK, SUPPORT_PREVIOUS_TRACK, + SUPPORT_PAUSE, MediaPlayerDevice) +from homeassistant.const import ( + STATE_PLAYING, STATE_PAUSED, STATE_OFF) + +_LOGGER = logging.getLogger(__name__) +REQUIREMENTS = ['websocket-client==0.35.0'] +SUPPORT_GPMDP = SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the GPMDP platform.""" + from websocket import create_connection + + name = config.get("name", "GPM Desktop Player") + address = config.get("address") + + if address is None: + _LOGGER.error("Missing address in config") + return False + + add_devices([GPMDP(name, address, create_connection)]) + + +class GPMDP(MediaPlayerDevice): + """Representation of a GPMDP.""" + + # pylint: disable=too-many-public-methods, abstract-method + # pylint: disable=too-many-instance-attributes + def __init__(self, name, address, create_connection): + """Initialize.""" + self._connection = create_connection + self._address = address + self._name = name + self._status = STATE_OFF + self._ws = None + self._title = None + self._artist = None + self._albumart = None + self.update() + + def get_ws(self): + """Check if the websocket is setup and connected.""" + if self._ws is None: + try: + self._ws = self._connection(("ws://" + self._address + + ":5672"), timeout=1) + except (socket.timeout, ConnectionRefusedError, + ConnectionResetError): + self._ws = None + elif self._ws.connected is True: + self._ws.close() + try: + self._ws = self._connection(("ws://" + self._address + + ":5672"), timeout=1) + except (socket.timeout, ConnectionRefusedError, + ConnectionResetError): + self._ws = None + return self._ws + + def update(self): + """Get the latest details from the player.""" + websocket = self.get_ws() + if websocket is None: + self._status = STATE_OFF + return + else: + state = websocket.recv() + state = ((json.loads(state))['payload']) + if state is True: + websocket.recv() + websocket.recv() + song = websocket.recv() + song = json.loads(song) + self._title = (song['payload']['title']) + self._artist = (song['payload']['artist']) + self._albumart = (song['payload']['albumArt']) + self._status = STATE_PLAYING + elif state is False: + self._status = STATE_PAUSED + + @property + def media_content_type(self): + """Content type of current playing media.""" + return MEDIA_TYPE_MUSIC + + @property + def state(self): + """Return the state of the device.""" + return self._status + + @property + def media_title(self): + """Title of current playing media.""" + return self._title + + @property + def media_artist(self): + """Artist of current playing media (Music track only).""" + return self._artist + + @property + def media_image_url(self): + """Image url of current playing media.""" + return self._albumart + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def supported_media_commands(self): + """Flag of media commands that are supported.""" + return SUPPORT_GPMDP + + 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"}') + + 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"}') + + 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._status = STATE_PAUSED + self.update_ha_state() + + def media_pause(self): + """Send media_pause command to media player.""" + websocket = self.get_ws() + if websocket is None: + return + websocket.send('{"namespace": "playback", "method": "playPause"}') + self._status = STATE_PAUSED + self.update_ha_state() diff --git a/requirements_all.txt b/requirements_all.txt index 1084da242b2..75830e79a53 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -347,6 +347,9 @@ vsure==0.8.1 # homeassistant.components.switch.wake_on_lan wakeonlan==0.2.2 +# homeassistant.components.media_player.gpmdp +websocket-client==0.35.0 + # homeassistant.components.zigbee xbee-helper==0.0.7