"""Provide functionality to interact with the vlc telnet interface.""" import logging import voluptuous as vol from python_telnet_vlc import VLCTelnet, ConnectionError as ConnErr from homeassistant.components.media_player import ( MediaPlayerDevice, PLATFORM_SCHEMA) from homeassistant.components.media_player.const import ( MEDIA_TYPE_MUSIC, SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_PLAY_MEDIA, SUPPORT_STOP, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_PREVIOUS_TRACK, SUPPORT_SEEK, SUPPORT_NEXT_TRACK, SUPPORT_CLEAR_PLAYLIST, SUPPORT_SHUFFLE_SET) from homeassistant.const import ( CONF_NAME, STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_UNAVAILABLE, CONF_HOST, CONF_PORT, CONF_PASSWORD) import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) DOMAIN = 'vlc_telnet' DEFAULT_NAME = 'VLC-TELNET' DEFAULT_PORT = 4212 SUPPORT_VLC = SUPPORT_PAUSE | SUPPORT_SEEK | SUPPORT_VOLUME_SET \ | SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK \ | SUPPORT_NEXT_TRACK | SUPPORT_PLAY_MEDIA | SUPPORT_STOP \ | SUPPORT_CLEAR_PLAYLIST | SUPPORT_PLAY \ | SUPPORT_SHUFFLE_SET PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.positive_int, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the vlc platform.""" add_entities([VlcDevice(config.get(CONF_NAME), config.get(CONF_HOST), config.get(CONF_PORT), config.get(CONF_PASSWORD))], True) class VlcDevice(MediaPlayerDevice): """Representation of a vlc player.""" def __init__(self, name, host, port, passwd): """Initialize the vlc device.""" self._instance = None self._name = name self._volume = None self._muted = None self._state = STATE_UNAVAILABLE self._media_position_updated_at = None self._media_position = None self._media_duration = None self._host = host self._port = port self._password = passwd self._vlc = None self._available = False self._volume_bkp = 0 self._media_artist = "" self._media_title = "" def update(self): """Get the latest details from the device.""" if self._vlc is None: try: self._vlc = VLCTelnet(self._host, self._password, self._port) self._state = STATE_IDLE self._available = True except (ConnErr, EOFError): self._available = False self._vlc = None else: try: status = self._vlc.status() if status: if 'volume' in status: self._volume = int(status['volume']) / 500.0 else: self._volume = None if 'state' in status: state = status["state"] if state == "playing": self._state = STATE_PLAYING elif state == "paused": self._state = STATE_PAUSED else: self._state = STATE_IDLE else: self._state = STATE_IDLE self._media_duration = self._vlc.get_length() self._media_position = self._vlc.get_time() info = self._vlc.info() if info: self._media_artist = info[0].get('artist') self._media_title = info[0].get('title') except (ConnErr, EOFError): self._available = False self._vlc = None return True @property def name(self): """Return the name of the device.""" return self._name @property def state(self): """Return the state of the device.""" return self._state @property def available(self) -> bool: """Return True if entity is available.""" return self._available @property def volume_level(self): """Volume level of the media player (0..1).""" return self._volume @property def is_volume_muted(self): """Boolean if volume is currently muted.""" return self._muted @property def supported_features(self): """Flag media player features that are supported.""" return SUPPORT_VLC @property def media_content_type(self): """Content type of current playing media.""" return MEDIA_TYPE_MUSIC @property def media_duration(self): """Duration of current playing media in seconds.""" return self._media_duration @property def media_position(self): """Position of current playing media in seconds.""" return self._media_position @property def media_position_updated_at(self): """When was the position of the current playing media valid.""" return self._media_position_updated_at @property def media_title(self): """Title of current playing media.""" return self._media_title @property def media_artist(self): """Artist of current playing media, music track only.""" return self._media_artist def media_seek(self, position): """Seek the media to a specific location.""" track_length = self._vlc.get_length() / 1000 self._vlc.seek(position / track_length) def mute_volume(self, mute): """Mute the volume.""" if mute: self._volume_bkp = self._volume self._volume = 0 self._vlc.set_volume("0") else: self._vlc.set_volume(str(self._volume_bkp)) self._volume = self._volume_bkp self._muted = mute def set_volume_level(self, volume): """Set volume level, range 0..1.""" self._vlc.set_volume(str(volume * 500)) self._volume = volume def media_play(self): """Send play command.""" self._vlc.play() self._state = STATE_PLAYING def media_pause(self): """Send pause command.""" self._vlc.pause() self._state = STATE_PAUSED def media_stop(self): """Send stop command.""" self._vlc.stop() self._state = STATE_IDLE def play_media(self, media_type, media_id, **kwargs): """Play media from a URL or file.""" if media_type != MEDIA_TYPE_MUSIC: _LOGGER.error( "Invalid media type %s. Only %s is supported", media_type, MEDIA_TYPE_MUSIC) return self._vlc.add(media_id) self._state = STATE_PLAYING def media_previous_track(self): """Send previous track command.""" self._vlc.prev() def media_next_track(self): """Send next track command.""" self._vlc.next() def clear_playlist(self): """Clear players playlist.""" self._vlc.clear() def set_shuffle(self, shuffle): """Enable/disable shuffle mode.""" self._vlc.random(shuffle)