From 3e01ce2a6ce1b12432b8e81004981a9373856f42 Mon Sep 17 00:00:00 2001 From: Hans Bakker Date: Fri, 29 May 2015 22:19:42 +0200 Subject: [PATCH 1/3] Proposed fixes to chromecast component --- .../components/media_player/__init__.py | 1 + homeassistant/components/media_player/cast.py | 100 +++++++++--------- requirements.txt | 2 +- 3 files changed, 53 insertions(+), 50 deletions(-) diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 00fee802397..ddfc2f49153 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -41,6 +41,7 @@ ATTR_MEDIA_DURATION = 'media_duration' MEDIA_STATE_UNKNOWN = 'unknown' MEDIA_STATE_PLAYING = 'playing' +MEDIA_STATE_PAUSED = 'paused' MEDIA_STATE_STOPPED = 'stopped' diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 32b86e4b90b..7df349c0d57 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -10,6 +10,7 @@ import logging try: import pychromecast + import pychromecast.controllers.youtube as youtube except ImportError: # We will throw error later pass @@ -18,7 +19,7 @@ from homeassistant.components.media_player import ( MediaPlayerDevice, STATE_NO_APP, ATTR_MEDIA_STATE, ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_TITLE, ATTR_MEDIA_ARTIST, ATTR_MEDIA_ALBUM, ATTR_MEDIA_IMAGE_URL, ATTR_MEDIA_DURATION, - ATTR_MEDIA_VOLUME, MEDIA_STATE_PLAYING, MEDIA_STATE_STOPPED) + ATTR_MEDIA_VOLUME, MEDIA_STATE_PLAYING, MEDIA_STATE_PAUSED, MEDIA_STATE_STOPPED) # pylint: disable=unused-argument @@ -57,7 +58,9 @@ class CastDevice(MediaPlayerDevice): """ Represents a Cast device on the network. """ def __init__(self, host): - self.cast = pychromecast.PyChromecast(host) + self.cast = pychromecast.Chromecast(host) + self.youtube = youtube.YouTubeController() + self.cast.register_handler(self.youtube) @property def name(self): @@ -67,45 +70,52 @@ class CastDevice(MediaPlayerDevice): @property def state(self): """ Returns the state of the device. """ - status = self.cast.app + status = self.cast.status - if status is None or status.app_id == pychromecast.APP_ID['HOME']: - return STATE_NO_APP + if self.cast.app_display_name: + return self.cast.app_display_name else: - return status.description + return STATE_NO_APP @property def state_attributes(self): """ Returns the state attributes. """ - ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) + mc = self.cast.media_controller; - if ramp and ramp.state != pychromecast.RAMP_STATE_UNKNOWN: + if mc: state_attr = {} - if ramp.state == pychromecast.RAMP_STATE_PLAYING: + if mc.is_playing: state_attr[ATTR_MEDIA_STATE] = MEDIA_STATE_PLAYING - else: + elif mc.is_paused: + state_attr[ATTR_MEDIA_STATE] = MEDIA_STATE_PAUSED + elif mc.is_idle: state_attr[ATTR_MEDIA_STATE] = MEDIA_STATE_STOPPED - if ramp.content_id: - state_attr[ATTR_MEDIA_CONTENT_ID] = ramp.content_id + media_status = self.cast.status - if ramp.title: - state_attr[ATTR_MEDIA_TITLE] = ramp.title + if media_status: - if ramp.artist: - state_attr[ATTR_MEDIA_ARTIST] = ramp.artist + """ These status properties seem not to be present anymore in pychromecast """ + #if ramp.content_id: + # state_attr[ATTR_MEDIA_CONTENT_ID] = mc.ramp.content_id - if ramp.album: - state_attr[ATTR_MEDIA_ALBUM] = ramp.album + #if ramp.title: + # state_attr[ATTR_MEDIA_TITLE] = ramp.title - if ramp.image_url: - state_attr[ATTR_MEDIA_IMAGE_URL] = ramp.image_url + #if ramp.artist: + # state_attr[ATTR_MEDIA_ARTIST] = ramp.artist - if ramp.duration: - state_attr[ATTR_MEDIA_DURATION] = ramp.duration + #if ramp.album: + # state_attr[ATTR_MEDIA_ALBUM] = ramp.album - state_attr[ATTR_MEDIA_VOLUME] = ramp.volume + #if ramp.image_url: + # state_attr[ATTR_MEDIA_IMAGE_URL] = ramp.image_url + + if hasattr(media_status, 'duration'): + state_attr[ATTR_MEDIA_DURATION] = media_status.duration + + state_attr[ATTR_MEDIA_VOLUME] = media_status.volume_level return state_attr @@ -117,46 +127,38 @@ class CastDevice(MediaPlayerDevice): def volume_up(self): """ Service to send the chromecast the command for volume up. """ - ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) - - if ramp: - ramp.volume_up() + self.cast.volume_up() def volume_down(self): """ Service to send the chromecast the command for volume down. """ - ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) - - if ramp: - ramp.volume_down() + self.cast.volume_down() def media_play_pause(self): """ Service to send the chromecast the command for play/pause. """ - ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) - - if ramp: - ramp.playpause() + media_state = self.state_attributes[ATTR_MEDIA_STATE] + if media_state == MEDIA_STATE_STOPPED or media_state == MEDIA_STATE_PAUSED: + self.media_pause() + elif media_state == MEDIA_STATE_PLAYING: + self.media_play() def media_play(self): """ Service to send the chromecast the command for play/pause. """ - ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) - - if ramp and ramp.state == pychromecast.RAMP_STATE_STOPPED: - ramp.playpause() + if self.state_attributes[ATTR_MEDIA_STATE] == MEDIA_STATE_STOPPED: + self.media_play_pause() def media_pause(self): """ Service to send the chromecast the command for play/pause. """ - ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) + if self.state_attributes[ATTR_MEDIA_STATE] == MEDIA_STATE_PLAYING: + self.media_play_pause() - if ramp and ramp.state == pychromecast.RAMP_STATE_PLAYING: - ramp.playpause() + """ This one seems not to be present anymore in pychromecast, needs porting or cleanup """ + #def media_next_track(self): + # """ Service to send the chromecast the command for next track. """ + # ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) - def media_next_track(self): - """ Service to send the chromecast the command for next track. """ - ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) - - if ramp: - ramp.next() + # if ramp: + # ramp.next() def play_youtube_video(self, video_id): """ Plays specified video_id on the Chromecast's YouTube channel. """ - pychromecast.play_youtube_video(video_id, self.cast.host) + self.youtube.play_video(video_id) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 63e3f3d5022..6d2e032af45 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ phue>=0.8 ledcontroller>=1.0.7 # media_player.cast -pychromecast>=0.5 +pychromecast>=0.6 # keyboard pyuserinput>=0.1.9 From ac8a2d03d8313bab4096fb4b8cd301397d30938a Mon Sep 17 00:00:00 2001 From: Hans Bakker Date: Fri, 29 May 2015 22:31:52 +0200 Subject: [PATCH 2/3] Fix play_pause command --- homeassistant/components/media_player/cast.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 7df349c0d57..d5f81646ea3 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -137,9 +137,9 @@ class CastDevice(MediaPlayerDevice): """ Service to send the chromecast the command for play/pause. """ media_state = self.state_attributes[ATTR_MEDIA_STATE] if media_state == MEDIA_STATE_STOPPED or media_state == MEDIA_STATE_PAUSED: - self.media_pause() + self.cast.media_controller.play() elif media_state == MEDIA_STATE_PLAYING: - self.media_play() + self.cast.media_controller.pause() def media_play(self): """ Service to send the chromecast the command for play/pause. """ From b50216600baa7e0516ed3254b37d7b8ba1bcf5f3 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 29 May 2015 22:36:40 -0700 Subject: [PATCH 3/3] Update cast integration --- homeassistant/components/media_player/cast.py | 100 ++++++++---------- 1 file changed, 44 insertions(+), 56 deletions(-) diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index d5f81646ea3..35d9748c663 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -15,11 +15,13 @@ except ImportError: # We will throw error later pass +# ATTR_MEDIA_ALBUM, ATTR_MEDIA_IMAGE_URL, +# ATTR_MEDIA_TITLE, ATTR_MEDIA_ARTIST, from homeassistant.components.media_player import ( MediaPlayerDevice, STATE_NO_APP, ATTR_MEDIA_STATE, - ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_TITLE, ATTR_MEDIA_ARTIST, - ATTR_MEDIA_ALBUM, ATTR_MEDIA_IMAGE_URL, ATTR_MEDIA_DURATION, - ATTR_MEDIA_VOLUME, MEDIA_STATE_PLAYING, MEDIA_STATE_PAUSED, MEDIA_STATE_STOPPED) + ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_DURATION, ATTR_MEDIA_VOLUME, + MEDIA_STATE_PLAYING, MEDIA_STATE_PAUSED, MEDIA_STATE_STOPPED, + MEDIA_STATE_UNKNOWN) # pylint: disable=unused-argument @@ -70,54 +72,47 @@ class CastDevice(MediaPlayerDevice): @property def state(self): """ Returns the state of the device. """ - status = self.cast.status - - if self.cast.app_display_name: - return self.cast.app_display_name - else: + if self.cast.is_idle: return STATE_NO_APP + else: + return self.cast.app_display_name + + @property + def media_state(self): + """ Returns the media state. """ + media_controller = self.cast.media_controller + + if media_controller.is_playing: + return MEDIA_STATE_PLAYING + elif media_controller.is_paused: + return MEDIA_STATE_PAUSED + elif media_controller.is_idle: + return MEDIA_STATE_STOPPED + else: + return MEDIA_STATE_UNKNOWN @property def state_attributes(self): """ Returns the state attributes. """ - mc = self.cast.media_controller; + cast_status = self.cast.status + media_status = self.cast.media_status - if mc: - state_attr = {} + state_attr = { + ATTR_MEDIA_STATE: self.media_state, + 'application_id': self.cast.app_id, + } - if mc.is_playing: - state_attr[ATTR_MEDIA_STATE] = MEDIA_STATE_PLAYING - elif mc.is_paused: - state_attr[ATTR_MEDIA_STATE] = MEDIA_STATE_PAUSED - elif mc.is_idle: - state_attr[ATTR_MEDIA_STATE] = MEDIA_STATE_STOPPED + if cast_status: + state_attr[ATTR_MEDIA_VOLUME] = cast_status.volume_level, - media_status = self.cast.status + if media_status: + if media_status.content_id: + state_attr[ATTR_MEDIA_CONTENT_ID] = media_status.content_id - if media_status: + if media_status.duration: + state_attr[ATTR_MEDIA_DURATION] = media_status.duration - """ These status properties seem not to be present anymore in pychromecast """ - #if ramp.content_id: - # state_attr[ATTR_MEDIA_CONTENT_ID] = mc.ramp.content_id - - #if ramp.title: - # state_attr[ATTR_MEDIA_TITLE] = ramp.title - - #if ramp.artist: - # state_attr[ATTR_MEDIA_ARTIST] = ramp.artist - - #if ramp.album: - # state_attr[ATTR_MEDIA_ALBUM] = ramp.album - - #if ramp.image_url: - # state_attr[ATTR_MEDIA_IMAGE_URL] = ramp.image_url - - if hasattr(media_status, 'duration'): - state_attr[ATTR_MEDIA_DURATION] = media_status.duration - - state_attr[ATTR_MEDIA_VOLUME] = media_status.volume_level - - return state_attr + return state_attr def turn_off(self): """ Service to exit any running app on the specimedia player ChromeCast and @@ -135,30 +130,23 @@ class CastDevice(MediaPlayerDevice): def media_play_pause(self): """ Service to send the chromecast the command for play/pause. """ - media_state = self.state_attributes[ATTR_MEDIA_STATE] - if media_state == MEDIA_STATE_STOPPED or media_state == MEDIA_STATE_PAUSED: + media_state = self.media_state + + if media_state in (MEDIA_STATE_STOPPED, MEDIA_STATE_PAUSED): self.cast.media_controller.play() elif media_state == MEDIA_STATE_PLAYING: self.cast.media_controller.pause() def media_play(self): """ Service to send the chromecast the command for play/pause. """ - if self.state_attributes[ATTR_MEDIA_STATE] == MEDIA_STATE_STOPPED: - self.media_play_pause() + if self.media_state in (MEDIA_STATE_STOPPED, MEDIA_STATE_PAUSED): + self.cast.media_controller.play() def media_pause(self): """ Service to send the chromecast the command for play/pause. """ - if self.state_attributes[ATTR_MEDIA_STATE] == MEDIA_STATE_PLAYING: - self.media_play_pause() - - """ This one seems not to be present anymore in pychromecast, needs porting or cleanup """ - #def media_next_track(self): - # """ Service to send the chromecast the command for next track. """ - # ramp = self.cast.get_protocol(pychromecast.PROTOCOL_RAMP) - - # if ramp: - # ramp.next() + if self.media_state == MEDIA_STATE_PLAYING: + self.cast.media_controller.pause() def play_youtube_video(self, video_id): """ Plays specified video_id on the Chromecast's YouTube channel. """ - self.youtube.play_video(video_id) \ No newline at end of file + self.youtube.play_video(video_id)