Files
home-assistant-core/homeassistant/components/media_player/kodi.py
T
Robert Marklund 0bdd293572 kodi: remove traceback on state check
If the computer is sleeping that are running xbmc then
the traceback is printed in the log all the time.
Keep the traceback in debug mode of the module if needed.

Signed-off-by: Robert Marklund <robbelibobban@gmail.com>
2016-01-21 20:59:58 +01:00

274 lines
8.1 KiB
Python

"""
homeassistant.components.media_player.kodi
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides an interface to the XBMC/Kodi JSON-RPC API
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.kodi/
"""
import urllib
import logging
from homeassistant.components.media_player import (
MediaPlayerDevice, SUPPORT_PAUSE, SUPPORT_SEEK, SUPPORT_VOLUME_SET,
SUPPORT_VOLUME_MUTE, SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK)
from homeassistant.const import (
STATE_IDLE, STATE_PLAYING, STATE_PAUSED, STATE_OFF)
_LOGGER = logging.getLogger(__name__)
REQUIREMENTS = ['jsonrpc-requests==0.1']
SUPPORT_KODI = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_SEEK
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the kodi platform. """
add_devices([
KodiDevice(
config.get('name', 'Kodi'),
config.get('url'),
auth=(
config.get('user', ''),
config.get('password', ''))),
])
def _get_image_url(kodi_url):
""" Helper function that parses the thumbnail URLs used by Kodi. """
url_components = urllib.parse.urlparse(kodi_url)
if url_components.scheme == 'image':
return urllib.parse.unquote(url_components.netloc)
class KodiDevice(MediaPlayerDevice):
""" Represents a XBMC/Kodi device. """
# pylint: disable=too-many-public-methods
def __init__(self, name, url, auth=None):
import jsonrpc_requests
self._name = name
self._url = url
self._server = jsonrpc_requests.Server(url, auth=auth)
self._players = None
self._properties = None
self._item = None
self._app_properties = None
self.update()
@property
def name(self):
""" Returns the name of the device. """
return self._name
def _get_players(self):
""" Returns the active player objects or None """
import jsonrpc_requests
try:
return self._server.Player.GetActivePlayers()
except jsonrpc_requests.jsonrpc.TransportError:
_LOGGER.warning('Unable to fetch kodi data')
_LOGGER.debug('Unable to fetch kodi data', exc_info=True)
return None
@property
def state(self):
""" Returns the state of the device. """
if self._players is None:
return STATE_OFF
if len(self._players) == 0:
return STATE_IDLE
if self._properties['speed'] == 0:
return STATE_PAUSED
else:
return STATE_PLAYING
def update(self):
""" Retrieve latest state. """
self._players = self._get_players()
if self._players is not None and len(self._players) > 0:
player_id = self._players[0]['playerid']
assert isinstance(player_id, int)
self._properties = self._server.Player.GetProperties(
player_id,
['time', 'totaltime', 'speed']
)
self._item = self._server.Player.GetItem(
player_id,
['title', 'file', 'uniqueid', 'thumbnail', 'artist']
)['item']
self._app_properties = self._server.Application.GetProperties(
['volume', 'muted']
)
else:
self._properties = None
self._item = None
self._app_properties = None
@property
def volume_level(self):
""" Volume level of the media player (0..1). """
if self._app_properties is not None:
return self._app_properties['volume'] / 100.0
@property
def is_volume_muted(self):
""" Boolean if volume is currently muted. """
if self._app_properties is not None:
return self._app_properties['muted']
@property
def media_content_id(self):
""" Content ID of current playing media. """
if self._item is not None:
return self._item.get('uniqueid', None)
@property
def media_content_type(self):
""" Content type of current playing media. """
if self._players is not None and len(self._players) > 0:
return self._players[0]['type']
@property
def media_duration(self):
""" Duration of current playing media in seconds. """
if self._properties is not None:
total_time = self._properties['totaltime']
return (
total_time['hours'] * 3600 +
total_time['minutes'] * 60 +
total_time['seconds'])
@property
def media_image_url(self):
""" Image url of current playing media. """
if self._item is not None:
return _get_image_url(self._item['thumbnail'])
@property
def media_title(self):
""" Title of current playing media. """
# find a string we can use as a title
if self._item is not None:
return self._item.get(
'title',
self._item.get(
'label',
self._item.get(
'file',
'unknown')))
@property
def supported_media_commands(self):
""" Flags of media commands that are supported. """
return SUPPORT_KODI
def turn_off(self):
""" turn_off media player. """
self._server.System.Shutdown()
self.update_ha_state()
def volume_up(self):
""" volume_up media player. """
assert self._server.Input.ExecuteAction('volumeup') == 'OK'
self.update_ha_state()
def volume_down(self):
""" volume_down media player. """
assert self._server.Input.ExecuteAction('volumedown') == 'OK'
self.update_ha_state()
def set_volume_level(self, volume):
""" set volume level, range 0..1. """
self._server.Application.SetVolume(int(volume * 100))
self.update_ha_state()
def mute_volume(self, mute):
""" mute (true) or unmute (false) media player. """
self._server.Application.SetMute(mute)
self.update_ha_state()
def _set_play_state(self, state):
""" Helper method for play/pause/toggle. """
players = self._get_players()
if len(players) != 0:
self._server.Player.PlayPause(players[0]['playerid'], state)
self.update_ha_state()
def media_play_pause(self):
""" media_play_pause media player. """
self._set_play_state('toggle')
def media_play(self):
""" media_play media player. """
self._set_play_state(True)
def media_pause(self):
""" media_pause media player. """
self._set_play_state(False)
def _goto(self, direction):
""" Helper method used for previous/next track. """
players = self._get_players()
if len(players) != 0:
self._server.Player.GoTo(players[0]['playerid'], direction)
self.update_ha_state()
def media_next_track(self):
""" Send next track command. """
self._goto('next')
def media_previous_track(self):
""" Send next track command. """
# first seek to position 0, Kodi seems to go to the beginning
# of the current track current track is not at the beginning
self.media_seek(0)
self._goto('previous')
def media_seek(self, position):
""" Send seek command. """
players = self._get_players()
time = {}
time['milliseconds'] = int((position % 1) * 1000)
position = int(position)
time['seconds'] = int(position % 60)
position /= 60
time['minutes'] = int(position % 60)
position /= 60
time['hours'] = int(position)
if len(players) != 0:
self._server.Player.Seek(players[0]['playerid'], time)
self.update_ha_state()
def turn_on(self):
""" turn the media player on. """
raise NotImplementedError()
def play_youtube(self, media_id):
""" Plays a YouTube media. """
raise NotImplementedError()