-
-
Notifications
You must be signed in to change notification settings - Fork 37.5k
Introducing a media_player component for Yamaha Multicast devices #9258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
a4fb64b
Introducing media_player yamaha_multicast
jalmeroth 664c25d
Fix pep8_max_line_length
jalmeroth 7b79f48
Revert "Fix pep8_max_line_length"
jalmeroth 4f983bb
Revert "Introducing media_player yamaha_multicast"
jalmeroth 51b138f
Introducing media_player for Yamaha MultiCast Devices
jalmeroth e055a34
Add missing Docstrings
jalmeroth b72b7cf
Adding Requirements
jalmeroth c240d90
Add Geofency device tracker (#9106)
gunnarhelgason 58fda2a
Version bump
jalmeroth e188e0d
Version bump
jalmeroth d5247cb
D210: No whitespaces allowed surrounding docstring text
jalmeroth 2538d7f
Fix linting
jalmeroth 7d763b2
Version bump
jalmeroth 0b7fdf1
Revert "Add Geofency device tracker (#9106)"
jalmeroth e45c4c5
Fix Invalid method names
jalmeroth dda3e85
Fix update_status timer
jalmeroth 57baeba
Fix Invalid class name "mcDevice"
jalmeroth f3d48bf
Fix Access to a protected members
jalmeroth 036493e
Introducing source_list setter
jalmeroth ca17f17
Fix logging
jalmeroth b6b6ed4
Version bump
jalmeroth 9cbcbe7
D400: First line should end with a period (not 'e')
jalmeroth f250f82
Removed unnecessary logging
jalmeroth c7e34c4
Minor changes
jalmeroth File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
233 changes: 233 additions & 0 deletions
233
homeassistant/components/media_player/yamaha_musiccast.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| """Example for configuration.yaml. | ||
|
|
||
| media_player: | ||
| - platform: yamaha_musiccast | ||
| name: "Living Room" | ||
| host: 192.168.xxx.xx | ||
| port: 5005 | ||
|
|
||
| """ | ||
|
|
||
| import logging | ||
| import voluptuous as vol | ||
| import homeassistant.helpers.config_validation as cv | ||
|
|
||
| from homeassistant.const import ( | ||
| CONF_NAME, CONF_HOST, CONF_PORT, | ||
| STATE_UNKNOWN, STATE_ON | ||
| ) | ||
| from homeassistant.components.media_player import ( | ||
| MediaPlayerDevice, MEDIA_TYPE_MUSIC, PLATFORM_SCHEMA, | ||
| SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK, | ||
| SUPPORT_TURN_ON, SUPPORT_TURN_OFF, SUPPORT_PLAY, | ||
| SUPPORT_VOLUME_SET, SUPPORT_VOLUME_MUTE, | ||
| SUPPORT_SELECT_SOURCE, SUPPORT_STOP | ||
| ) | ||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| SUPPORTED_FEATURES = ( | ||
| SUPPORT_PLAY | SUPPORT_PAUSE | SUPPORT_STOP | | ||
| SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | | ||
| SUPPORT_TURN_ON | SUPPORT_TURN_OFF | | ||
| SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | | ||
| SUPPORT_SELECT_SOURCE | ||
| ) | ||
|
|
||
| REQUIREMENTS = ['pymusiccast==0.1.0'] | ||
|
|
||
| DEFAULT_NAME = "Yamaha Receiver" | ||
| DEFAULT_PORT = 5005 | ||
|
|
||
| PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | ||
| vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, | ||
| vol.Required(CONF_HOST): cv.string, | ||
| vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.positive_int, | ||
| }) | ||
|
|
||
|
|
||
| def setup_platform(hass, config, add_devices, discovery_info=None): | ||
| """Set up the Yamaha MusicCast platform.""" | ||
| import pymusiccast | ||
|
|
||
| name = config.get(CONF_NAME) | ||
| host = config.get(CONF_HOST) | ||
| port = config.get(CONF_PORT) | ||
|
|
||
| receiver = pymusiccast.McDevice(host, udp_port=port) | ||
| _LOGGER.debug("receiver: %s / Port: %d", receiver, port) | ||
|
|
||
| add_devices([YamahaDevice(receiver, name)], True) | ||
|
|
||
|
|
||
| class YamahaDevice(MediaPlayerDevice): | ||
| """Representation of a Yamaha MusicCast device.""" | ||
|
|
||
| def __init__(self, receiver, name): | ||
| """Initialize the Yamaha MusicCast device.""" | ||
| self._receiver = receiver | ||
| self._name = name | ||
| self.power = STATE_UNKNOWN | ||
| self.volume = 0 | ||
| self.volume_max = 0 | ||
| self.mute = False | ||
| self._source = None | ||
| self._source_list = [] | ||
| self.status = STATE_UNKNOWN | ||
| self.media_status = None | ||
| self._receiver.set_yamaha_device(self) | ||
|
|
||
| @property | ||
| def name(self): | ||
| """Return the name of the device.""" | ||
| return self._name | ||
|
|
||
| @property | ||
| def state(self): | ||
| """Return the state of the device.""" | ||
| if self.power == STATE_ON and self.status is not STATE_UNKNOWN: | ||
| return self.status | ||
| return self.power | ||
|
|
||
| @property | ||
| def should_poll(self): | ||
| """Push an update after each command.""" | ||
| return True | ||
|
|
||
| @property | ||
| def is_volume_muted(self): | ||
| """Boolean if volume is currently muted.""" | ||
| return self.mute | ||
|
|
||
| @property | ||
| def volume_level(self): | ||
| """Volume level of the media player (0..1).""" | ||
| return self.volume | ||
|
|
||
| @property | ||
| def supported_features(self): | ||
| """Flag of features that are supported.""" | ||
| return SUPPORTED_FEATURES | ||
|
|
||
| @property | ||
| def source(self): | ||
| """Return the current input source.""" | ||
| return self._source | ||
|
|
||
| @property | ||
| def source_list(self): | ||
| """List of available input sources.""" | ||
| return self._source_list | ||
|
|
||
| @source_list.setter | ||
| def source_list(self, value): | ||
| """Set source_list attribute.""" | ||
| self._source_list = value | ||
|
|
||
| @property | ||
| def media_content_type(self): | ||
| """Return the media content type.""" | ||
| return MEDIA_TYPE_MUSIC | ||
|
|
||
| @property | ||
| def media_duration(self): | ||
| """Duration of current playing media in seconds.""" | ||
| return self.media_status.media_duration \ | ||
| if self.media_status else None | ||
|
|
||
| @property | ||
| def media_image_url(self): | ||
| """Image url of current playing media.""" | ||
| return self.media_status.media_image_url \ | ||
| if self.media_status else None | ||
|
|
||
| @property | ||
| def media_artist(self): | ||
| """Artist of current playing media, music track only.""" | ||
| return self.media_status.media_artist if self.media_status else None | ||
|
|
||
| @property | ||
| def media_album(self): | ||
| """Album of current playing media, music track only.""" | ||
| return self.media_status.media_album if self.media_status else None | ||
|
|
||
| @property | ||
| def media_track(self): | ||
| """Track number of current playing media, music track only.""" | ||
| return self.media_status.media_track if self.media_status else None | ||
|
|
||
| @property | ||
| def media_title(self): | ||
| """Title of current playing media.""" | ||
| return self.media_status.media_title if self.media_status else None | ||
|
|
||
| def update(self): | ||
| """Get the latest details from the device.""" | ||
| _LOGGER.debug("update: %s", self.entity_id) | ||
|
|
||
| # call from constructor setup_platform() | ||
| if not self.entity_id: | ||
| _LOGGER.debug("First run") | ||
| self._receiver.update_status(push=False) | ||
| # call from regular polling | ||
| else: | ||
| # update_status_timer was set before | ||
| if self._receiver.update_status_timer: | ||
| _LOGGER.debug( | ||
| "is_alive: %s", | ||
| self._receiver.update_status_timer.is_alive()) | ||
| # e.g. computer was suspended, while hass was running | ||
| if not self._receiver.update_status_timer.is_alive(): | ||
| _LOGGER.debug("Reinitializing") | ||
| self._receiver.update_status() | ||
|
|
||
| def turn_on(self): | ||
| """Turn on specified media player or all.""" | ||
| _LOGGER.debug("Turn device: on") | ||
| self._receiver.set_power(True) | ||
|
|
||
| def turn_off(self): | ||
| """Turn off specified media player or all.""" | ||
| _LOGGER.debug("Turn device: off") | ||
| self._receiver.set_power(False) | ||
|
|
||
| def media_play(self): | ||
| """Send the media player the command for play/pause.""" | ||
| _LOGGER.debug("Play") | ||
| self._receiver.set_playback("play") | ||
|
|
||
| def media_pause(self): | ||
| """Send the media player the command for pause.""" | ||
| _LOGGER.debug("Pause") | ||
| self._receiver.set_playback("pause") | ||
|
|
||
| def media_stop(self): | ||
| """Send the media player the stop command.""" | ||
| _LOGGER.debug("Stop") | ||
| self._receiver.set_playback("stop") | ||
|
|
||
| def media_previous_track(self): | ||
| """Send the media player the command for prev track.""" | ||
| _LOGGER.debug("Previous") | ||
| self._receiver.set_playback("previous") | ||
|
|
||
| def media_next_track(self): | ||
| """Send the media player the command for next track.""" | ||
| _LOGGER.debug("Next") | ||
| self._receiver.set_playback("next") | ||
|
|
||
| def mute_volume(self, mute): | ||
| """Send mute command.""" | ||
| _LOGGER.debug("Mute volume: %s", mute) | ||
| self._receiver.set_mute(mute) | ||
|
|
||
| def set_volume_level(self, volume): | ||
| """Set volume level, range 0..1.""" | ||
| _LOGGER.debug("Volume level: %.2f / %d", | ||
| volume, volume * self.volume_max) | ||
| self._receiver.set_volume(volume * self.volume_max) | ||
|
|
||
| def select_source(self, source): | ||
| """Send the media player the command to select input source.""" | ||
| _LOGGER.debug("select_source: %s", source) | ||
| self.status = STATE_UNKNOWN | ||
| self._receiver.set_input(source) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just return self.media_status
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.media_status is the whole object incl. artist, etc.. But I guess returning MEDIA_TYPE_MUSIC would be sufficient