Move companion json rpc commands

This commit is contained in:
croneter 2017-12-08 07:53:01 +01:00
parent a09b6a4562
commit f6b666e892
3 changed files with 241 additions and 120 deletions

View file

@ -1,94 +1,50 @@
# -*- coding: utf-8 -*- """
import logging Processes Plex companion inputs from the plexbmchelper to Kodi commands
"""
from logging import getLogger
from xbmc import Player from xbmc import Player
from utils import JSONRPC
from variables import ALEXA_TO_COMPANION from variables import ALEXA_TO_COMPANION
from playqueue import Playqueue from playqueue import Playqueue
from PlexFunctions import GetPlexKeyNumber from PlexFunctions import GetPlexKeyNumber
import json_rpc as js
############################################################################### ###############################################################################
log = logging.getLogger("PLEX."+__name__) LOG = getLogger("PLEX." + __name__)
############################################################################### ###############################################################################
def getPlayers(): def skip_to(params):
info = JSONRPC("Player.GetActivePlayers").execute()['result'] or []
ret = {}
for player in info:
player['playerid'] = int(player['playerid'])
ret[player['type']] = player
return ret
def getPlayerIds():
ret = []
for player in getPlayers().values():
ret.append(player['playerid'])
return ret
def getPlaylistId(typus):
""" """
typus: one of the Kodi types, e.g. audio or video Skip to a specific playlist position.
Returns None if nothing was found Does not seem to be implemented yet by Plex!
""" """
for playlist in getPlaylists(): playqueue_item_id = params.get('playQueueItemID', 'not available')
if playlist.get('type') == typus: _, plex_id = GetPlexKeyNumber(params.get('key'))
return playlist.get('playlistid') LOG.debug('Skipping to playQueueItemID %s, plex_id %s',
playqueue_item_id, plex_id)
def getPlaylists():
"""
Returns a list, e.g.
[
{u'playlistid': 0, u'type': u'audio'},
{u'playlistid': 1, u'type': u'video'},
{u'playlistid': 2, u'type': u'picture'}
]
"""
return JSONRPC('Playlist.GetPlaylists').execute()
def millisToTime(t):
millis = int(t)
seconds = millis / 1000
minutes = seconds / 60
hours = minutes / 60
seconds = seconds % 60
minutes = minutes % 60
millis = millis % 1000
return {'hours': hours,
'minutes': minutes,
'seconds': seconds,
'milliseconds': millis}
def skipTo(params):
# Does not seem to be implemented yet
playQueueItemID = params.get('playQueueItemID', 'not available')
library, plex_id = GetPlexKeyNumber(params.get('key'))
log.debug('Skipping to playQueueItemID %s, plex_id %s'
% (playQueueItemID, plex_id))
found = True found = True
playqueues = Playqueue() playqueues = Playqueue()
for (player, ID) in getPlayers().iteritems(): for (player, _) in js.get_players().iteritems():
playqueue = playqueues.get_playqueue_from_type(player) playqueue = playqueues.get_playqueue_from_type(player)
for i, item in enumerate(playqueue.items): for i, item in enumerate(playqueue.items):
if item.ID == playQueueItemID or item.plex_id == plex_id: if item.ID == playqueue_item_id or item.plex_id == plex_id:
break break
else: else:
log.debug('Item not found to skip to') LOG.debug('Item not found to skip to')
found = False found = False
if found: if found:
Player().play(playqueue.kodi_pl, None, False, i) Player().play(playqueue.kodi_pl, None, False, i)
def convert_alexa_to_companion(dictionary): def convert_alexa_to_companion(dictionary):
"""
The params passed by Alexa must first be converted to Companion talk
"""
for key in dictionary: for key in dictionary:
if key in ALEXA_TO_COMPANION: if key in ALEXA_TO_COMPANION:
dictionary[ALEXA_TO_COMPANION[key]] = dictionary[key] dictionary[ALEXA_TO_COMPANION[key]] = dictionary[key]
@ -101,7 +57,7 @@ def process_command(request_path, params, queue=None):
""" """
if params.get('deviceName') == 'Alexa': if params.get('deviceName') == 'Alexa':
convert_alexa_to_companion(params) convert_alexa_to_companion(params)
log.debug('Received request_path: %s, params: %s' % (request_path, params)) LOG.debug('Received request_path: %s, params: %s', request_path, params)
if "/playMedia" in request_path: if "/playMedia" in request_path:
# We need to tell service.py # We need to tell service.py
action = 'alexa' if params.get('deviceName') == 'Alexa' else 'playlist' action = 'alexa' if params.get('deviceName') == 'Alexa' else 'playlist'
@ -109,84 +65,47 @@ def process_command(request_path, params, queue=None):
'action': action, 'action': action,
'data': params 'data': params
}) })
elif request_path == 'player/playback/refreshPlayQueue': elif request_path == 'player/playback/refreshPlayQueue':
queue.put({ queue.put({
'action': 'refreshPlayQueue', 'action': 'refreshPlayQueue',
'data': params 'data': params
}) })
elif request_path == "player/playback/setParameters": elif request_path == "player/playback/setParameters":
if 'volume' in params: if 'volume' in params:
volume = int(params['volume']) js.set_volume(int(params['volume']))
log.debug("Adjusting the volume to %s" % volume)
JSONRPC('Application.SetVolume').execute({"volume": volume})
else: else:
log.error('Unknown parameters: %s' % params) LOG.error('Unknown parameters: %s', params)
elif request_path == "player/playback/play": elif request_path == "player/playback/play":
for playerid in getPlayerIds(): js.play()
JSONRPC("Player.PlayPause").execute({"playerid": playerid,
"play": True})
elif request_path == "player/playback/pause": elif request_path == "player/playback/pause":
for playerid in getPlayerIds(): js.pause()
JSONRPC("Player.PlayPause").execute({"playerid": playerid,
"play": False})
elif request_path == "player/playback/stop": elif request_path == "player/playback/stop":
for playerid in getPlayerIds(): js.stop()
JSONRPC("Player.Stop").execute({"playerid": playerid})
elif request_path == "player/playback/seekTo": elif request_path == "player/playback/seekTo":
for playerid in getPlayerIds(): js.seek_to(int(params.get('offset', 0)))
JSONRPC("Player.Seek").execute(
{"playerid": playerid,
"value": millisToTime(params.get('offset', 0))})
elif request_path == "player/playback/stepForward": elif request_path == "player/playback/stepForward":
for playerid in getPlayerIds(): js.smallforward()
JSONRPC("Player.Seek").execute({"playerid": playerid,
"value": "smallforward"})
elif request_path == "player/playback/stepBack": elif request_path == "player/playback/stepBack":
for playerid in getPlayerIds(): js.smallbackward()
JSONRPC("Player.Seek").execute({"playerid": playerid,
"value": "smallbackward"})
elif request_path == "player/playback/skipNext": elif request_path == "player/playback/skipNext":
for playerid in getPlayerIds(): js.skipnext()
JSONRPC("Player.GoTo").execute({"playerid": playerid,
"to": "next"})
elif request_path == "player/playback/skipPrevious": elif request_path == "player/playback/skipPrevious":
for playerid in getPlayerIds(): js.skipprevious()
JSONRPC("Player.GoTo").execute({"playerid": playerid,
"to": "previous"})
elif request_path == "player/playback/skipTo": elif request_path == "player/playback/skipTo":
skipTo(params) skip_to(params)
elif request_path == "player/navigation/moveUp": elif request_path == "player/navigation/moveUp":
JSONRPC("Input.Up").execute() js.input_up()
elif request_path == "player/navigation/moveDown": elif request_path == "player/navigation/moveDown":
JSONRPC("Input.Down").execute() js.input_down()
elif request_path == "player/navigation/moveLeft": elif request_path == "player/navigation/moveLeft":
JSONRPC("Input.Left").execute() js.input_left()
elif request_path == "player/navigation/moveRight": elif request_path == "player/navigation/moveRight":
JSONRPC("Input.Right").execute() js.input_right()
elif request_path == "player/navigation/select": elif request_path == "player/navigation/select":
JSONRPC("Input.Select").execute() js.input_select()
elif request_path == "player/navigation/home": elif request_path == "player/navigation/home":
JSONRPC("Input.Home").execute() js.input_home()
elif request_path == "player/navigation/back": elif request_path == "player/navigation/back":
JSONRPC("Input.Back").execute() js.input_back()
else: else:
log.error('Unknown request path: %s' % request_path) LOG.error('Unknown request path: %s', request_path)

185
resources/lib/json_rpc.py Normal file
View file

@ -0,0 +1,185 @@
"""
Collection of functions using the Kodi JSON RPC interface.
See http://kodi.wiki/view/JSON-RPC_API
"""
from utils import JSONRPC, milliseconds_to_kodi_time
def get_players():
"""
Returns all the active Kodi players (usually 3) in a dict:
{
'video': {'playerid': int, 'type': 'video'}
'audio': ...
'picture': ...
}
"""
info = JSONRPC("Player.GetActivePlayers").execute()['result'] or []
ret = {}
for player in info:
player['playerid'] = int(player['playerid'])
ret[player['type']] = player
return ret
def get_player_ids():
"""
Returns a list of all the active Kodi player ids (usually 3) as int
"""
ret = []
for player in get_players().values():
ret.append(player['playerid'])
return ret
def get_playlist_id(typus):
"""
Returns the corresponding Kodi playlist id as an int
typus: Kodi playlist types: 'video', 'audio' or 'picture'
Returns None if nothing was found
"""
for playlist in get_playlists():
if playlist.get('type') == typus:
return playlist.get('playlistid')
def get_playlists():
"""
Returns a list of all the Kodi playlists, e.g.
[
{u'playlistid': 0, u'type': u'audio'},
{u'playlistid': 1, u'type': u'video'},
{u'playlistid': 2, u'type': u'picture'}
]
"""
return JSONRPC('Playlist.GetPlaylists').execute()
def set_volume(volume):
"""
Set's the volume (for Kodi overall, not only a player).
Feed with an int
"""
return JSONRPC('Application.SetVolume').execute({"volume": volume})
def play():
"""
Toggles all Kodi players to play
"""
for playerid in get_player_ids():
JSONRPC("Player.PlayPause").execute({"playerid": playerid,
"play": True})
def pause():
"""
Pauses playback for all Kodi players
"""
for playerid in get_player_ids():
JSONRPC("Player.PlayPause").execute({"playerid": playerid,
"play": False})
def stop():
"""
Stops playback for all Kodi players
"""
for playerid in get_player_ids():
JSONRPC("Player.Stop").execute({"playerid": playerid})
def seek_to(offset):
"""
Seeks all Kodi players to offset [int]
"""
for playerid in get_player_ids():
JSONRPC("Player.Seek").execute(
{"playerid": playerid,
"value": milliseconds_to_kodi_time(offset)})
def smallforward():
"""
Small step forward for all Kodi players
"""
for playerid in get_player_ids():
JSONRPC("Player.Seek").execute({"playerid": playerid,
"value": "smallforward"})
def smallbackward():
"""
Small step backward for all Kodi players
"""
for playerid in get_player_ids():
JSONRPC("Player.Seek").execute({"playerid": playerid,
"value": "smallbackward"})
def skipnext():
"""
Skips to the next item to play for all Kodi players
"""
for playerid in get_player_ids():
JSONRPC("Player.GoTo").execute({"playerid": playerid,
"to": "next"})
def skipprevious():
"""
Skips to the previous item to play for all Kodi players
"""
for playerid in get_player_ids():
JSONRPC("Player.GoTo").execute({"playerid": playerid,
"to": "previous"})
def input_up():
"""
Tells Kodi the users pushed up
"""
JSONRPC("Input.Up").execute()
def input_down():
"""
Tells Kodi the users pushed down
"""
JSONRPC("Input.Down").execute()
def input_left():
"""
Tells Kodi the users pushed left
"""
JSONRPC("Input.Left").execute()
def input_right():
"""
Tells Kodi the users pushed left
"""
JSONRPC("Input.Right").execute()
def input_select():
"""
Tells Kodi the users pushed select
"""
JSONRPC("Input.Select").execute()
def input_home():
"""
Tells Kodi the users pushed home
"""
JSONRPC("Input.Home").execute()
def input_back():
"""
Tells Kodi the users pushed back
"""
JSONRPC("Input.Back").execute()

View file

@ -180,6 +180,23 @@ def dialog(typus, *args, **kwargs):
return types[typus](*args, **kwargs) return types[typus](*args, **kwargs)
def milliseconds_to_kodi_time(milliseconds):
"""
Converts time in milliseconds to the time dict used by the Kodi JSON RPC
Pass in the time in milliseconds as an int
"""
seconds = milliseconds / 1000
minutes = seconds / 60
hours = minutes / 60
seconds = seconds % 60
minutes = minutes % 60
milliseconds = milliseconds % 1000
return {'hours': hours,
'minutes': minutes,
'seconds': seconds,
'milliseconds': milliseconds}
def tryEncode(uniString, encoding='utf-8'): def tryEncode(uniString, encoding='utf-8'):
""" """
Will try to encode uniString (in unicode) to encoding. This possibly Will try to encode uniString (in unicode) to encoding. This possibly