Fix episode widget resume not working (add-on paths)

- Hack alert, really...
- Need to reset the Kodi DB
This commit is contained in:
croneter 2018-05-26 18:54:20 +02:00
parent ac7b7bb96d
commit 5c33f3c02a
8 changed files with 97 additions and 42 deletions

View file

@ -99,14 +99,15 @@ class API(object):
"""
return self.item.get('ratingKey')
def path(self, force_first_media=True):
def path(self, force_first_media=True, force_addon=False):
"""
Returns a "fully qualified path": add-on paths or direct paths
depending on the current settings. Will NOT valide the playurl
Returns unicode or None if something went wrong.
"""
filename = self.file_path(force_first_media=force_first_media)
if not state.DIRECT_PATHS or self.plex_type() == v.PLEX_TYPE_CLIP:
if (not state.DIRECT_PATHS or force_addon
or self.plex_type() == v.PLEX_TYPE_CLIP):
if filename and '/' in filename:
filename = filename.rsplit('/', 1)
elif filename:
@ -116,11 +117,14 @@ class API(object):
except (TypeError, IndexError):
filename = None
# Set plugin path and media flags using real filename
path = ('plugin://%s/?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (v.ADDON_TYPE[self.plex_type()],
self.plex_id(),
self.plex_type(),
filename))
if self.plex_type() == v.PLEX_TYPE_EPISODE:
# need to include the plex show id in the path
path = ('plugin://plugin.video.plexkodiconnect.tvshows/%s/'
% self.grandparent_id())
else:
path = 'plugin://%s/' % v.ADDON_TYPE[self.plex_type()]
path = ('%s?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (path, self.plex_id(), self.plex_type(), filename))
else:
# Direct paths is set the Kodi way
path = self.validate_playurl(filename,

View file

@ -155,10 +155,7 @@ class ContextMenu(object):
v.KODI_PLAYLIST_TYPE_FROM_KODI_TYPE[self.kodi_type])
playqueue.clear()
state.CONTEXT_MENU_PLAY = True
handle = ('plugin://%s/?plex_id=%s&plex_type=%s&mode=play'
% (v.ADDON_TYPE[self.plex_type],
self.plex_id,
self.plex_type))
handle = self.api.path(force_first_media=False, force_addon=True)
xbmc.executebuiltin('RunPlugin(%s)' % handle)
def _extras(self):

View file

@ -552,14 +552,7 @@ def getOnDeck(viewid, mediatype, tagname, limit):
listitem = api.create_listitem(
append_show_title=append_show_title,
append_sxxexx=append_sxxexx)
if directpaths:
url = api.file_path(force_first_media=True)
else:
url = ('plugin://%s.tvshows/?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (v.ADDON_ID,
api.plex_id(),
api.plex_type(),
api.file_name(force_first_media=True)))
url = api.path()
if api.resume_point():
listitem.setProperty('resumetime', str(api.resume_point()))
xbmcplugin.addDirectoryItem(
@ -829,11 +822,7 @@ def __build_item(xml_element):
elif api.plex_type() == v.PLEX_TYPE_PHOTO:
url = api.get_picture_path()
else:
url = 'plugin://%s/?plex_id=%s&plex_type=%s&mode=play&filename=%s' \
% (v.ADDON_TYPE[api.plex_type()],
api.plex_id(),
api.plex_type(),
api.file_name(force_first_media=True))
url = api.path()
if api.resume_point():
listitem.setProperty('resumetime', str(api.resume_point()))
xbmcplugin.addDirectoryItem(handle=HANDLE,

View file

@ -147,21 +147,22 @@ class Items(object):
userdata['Resume'],
userdata['Runtime'],
userdata['PlayCount'],
userdata['LastPlayedDate'])
userdata['LastPlayedDate'],
api.plex_type())
if v.KODIVERSION >= 17:
self.kodi_db.update_userrating(db_item[0],
db_item[4],
userdata['UserRating'])
def updatePlaystate(self, mark_played, view_count, resume, duration,
file_id, lastViewedAt):
file_id, lastViewedAt, plex_type):
"""
Use with websockets, not xml
"""
# If the playback was stopped, check whether we need to increment the
# playcount. PMS won't tell us the playcount via websockets
LOG.debug('Set playstate for file_id %s: viewcount: %s, resume: %s',
file_id, view_count, resume)
LOG.debug('Playstate file_id %s: viewcount: %s, resume: %s, type: %s',
file_id, view_count, resume, plex_type)
if mark_played:
LOG.info('Marking as completely watched in Kodi')
try:
@ -174,7 +175,8 @@ class Items(object):
resume,
duration,
view_count,
lastViewedAt)
lastViewedAt,
plex_type)
class Movies(Items):
@ -448,7 +450,12 @@ class Movies(Items):
# Add any sets from Plex collection tags
self.kodi_db.addSets(movieid, collections, kodicursor)
# Process playstates
self.kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
self.kodi_db.addPlaystate(fileid,
resume,
runtime,
playcount,
dateplayed,
v.PLEX_TYPE_MOVIE)
def remove(self, plex_id):
"""
@ -584,7 +591,8 @@ class TVShows(Items):
# Set plugin path
toplevelpath = "plugin://%s.tvshows/" % v.ADDON_ID
path = "%s%s/" % (toplevelpath, itemid)
toppathid = self.kodi_db.get_path(toplevelpath)
# Do NOT set a parent id because addon-path cannot be "stacked"
toppathid = None
pathid = self.kodi_db.add_video_path(path,
date_added=api.date_created(),
@ -989,7 +997,24 @@ class TVShows(Items):
resume,
runtime,
playcount,
dateplayed)
dateplayed,
None) # Do send None, we check here
if not state.DIRECT_PATHS:
# need to set a SECOND file entry for a path without plex show id
filename = api.file_name(force_first_media=True)
path = 'plugin://%s.tvshows/' % v.ADDON_ID
# Filename is exactly the same, WITH plex show id!
filename = ('%s%s/?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (path, series_id, itemid, v.PLEX_TYPE_EPISODE,
filename))
pathid = self.kodi_db.add_video_path(path)
fileid = self.kodi_db.add_file(filename, pathid, dateadded)
self.kodi_db.addPlaystate(fileid,
resume,
runtime,
playcount,
dateplayed,
None) # Do send None - 2nd entry
@catch_exceptions(warnuser=True)
def remove(self, plex_id):
@ -1093,7 +1118,7 @@ class TVShows(Items):
Remove an episode, and episode only from the Kodi DB (not Plex DB)
"""
self.kodi_db.modify_people(kodi_id, v.KODI_TYPE_EPISODE)
self.kodi_db.remove_file(file_id)
self.kodi_db.remove_file(file_id, plex_type=v.PLEX_TYPE_EPISODE)
self.artwork.delete_artwork(kodi_id,
v.KODI_TYPE_EPISODE,
self.kodicursor)

View file

@ -8,6 +8,7 @@ from sqlite3 import IntegrityError
import artwork
from utils import kodi_sql, try_decode, unix_timestamp, unix_date_to_kodi
import variables as v
import state
###############################################################################
@ -237,13 +238,31 @@ class KodiDBMethods(object):
show_id = None
return show_id
def remove_file(self, file_id, remove_orphans=True):
def remove_file(self, file_id, remove_orphans=True, plex_type=None):
"""
Removes the entry for file_id from the files table. Will also delete
entries from the associated tables: bookmark, settings, streamdetails.
If remove_orphans is true, this method will delete any orphaned path
entries in the Kodi path table
Passing plex_type = v.PLEX_TYPE_EPISODE deletes any secondary files for
add-on paths
"""
if not state.DIRECT_PATHS and plex_type == v.PLEX_TYPE_EPISODE:
# Hack for the 2 entries for episodes for addon paths
query = 'SELECT strFilename FROM files WHERE idFile = ? LIMIT 1'
self.cursor.execute(query, (file_id, ))
filename = self.cursor.fetchone()
if not filename:
LOG.error('Could not find file_id %s', file_id)
return
query = 'SELECT idFile FROM files WHERE strFilename = ? LIMIT 2'
self.cursor.execute(query, (filename[0], ))
file_ids = self.cursor.fetchall()
for new_id in file_ids:
self.remove_file(new_id[0], remove_orphans=remove_orphans)
return
self.cursor.execute('SELECT idPath FROM files WHERE idFile = ? LIMIT 1',
(file_id,))
try:
@ -708,7 +727,29 @@ class KodiDBMethods(object):
return answ
def addPlaystate(self, file_id, resume_seconds, total_seconds, playcount,
dateplayed):
dateplayed, plex_type):
if not state.DIRECT_PATHS and plex_type == v.PLEX_TYPE_EPISODE:
# Need to make sure to set a SECOND bookmark entry for another,
# second file_id that points to the path .tvshows instead of
# .tvshows/<plex show id/!
query = 'SELECT strFilename FROM files WHERE idFile = ? LIMIT 1'
self.cursor.execute(query, (file_id, ))
filename = self.cursor.fetchone()
if not filename:
LOG.error('Could not find fileid %s in Kodi DB', file_id)
raise RuntimeError
query = 'SELECT idFile FROM files WHERE strFilename = ? LIMIT 2'
self.cursor.execute(query, (filename[0], ))
file_ids = self.cursor.fetchall()
if len(file_ids) != 2:
LOG.error('Expected to find 2 file ids but found %s',
len(file_ids))
raise RuntimeError
for new_id in file_ids:
self.addPlaystate(new_id[0], resume_seconds, total_seconds,
playcount, dateplayed, None)
return
# Delete existing resume point
self.cursor.execute('DELETE FROM bookmark WHERE idFile = ?', (file_id,))
# Set watched count

View file

@ -523,7 +523,8 @@ def _record_playstate(status, ended):
time,
totaltime,
playcount,
last_played)
last_played,
status['plex_type'])
# Hack to force "in progress" widget to appear if it wasn't visible before
if (state.FORCE_RELOAD_SKIN and
xbmc.getCondVisibility('Window.IsVisible(Home.xml)')):

View file

@ -1357,12 +1357,14 @@ class LibrarySync(Thread):
item_fkt = getattr(itemtypes,
v.ITEMTYPE_FROM_KODITYPE[session['kodi_type']])
with item_fkt() as fkt:
plex_type = v.PLEX_TYPE_FROM_KODI_TYPE[session['kodi_type']]
fkt.updatePlaystate(mark_played,
session['viewCount'],
resume,
session['duration'],
session['file_id'],
utils.unix_date_to_kodi(utils.unix_timestamp()))
utils.unix_date_to_kodi(utils.unix_timestamp()),
plex_type)
def sync_fanart(self, missing_only=True, refresh=False):
"""

View file

@ -241,11 +241,7 @@ def _prep_playlist_stack(xml):
api.set_part_number(part)
if kodi_id is None:
# Need to redirect again to PKC to conclude playback
path = ('plugin://%s/?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (v.ADDON_TYPE[api.plex_type()],
api.plex_id(),
api.plex_type(),
api.file_name(force_first_media=True)))
path = api.path()
listitem = api.create_listitem()
listitem.setPath(try_encode(path))
else: