202 lines
5.8 KiB
Python
202 lines
5.8 KiB
Python
"""Support for HDMI CEC devices as media players."""
|
|
import logging
|
|
|
|
from pycec.commands import CecCommand, KeyPressCommand, KeyReleaseCommand
|
|
from pycec.const import (
|
|
KEY_BACKWARD,
|
|
KEY_FORWARD,
|
|
KEY_MUTE_TOGGLE,
|
|
KEY_PAUSE,
|
|
KEY_PLAY,
|
|
KEY_STOP,
|
|
KEY_VOLUME_DOWN,
|
|
KEY_VOLUME_UP,
|
|
POWER_OFF,
|
|
POWER_ON,
|
|
STATUS_PLAY,
|
|
STATUS_STILL,
|
|
STATUS_STOP,
|
|
TYPE_AUDIO,
|
|
TYPE_PLAYBACK,
|
|
TYPE_RECORDER,
|
|
TYPE_TUNER,
|
|
)
|
|
|
|
from homeassistant.components.media_player import MediaPlayerEntity
|
|
from homeassistant.components.media_player.const import (
|
|
DOMAIN,
|
|
SUPPORT_NEXT_TRACK,
|
|
SUPPORT_PAUSE,
|
|
SUPPORT_PLAY_MEDIA,
|
|
SUPPORT_PREVIOUS_TRACK,
|
|
SUPPORT_STOP,
|
|
SUPPORT_TURN_OFF,
|
|
SUPPORT_TURN_ON,
|
|
SUPPORT_VOLUME_MUTE,
|
|
SUPPORT_VOLUME_STEP,
|
|
)
|
|
from homeassistant.const import (
|
|
STATE_IDLE,
|
|
STATE_OFF,
|
|
STATE_ON,
|
|
STATE_PAUSED,
|
|
STATE_PLAYING,
|
|
)
|
|
|
|
from . import ATTR_NEW, CecEntity
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
|
|
|
|
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
|
"""Find and return HDMI devices as +switches."""
|
|
if ATTR_NEW in discovery_info:
|
|
_LOGGER.debug("Setting up HDMI devices %s", discovery_info[ATTR_NEW])
|
|
entities = []
|
|
for device in discovery_info[ATTR_NEW]:
|
|
hdmi_device = hass.data.get(device)
|
|
entities.append(CecPlayerEntity(hdmi_device, hdmi_device.logical_address))
|
|
add_entities(entities, True)
|
|
|
|
|
|
class CecPlayerEntity(CecEntity, MediaPlayerEntity):
|
|
"""Representation of a HDMI device as a Media player."""
|
|
|
|
def __init__(self, device, logical) -> None:
|
|
"""Initialize the HDMI device."""
|
|
CecEntity.__init__(self, device, logical)
|
|
self.entity_id = f"{DOMAIN}.hdmi_{hex(self._logical_address)[2:]}"
|
|
|
|
def send_keypress(self, key):
|
|
"""Send keypress to CEC adapter."""
|
|
_LOGGER.debug(
|
|
"Sending keypress %s to device %s", hex(key), hex(self._logical_address)
|
|
)
|
|
self._device.send_command(KeyPressCommand(key, dst=self._logical_address))
|
|
self._device.send_command(KeyReleaseCommand(dst=self._logical_address))
|
|
|
|
def send_playback(self, key):
|
|
"""Send playback status to CEC adapter."""
|
|
self._device.async_send_command(CecCommand(key, dst=self._logical_address))
|
|
|
|
def mute_volume(self, mute):
|
|
"""Mute volume."""
|
|
self.send_keypress(KEY_MUTE_TOGGLE)
|
|
|
|
def media_previous_track(self):
|
|
"""Go to previous track."""
|
|
self.send_keypress(KEY_BACKWARD)
|
|
|
|
def turn_on(self):
|
|
"""Turn device on."""
|
|
self._device.turn_on()
|
|
self._state = STATE_ON
|
|
|
|
def clear_playlist(self):
|
|
"""Clear players playlist."""
|
|
raise NotImplementedError()
|
|
|
|
def turn_off(self):
|
|
"""Turn device off."""
|
|
self._device.turn_off()
|
|
self._state = STATE_OFF
|
|
|
|
def media_stop(self):
|
|
"""Stop playback."""
|
|
self.send_keypress(KEY_STOP)
|
|
self._state = STATE_IDLE
|
|
|
|
def play_media(self, media_type, media_id, **kwargs):
|
|
"""Not supported."""
|
|
raise NotImplementedError()
|
|
|
|
def media_next_track(self):
|
|
"""Skip to next track."""
|
|
self.send_keypress(KEY_FORWARD)
|
|
|
|
def media_seek(self, position):
|
|
"""Not supported."""
|
|
raise NotImplementedError()
|
|
|
|
def set_volume_level(self, volume):
|
|
"""Set volume level, range 0..1."""
|
|
raise NotImplementedError()
|
|
|
|
def media_pause(self):
|
|
"""Pause playback."""
|
|
self.send_keypress(KEY_PAUSE)
|
|
self._state = STATE_PAUSED
|
|
|
|
def select_source(self, source):
|
|
"""Not supported."""
|
|
raise NotImplementedError()
|
|
|
|
def media_play(self):
|
|
"""Start playback."""
|
|
self.send_keypress(KEY_PLAY)
|
|
self._state = STATE_PLAYING
|
|
|
|
def volume_up(self):
|
|
"""Increase volume."""
|
|
_LOGGER.debug("%s: volume up", self._logical_address)
|
|
self.send_keypress(KEY_VOLUME_UP)
|
|
|
|
def volume_down(self):
|
|
"""Decrease volume."""
|
|
_LOGGER.debug("%s: volume down", self._logical_address)
|
|
self.send_keypress(KEY_VOLUME_DOWN)
|
|
|
|
@property
|
|
def state(self) -> str:
|
|
"""Cache state of device."""
|
|
return self._state
|
|
|
|
def update(self):
|
|
"""Update device status."""
|
|
device = self._device
|
|
if device.power_status in [POWER_OFF, 3]:
|
|
self._state = STATE_OFF
|
|
elif not self.support_pause:
|
|
if device.power_status in [POWER_ON, 4]:
|
|
self._state = STATE_ON
|
|
elif device.status == STATUS_PLAY:
|
|
self._state = STATE_PLAYING
|
|
elif device.status == STATUS_STOP:
|
|
self._state = STATE_IDLE
|
|
elif device.status == STATUS_STILL:
|
|
self._state = STATE_PAUSED
|
|
else:
|
|
_LOGGER.warning("Unknown state: %s", device.status)
|
|
|
|
@property
|
|
def supported_features(self):
|
|
"""Flag media player features that are supported."""
|
|
if self.type_id == TYPE_RECORDER or self.type == TYPE_PLAYBACK:
|
|
return (
|
|
SUPPORT_TURN_ON
|
|
| SUPPORT_TURN_OFF
|
|
| SUPPORT_PLAY_MEDIA
|
|
| SUPPORT_PAUSE
|
|
| SUPPORT_STOP
|
|
| SUPPORT_PREVIOUS_TRACK
|
|
| SUPPORT_NEXT_TRACK
|
|
)
|
|
if self.type == TYPE_TUNER:
|
|
return (
|
|
SUPPORT_TURN_ON
|
|
| SUPPORT_TURN_OFF
|
|
| SUPPORT_PLAY_MEDIA
|
|
| SUPPORT_PAUSE
|
|
| SUPPORT_STOP
|
|
)
|
|
if self.type_id == TYPE_AUDIO:
|
|
return (
|
|
SUPPORT_TURN_ON
|
|
| SUPPORT_TURN_OFF
|
|
| SUPPORT_VOLUME_STEP
|
|
| SUPPORT_VOLUME_MUTE
|
|
)
|
|
return SUPPORT_TURN_ON | SUPPORT_TURN_OFF
|