Fixes to playQueues for Addon paths
This commit is contained in:
parent
49b5131dbb
commit
eec2c10cb4
4 changed files with 152 additions and 89 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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():
|
||||||
|
|
Loading…
Reference in a new issue