Fix playback sometimes not starting and UnicodeEncodeError for logging

- Fixes #520
This commit is contained in:
croneter 2018-08-05 14:44:24 +02:00
parent a46fc22fb2
commit 11a66a8465
3 changed files with 74 additions and 68 deletions

View file

@ -38,9 +38,11 @@ def config():
class LogHandler(logging.StreamHandler):
def __init__(self):
logging.StreamHandler.__init__(self)
self.setFormatter(logging.Formatter(fmt="%(name)s: %(message)s"))
self.setFormatter(logging.Formatter(fmt=b"%(name)s: %(message)s"))
def emit(self, record):
if isinstance(record.msg, unicode):
record.msg = record.msg.encode('utf-8')
try:
xbmc.log(self.format(record), level=LEVELS[record.levelno])
except UnicodeEncodeError:

View file

@ -33,36 +33,7 @@ class PlaylistError(Exception):
pass
class PlaylistObjectBaseclase(object):
"""
Base class
"""
def __init__(self):
self.id = None
self.type = None
def __repr__(self):
"""
Print the playlist, e.g. to log. Returns unicode
"""
answ = '{\'%s\': {\'id\': %s, ' % (self.__class__.__name__, self.id)
# For some reason, can't use dir directly
for key in self.__dict__:
if key in ('id', 'kodi_pl'):
continue
if isinstance(getattr(self, key), str):
answ += '\'%s\': \'%s\', ' % (key,
utils.try_decode(getattr(self,
key)))
elif isinstance(getattr(self, key), unicode):
answ += '\'%s\': \'%s\', ' % (key, getattr(self, key))
else:
# e.g. int
answ += '\'%s\': %s, ' % (key, unicode(getattr(self, key)))
return answ + '}}'
class Playqueue_Object(PlaylistObjectBaseclase):
class Playqueue_Object(object):
"""
PKC object to represent PMS playQueues and Kodi playlist for queueing
@ -85,6 +56,8 @@ class Playqueue_Object(PlaylistObjectBaseclase):
kind = 'playQueue'
def __init__(self):
self.id = None
self.type = None
self.playlistid = None
self.kodi_pl = None
self.items = []
@ -104,7 +77,25 @@ class Playqueue_Object(PlaylistObjectBaseclase):
# To keep track if Kodi playback was initiated from a Kodi playlist
# There are a couple of pitfalls, unfortunately...
self.kodi_playlist_playback = False
PlaylistObjectBaseclase.__init__(self)
def __repr__(self):
answ = ("{{"
"'playlistid': {self.playlistid}, "
"'id': {self.id}, "
"'version': {self.version}, "
"'type': '{self.type}', "
"'selectedItemID': {self.selectedItemID}, "
"'selectedItemOffset': {self.selectedItemOffset}, "
"'shuffled': {self.shuffled}, "
"'repeat': {self.repeat}, "
"'kodi_playlist_playback': {self.kodi_playlist_playback}, "
"'pkc_edit': {self.pkc_edit}, ".format(self=self))
answ = answ.encode('utf-8')
# Since list.__repr__ will return string, not unicode
return answ + b"'items': {self.items}}}".format(self=self)
def __str__(self):
return self.__repr__()
def is_pkc_clear(self):
"""
@ -181,28 +172,27 @@ class Playlist_Item(object):
self.force_transcode = False
def __repr__(self):
"""
Print the playlist item, e.g. to log. Returns unicode
"""
answ = ('{\'%s\': {\'id\': \'%s\', \'plex_id\': \'%s\', '
% (self.__class__.__name__, self.id, self.plex_id))
for key in self.__dict__:
if key in ('id', 'plex_id', 'xml'):
continue
if isinstance(getattr(self, key), str):
answ += '\'%s\': \'%s\', ' % (key,
utils.try_decode(getattr(self,
key)))
elif isinstance(getattr(self, key), unicode):
answ += '\'%s\': \'%s\', ' % (key, getattr(self, key))
else:
# e.g. int
answ += '\'%s\': %s, ' % (key, unicode(getattr(self, key)))
if self.xml is None:
answ += '\'xml\': None}}'
else:
answ += '\'xml\': \'%s\'}}' % self.xml.tag
return answ
answ = ("{{"
"'id': {self.id}, "
"'plex_id': {self.plex_id}, "
"'plex_type': '{self.plex_type}', "
"'plex_uuid': '{self.plex_uuid}', "
"'kodi_id': {self.kodi_id}, "
"'kodi_type': '{self.kodi_type}', "
"'file': '{self.file}', "
"'uri': '{self.uri}', "
"'guid': '{self.guid}', "
"'playmethod': '{self.playmethod}', "
"'playcount': {self.playcount}, "
"'offset': {self.offset}, "
"'force_transcode': {self.force_transcode}, "
"'part': {self.part}, ".format(self=self))
answ = answ.encode('utf-8')
# etree xml.__repr__() could return string, not unicode
return answ + b"'xml': \"{self.xml}\"}}".format(self=self)
def __str__(self):
return self.__repr__()
def plex_stream_index(self, kodi_stream_index, stream_type):
"""
@ -412,12 +402,13 @@ def get_playlist_details_from_xml(playlist, xml):
Raises PlaylistError if something went wrong.
"""
playlist.id = xml.get('%sID' % playlist.kind)
playlist.version = xml.get('%sVersion' % playlist.kind)
playlist.shuffled = xml.get('%sShuffled' % playlist.kind)
playlist.selectedItemID = xml.get('%sSelectedItemID' % playlist.kind)
playlist.id = xml.get('%sID' % playlist.kind).decode('utf-8')
playlist.version = xml.get('%sVersion' % playlist.kind).decode('utf-8')
playlist.shuffled = xml.get('%sShuffled' % playlist.kind).decode('utf-8')
playlist.selectedItemID = xml.get(
'%sSelectedItemID' % playlist.kind).decode('utf-8')
playlist.selectedItemOffset = xml.get(
'%sSelectedItemOffset' % playlist.kind)
'%sSelectedItemOffset' % playlist.kind).decode('utf-8')
LOG.debug('Updated playlist from xml: %s', playlist)
@ -781,4 +772,4 @@ def get_plextype_from_xml(xml):
except (TypeError, IndexError, AttributeError):
LOG.error('Could not get plex metadata for plex id %s', plex_id)
return
return new_xml[0].attrib.get('type')
return new_xml[0].attrib.get('type').decode('utf-8')

View file

@ -53,6 +53,19 @@ LOG = getLogger('PLEX.plex_api')
###############################################################################
def _unicode_or_none(value):
"""
Tries to decode value to unicode. Returns None if this fails
"""
try:
return value.decode('utf-8')
except TypeError:
# e.g. Android TV's Python
return value.decode()
except AttributeError:
pass
class API(object):
"""
API(item)
@ -77,9 +90,10 @@ class API(object):
def plex_type(self):
"""
Returns the type of media, e.g. 'movie' or 'clip' for trailers
Returns the type of media, e.g. 'movie' or 'clip' for trailers as
Unicode or None.
"""
return self.item.get('type')
return _unicode_or_none(self.item.get('type'))
def playlist_type(self):
"""
@ -104,9 +118,9 @@ class API(object):
def plex_id(self):
"""
Returns the Plex ratingKey such as '246922' as a string or None
Returns the Plex ratingKey such as '246922' as Unicode or None
"""
return self.item.get('ratingKey')
return _unicode_or_none(self.item.get('ratingKey'))
def path(self, force_first_media=True, force_addon=False,
direct_paths=None):
@ -664,12 +678,11 @@ class API(object):
def item_id(self):
"""
Returns current playQueueItemID or if unsuccessful the playListItemID
as Unicode.
If not found, None is returned
"""
answ = self.item.get('playQueueItemID')
if answ is None:
answ = self.item.get('playListItemID')
return answ
return _unicode_or_none(self.item.get('playQueueItemID') or
self.item.get('playListItemID'))
def _data_from_part_or_media(self, key):
"""