Move companion json rpc commands
This commit is contained in:
parent
a09b6a4562
commit
f6b666e892
3 changed files with 241 additions and 120 deletions
|
@ -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
185
resources/lib/json_rpc.py
Normal 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()
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue