Fixes to playQueues for Addon paths

This commit is contained in:
tomkat83 2016-12-28 19:38:43 +01:00
parent 49b5131dbb
commit eec2c10cb4
4 changed files with 152 additions and 89 deletions

View file

@ -88,11 +88,16 @@ class PlexCompanion(Thread):
if ID != playqueue.ID: if ID != playqueue.ID:
# playqueue changed somehow # playqueue changed somehow
self.mgr.playqueue.update_playqueue_from_PMS( self.mgr.playqueue.update_playqueue_from_PMS(
playqueue, ID, int(query['repeat']), data['offset']) playqueue,
ID,
query.get('repeat'),
data.get('offset'))
else: else:
# No change to the playqueue # No change to the playqueue
self.mgr.playqueue.start_playqueue_initiated_by_companion( self.mgr.playqueue.start_playqueue_initiated_by_companion(
playqueue, int(query['repeat']), data['offset']) playqueue,
query.get('repeat'),
data.get('offset'))
def run(self): def run(self):
httpd = False httpd = False

View file

@ -17,6 +17,7 @@ import downloadutils
import PlexAPI import PlexAPI
import PlexFunctions as PF import PlexFunctions as PF
import playlist_func as PL
############################################################################### ###############################################################################
@ -36,9 +37,12 @@ class PlaybackUtils():
self.userid = window('currUserId') self.userid = window('currUserId')
self.server = window('pms_server') self.server = window('pms_server')
playqueue = Playqueue()
self.pl = Playqueue().get_playqueue_from_type( # We need to initialize already existing items as we have a completely
PF.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[self.API.getType()]) # different Python instance!
playqueue.init_playlists()
self.pl = playqueue.get_playqueue_from_type(
PF.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[item[0].attrib.get('type')])
def play(self, itemid, dbid=None): def play(self, itemid, dbid=None):
@ -51,6 +55,7 @@ class PlaybackUtils():
playutils = putils.PlayUtils(item[0]) playutils = putils.PlayUtils(item[0])
log.info("Play called.") log.info("Play called.")
log.debug('Playqueue: %s' % self.pl)
playurl = playutils.getPlayUrl() playurl = playutils.getPlayUrl()
if not playurl: if not playurl:
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
@ -108,6 +113,9 @@ class PlaybackUtils():
############### RESUME POINT ################ ############### RESUME POINT ################
seektime, runtime = API.getRuntime() seektime, runtime = API.getRuntime()
if window('plex_customplaylist.seektime'):
# Already got seektime, e.g. from playqueue & Plex companion
seektime = int(window('plex_customplaylist.seektime'))
# We need to ensure we add the intro and additional parts only once. # We need to ensure we add the intro and additional parts only once.
# Otherwise we get a loop. # Otherwise we get a loop.
@ -120,12 +128,20 @@ class PlaybackUtils():
window('plex_customplaylist') != "true" and window('plex_customplaylist') != "true" and
not contextmenu_play): not contextmenu_play):
log.debug("Adding dummy file to playlist.") log.debug("Adding dummy file to playlist.")
# Make sure Kodimonitor recognizes dummy
listitem.setLabel('plex_dummyfile')
dummyPlaylist = True dummyPlaylist = True
kodiPl.add(playurl, listitem, index=startPos) PL.add_listitem_to_Kodi_playlist(
self.pl,
listitem,
playurl,
startPos)
# Remove the original item from playlist # Remove the original item from playlist
self.pl.removefromPlaylist(startPos+1) PL.remove_from_Kodi_playlist(self.pl, startPos+1)
# Readd the original item to playlist - via jsonrpc so we have full metadata # Readd the original item to playlist - via jsonrpc so we have
self.pl.insertintoPlaylist( # full metadata
PL.insert_into_Kodi_playlist(
self.pl,
self.currentPosition+1, self.currentPosition+1,
dbid, dbid,
PF.KODITYPE_FROM_PLEXTYPE[API.getType()]) PF.KODITYPE_FROM_PLEXTYPE[API.getType()])
@ -146,9 +162,10 @@ class PlaybackUtils():
# Extend our current playlist with the actual item to play # Extend our current playlist with the actual item to play
# only if there's no playlist first # only if there's no playlist first
log.info("Adding main item to playlist.") log.info("Adding main item to playlist.")
self.pl.addtoPlaylist( PL.add_dbid_to_Kodi_playlist(
dbid, self.pl,
PF.KODITYPE_FROM_PLEXTYPE[API.getType()]) dbid=dbid,
mediatype=PF.KODITYPE_FROM_PLEXTYPE[API.getType()])
elif contextmenu_play: elif contextmenu_play:
if window('useDirectPaths') == 'true': if window('useDirectPaths') == 'true':
@ -168,10 +185,11 @@ class PlaybackUtils():
kodiPl.add(playurl, listitem, index=self.currentPosition+1) kodiPl.add(playurl, listitem, index=self.currentPosition+1)
else: else:
# Full metadata # Full metadata
self.pl.insertintoPlaylist( PL.insert_into_Kodi_playlist(
self.pl,
self.currentPosition+1, self.currentPosition+1,
dbid, dbid=dbid,
PF.KODITYPE_FROM_PLEXTYPE[API.getType()]) mediatype=PF.KODITYPE_FROM_PLEXTYPE[API.getType()])
self.currentPosition += 1 self.currentPosition += 1
if seektime: if seektime:
window('plex_customplaylist.seektime', value=str(seektime)) window('plex_customplaylist.seektime', value=str(seektime))
@ -201,7 +219,6 @@ class PlaybackUtils():
kodiPl.add(additionalPlayurl, additionalListItem, kodiPl.add(additionalPlayurl, additionalListItem,
index=self.currentPosition) index=self.currentPosition)
self.pl.verifyPlaylist()
self.currentPosition += 1 self.currentPosition += 1
API.setPartNumber(0) API.setPartNumber(0)
@ -287,7 +304,10 @@ class PlaybackUtils():
introPlayurl = path + '?' + urlencode(params) introPlayurl = path + '?' + urlencode(params)
log.info("Adding Intro: %s" % introPlayurl) log.info("Adding Intro: %s" % introPlayurl)
self.pl.insertintoPlaylist(self.currentPosition, url=introPlayurl) PL.insert_into_Kodi_playlist(
self.pl,
self.currentPosition,
url=introPlayurl)
self.currentPosition += 1 self.currentPosition += 1
return True return True

View file

@ -3,7 +3,7 @@ from urllib import quote
import embydb_functions as embydb import embydb_functions as embydb
from downloadutils import DownloadUtils as DU from downloadutils import DownloadUtils as DU
from utils import JSONRPC, tryEncode from utils import window, JSONRPC, tryEncode
from PlexAPI import API from PlexAPI import API
############################################################################### ###############################################################################
@ -250,6 +250,57 @@ def move_playlist_item(playlist, before_pos, after_pos):
playlist.items.insert(after_pos, playlist.items.pop(before_pos)) playlist.items.insert(after_pos, playlist.items.pop(before_pos))
def get_PMS_playlist(playlist, playlist_id=None):
"""
Fetches the PMS playlist/playqueue as an XML. Pass in playlist_id if we
need to fetch a new playlist
Returns None if something went wrong
"""
playlist_id = playlist_id if playlist_id else playlist.ID
xml = DU().downloadUrl(
"{server}/%ss/%s" % (playlist.kind, playlist_id),
headerOptions={'Accept': 'application/xml'})
try:
xml.attrib['%sID' % playlist.kind]
except (AttributeError, KeyError):
xml = None
return xml
def refresh_playlist_from_PMS(playlist):
"""
Only updates the selected item from the PMS side (e.g.
playQueueSelectedItemID). Will NOT check whether items still make sense.
"""
xml = get_PMS_playlist(playlist)
try:
xml.attrib['%sVersion' % playlist.kind]
except:
log.error('Could not download Plex playlist.')
return
_get_playlist_details_from_xml(playlist, xml)
def update_playlist_from_PMS(playlist, playlist_id=None):
"""
Updates Kodi playlist using a new PMS playlist. Pass in playlist_id if we
need to fetch a new playqueue
"""
xml = get_PMS_playlist(playlist, playlist_id)
try:
xml.attrib['%sVersion' % playlist.kind]
except:
log.error('Could not download Plex playlist.')
return
# Clear our existing playlist and the associated Kodi playlist
playlist.clear()
# Set new values
_get_playlist_details_from_xml(playlist, xml)
for plex_item in xml:
playlist.items.append(add_to_Kodi_playlist(playlist, plex_item))
def delete_playlist_item(playlist, pos): def delete_playlist_item(playlist, pos):
""" """
Delete the item at position pos [int] Delete the item at position pos [int]
@ -333,13 +384,43 @@ def add_to_Kodi_playlist(playlist, xml_video_element):
return item return item
def insertintoPlaylist(self, def add_listitem_to_Kodi_playlist(playlist, listitem, file, index):
position, """
dbid=None, Adds an xbmc listitem to the Kodi playlist. Will be ignored by kodimonitor
mediatype=None, by settings window('plex_ignore_Playlist.OnAdd')
url=None): """
playlist.kodi_pl.add(file, listitem, index=index)
def add_dbid_to_Kodi_playlist(playlist, dbid=None, mediatype=None, url=None):
params = { params = {
'playlistid': self.playlistId, 'playlistid': playlist.playlistid
}
if dbid is not None:
params['item'] = {'%sid' % tryEncode(mediatype): int(dbid)}
else:
params['item'] = {'file': url}
log.debug(JSONRPC('Playlist.Add').execute(params))
def remove_from_Kodi_playlist(playlist, position):
"""
Removes the item at position from the Kodi playlist using JSON. Will be
ignored by kodimonitor by settings window('plex_ignore_Playlist.OnRemove')
"""
log.debug('Removing position %s from playlist %s' % (position, playlist))
log.debug(JSONRPC('Playlist.Remove').execute({
'playlistid': playlist.playlistid,
'position': position
}))
def insert_into_Kodi_playlist(playlist, position, dbid=None, mediatype=None,
url=None):
"""
"""
params = {
'playlistid': playlist.playlistid,
'position': position 'position': position
} }
if dbid is not None: if dbid is not None:
@ -349,64 +430,7 @@ def insertintoPlaylist(self,
JSONRPC('Playlist.Insert').execute(params) JSONRPC('Playlist.Insert').execute(params)
def removefromPlaylist(self, position): # NOT YET UPDATED!!
params = {
'playlistid': self.playlistId,
'position': position
}
log.debug(JSONRPC('Playlist.Remove').execute(params))
def get_PMS_playlist(playlist, playlist_id=None):
"""
Fetches the PMS playlist/playqueue as an XML. Pass in playlist_id if we
need to fetch a new playlist
Returns None if something went wrong
"""
playlist_id = playlist_id if playlist_id else playlist.ID
xml = DU().downloadUrl(
"{server}/%ss/%s" % (playlist.kind, playlist_id),
headerOptions={'Accept': 'application/xml'})
try:
xml.attrib['%sID' % playlist.kind]
except (AttributeError, KeyError):
xml = None
return xml
def refresh_playlist_from_PMS(playlist):
"""
Only updates the selected item from the PMS side (e.g.
playQueueSelectedItemID). Will NOT check whether items still make sense.
"""
xml = get_PMS_playlist(playlist)
try:
xml.attrib['%sVersion' % playlist.kind]
except:
log.error('Could not download Plex playlist.')
return
_get_playlist_details_from_xml(playlist, xml)
def update_playlist_from_PMS(playlist, playlist_id=None):
"""
Updates Kodi playlist using a new PMS playlist. Pass in playlist_id if we
need to fetch a new playqueue
"""
xml = get_PMS_playlist(playlist, playlist_id)
try:
xml.attrib['%sVersion' % playlist.kind]
except:
log.error('Could not download Plex playlist.')
return
# Clear our existing playlist and the associated Kodi playlist
playlist.clear()
# Set new values
_get_playlist_details_from_xml(playlist, xml)
for plex_item in xml:
playlist.items.append(add_to_Kodi_playlist(playlist, plex_item))
def _processItems(self, startitem, startPlayer=False): def _processItems(self, startitem, startPlayer=False):
startpos = None startpos = None

View file

@ -94,7 +94,7 @@ class Playqueue(Thread):
""" """
log.info('New playqueue received from the PMS, updating!') log.info('New playqueue received from the PMS, updating!')
PL.update_playlist_from_PMS(playqueue, playqueue_id) PL.update_playlist_from_PMS(playqueue, playqueue_id)
playqueue.repeat = repeat playqueue.repeat = 0 if not repeat else int(repeat)
log.debug('Updated playqueue: %s' % playqueue) log.debug('Updated playqueue: %s' % playqueue)
window('plex_customplaylist', value="true") window('plex_customplaylist', value="true")
@ -124,7 +124,7 @@ class Playqueue(Thread):
# Still need to get new playQueue from the server - don't know what has # Still need to get new playQueue from the server - don't know what has
# been selected # been selected
PL.refresh_playlist_from_PMS(playqueue) PL.refresh_playlist_from_PMS(playqueue)
playqueue.repeat = repeat playqueue.repeat = 0 if not repeat else int(repeat)
window('plex_customplaylist', value="true") window('plex_customplaylist', value="true")
if offset not in (None, "0"): if offset not in (None, "0"):
window('plex_customplaylist.seektime', window('plex_customplaylist.seektime',
@ -153,6 +153,13 @@ class Playqueue(Thread):
} }
""" """
playqueue = self.playqueues[data['playlistid']] playqueue = self.playqueues[data['playlistid']]
if data['item'].get('id') is None and data['item'].get('file') is None:
# Kodi screwed up. Let's try to get the data anyway
items = PL.get_kodi_playlist_items(playqueue)
if items[data['position']].get('id') is not None:
data['item']['id'] = items[data['position']].get('id')
else:
data['item']['file'] = items[data['position']].get('file')
if playqueue.PKC_playlist_edits: if playqueue.PKC_playlist_edits:
old = (data['item'].get('id') if data['item'].get('id') old = (data['item'].get('id') if data['item'].get('id')
else data['item'].get('file')) else data['item'].get('file'))
@ -212,17 +219,24 @@ class Playqueue(Thread):
# monitor! # monitor!
log.debug('New playqueue: %s' % playqueue) log.debug('New playqueue: %s' % playqueue)
def run(self): def init_playlists(self):
threadStopped = self.threadStopped """
threadSuspended = self.threadSuspended Initializes the playqueues with already existing items.
log.info("----===## Starting PlayQueue client ##===----") Called on startup AND for addon paths!
# Initialize the playqueues, if Kodi already got items in them """
for playqueue in self.playqueues: for playqueue in self.playqueues:
for i, item in enumerate(PL.get_kodi_playlist_items(playqueue)): for i, item in enumerate(PL.get_kodi_playlist_items(playqueue)):
if i == 0: if i == 0:
PL.init_Plex_playlist(playqueue, kodi_item=item) PL.init_Plex_playlist(playqueue, kodi_item=item)
else: else:
PL.add_playlist_item(playqueue, item, i) PL.add_playlist_item(playqueue, item, i)
def run(self):
threadStopped = self.threadStopped
threadSuspended = self.threadSuspended
log.info("----===## Starting PlayQueue client ##===----")
# Initialize the playqueues, if Kodi already got items in them
self.init_playlists()
while not threadStopped(): while not threadStopped():
while threadSuspended(): while threadSuspended():
if threadStopped(): if threadStopped():