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 utils import JSONRPC
from variables import ALEXA_TO_COMPANION
from playqueue import Playqueue
from PlexFunctions import GetPlexKeyNumber
import json_rpc as js
###############################################################################
log = logging.getLogger("PLEX."+__name__)
LOG = getLogger("PLEX." + __name__)
###############################################################################
def getPlayers():
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):
def skip_to(params):
"""
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():
if playlist.get('type') == typus:
return playlist.get('playlistid')
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))
playqueue_item_id = params.get('playQueueItemID', 'not available')
_, plex_id = GetPlexKeyNumber(params.get('key'))
LOG.debug('Skipping to playQueueItemID %s, plex_id %s',
playqueue_item_id, plex_id)
found = True
playqueues = Playqueue()
for (player, ID) in getPlayers().iteritems():
for (player, _) in js.get_players().iteritems():
playqueue = playqueues.get_playqueue_from_type(player)
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
else:
log.debug('Item not found to skip to')
LOG.debug('Item not found to skip to')
found = False
if found:
Player().play(playqueue.kodi_pl, None, False, i)
def convert_alexa_to_companion(dictionary):
"""
The params passed by Alexa must first be converted to Companion talk
"""
for key in dictionary:
if key in ALEXA_TO_COMPANION:
dictionary[ALEXA_TO_COMPANION[key]] = dictionary[key]
@ -101,7 +57,7 @@ def process_command(request_path, params, queue=None):
"""
if params.get('deviceName') == 'Alexa':
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:
# We need to tell service.py
action = 'alexa' if params.get('deviceName') == 'Alexa' else 'playlist'
@ -109,84 +65,47 @@ def process_command(request_path, params, queue=None):
'action': action,
'data': params
})
elif request_path == 'player/playback/refreshPlayQueue':
queue.put({
'action': 'refreshPlayQueue',
'data': params
})
elif request_path == "player/playback/setParameters":
if 'volume' in params:
volume = int(params['volume'])
log.debug("Adjusting the volume to %s" % volume)
JSONRPC('Application.SetVolume').execute({"volume": volume})
js.set_volume(int(params['volume']))
else:
log.error('Unknown parameters: %s' % params)
LOG.error('Unknown parameters: %s', params)
elif request_path == "player/playback/play":
for playerid in getPlayerIds():
JSONRPC("Player.PlayPause").execute({"playerid": playerid,
"play": True})
js.play()
elif request_path == "player/playback/pause":
for playerid in getPlayerIds():
JSONRPC("Player.PlayPause").execute({"playerid": playerid,
"play": False})
js.pause()
elif request_path == "player/playback/stop":
for playerid in getPlayerIds():
JSONRPC("Player.Stop").execute({"playerid": playerid})
js.stop()
elif request_path == "player/playback/seekTo":
for playerid in getPlayerIds():
JSONRPC("Player.Seek").execute(
{"playerid": playerid,
"value": millisToTime(params.get('offset', 0))})
js.seek_to(int(params.get('offset', 0)))
elif request_path == "player/playback/stepForward":
for playerid in getPlayerIds():
JSONRPC("Player.Seek").execute({"playerid": playerid,
"value": "smallforward"})
js.smallforward()
elif request_path == "player/playback/stepBack":
for playerid in getPlayerIds():
JSONRPC("Player.Seek").execute({"playerid": playerid,
"value": "smallbackward"})
js.smallbackward()
elif request_path == "player/playback/skipNext":
for playerid in getPlayerIds():
JSONRPC("Player.GoTo").execute({"playerid": playerid,
"to": "next"})
js.skipnext()
elif request_path == "player/playback/skipPrevious":
for playerid in getPlayerIds():
JSONRPC("Player.GoTo").execute({"playerid": playerid,
"to": "previous"})
js.skipprevious()
elif request_path == "player/playback/skipTo":
skipTo(params)
skip_to(params)
elif request_path == "player/navigation/moveUp":
JSONRPC("Input.Up").execute()
js.input_up()
elif request_path == "player/navigation/moveDown":
JSONRPC("Input.Down").execute()
js.input_down()
elif request_path == "player/navigation/moveLeft":
JSONRPC("Input.Left").execute()
js.input_left()
elif request_path == "player/navigation/moveRight":
JSONRPC("Input.Right").execute()
js.input_right()
elif request_path == "player/navigation/select":
JSONRPC("Input.Select").execute()
js.input_select()
elif request_path == "player/navigation/home":
JSONRPC("Input.Home").execute()
js.input_home()
elif request_path == "player/navigation/back":
JSONRPC("Input.Back").execute()
js.input_back()
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)
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'):
"""
Will try to encode uniString (in unicode) to encoding. This possibly