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): class LogHandler(logging.StreamHandler):
def __init__(self): def __init__(self):
logging.StreamHandler.__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): def emit(self, record):
if isinstance(record.msg, unicode):
record.msg = record.msg.encode('utf-8')
try: try:
xbmc.log(self.format(record), level=LEVELS[record.levelno]) xbmc.log(self.format(record), level=LEVELS[record.levelno])
except UnicodeEncodeError: except UnicodeEncodeError:

View file

@ -33,36 +33,7 @@ class PlaylistError(Exception):
pass pass
class PlaylistObjectBaseclase(object): class Playqueue_Object(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):
""" """
PKC object to represent PMS playQueues and Kodi playlist for queueing PKC object to represent PMS playQueues and Kodi playlist for queueing
@ -85,6 +56,8 @@ class Playqueue_Object(PlaylistObjectBaseclase):
kind = 'playQueue' kind = 'playQueue'
def __init__(self): def __init__(self):
self.id = None
self.type = None
self.playlistid = None self.playlistid = None
self.kodi_pl = None self.kodi_pl = None
self.items = [] self.items = []
@ -104,7 +77,25 @@ class Playqueue_Object(PlaylistObjectBaseclase):
# To keep track if Kodi playback was initiated from a Kodi playlist # To keep track if Kodi playback was initiated from a Kodi playlist
# There are a couple of pitfalls, unfortunately... # There are a couple of pitfalls, unfortunately...
self.kodi_playlist_playback = False 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): def is_pkc_clear(self):
""" """
@ -181,28 +172,27 @@ class Playlist_Item(object):
self.force_transcode = False self.force_transcode = False
def __repr__(self): def __repr__(self):
""" answ = ("{{"
Print the playlist item, e.g. to log. Returns unicode "'id': {self.id}, "
""" "'plex_id': {self.plex_id}, "
answ = ('{\'%s\': {\'id\': \'%s\', \'plex_id\': \'%s\', ' "'plex_type': '{self.plex_type}', "
% (self.__class__.__name__, self.id, self.plex_id)) "'plex_uuid': '{self.plex_uuid}', "
for key in self.__dict__: "'kodi_id': {self.kodi_id}, "
if key in ('id', 'plex_id', 'xml'): "'kodi_type': '{self.kodi_type}', "
continue "'file': '{self.file}', "
if isinstance(getattr(self, key), str): "'uri': '{self.uri}', "
answ += '\'%s\': \'%s\', ' % (key, "'guid': '{self.guid}', "
utils.try_decode(getattr(self, "'playmethod': '{self.playmethod}', "
key))) "'playcount': {self.playcount}, "
elif isinstance(getattr(self, key), unicode): "'offset': {self.offset}, "
answ += '\'%s\': \'%s\', ' % (key, getattr(self, key)) "'force_transcode': {self.force_transcode}, "
else: "'part': {self.part}, ".format(self=self))
# e.g. int answ = answ.encode('utf-8')
answ += '\'%s\': %s, ' % (key, unicode(getattr(self, key))) # etree xml.__repr__() could return string, not unicode
if self.xml is None: return answ + b"'xml': \"{self.xml}\"}}".format(self=self)
answ += '\'xml\': None}}'
else: def __str__(self):
answ += '\'xml\': \'%s\'}}' % self.xml.tag return self.__repr__()
return answ
def plex_stream_index(self, kodi_stream_index, stream_type): 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. Raises PlaylistError if something went wrong.
""" """
playlist.id = xml.get('%sID' % playlist.kind) playlist.id = xml.get('%sID' % playlist.kind).decode('utf-8')
playlist.version = xml.get('%sVersion' % playlist.kind) playlist.version = xml.get('%sVersion' % playlist.kind).decode('utf-8')
playlist.shuffled = xml.get('%sShuffled' % playlist.kind) playlist.shuffled = xml.get('%sShuffled' % playlist.kind).decode('utf-8')
playlist.selectedItemID = xml.get('%sSelectedItemID' % playlist.kind) playlist.selectedItemID = xml.get(
'%sSelectedItemID' % playlist.kind).decode('utf-8')
playlist.selectedItemOffset = xml.get( playlist.selectedItemOffset = xml.get(
'%sSelectedItemOffset' % playlist.kind) '%sSelectedItemOffset' % playlist.kind).decode('utf-8')
LOG.debug('Updated playlist from xml: %s', playlist) LOG.debug('Updated playlist from xml: %s', playlist)
@ -781,4 +772,4 @@ def get_plextype_from_xml(xml):
except (TypeError, IndexError, AttributeError): except (TypeError, IndexError, AttributeError):
LOG.error('Could not get plex metadata for plex id %s', plex_id) LOG.error('Could not get plex metadata for plex id %s', plex_id)
return 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): class API(object):
""" """
API(item) API(item)
@ -77,9 +90,10 @@ class API(object):
def plex_type(self): 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): def playlist_type(self):
""" """
@ -104,9 +118,9 @@ class API(object):
def plex_id(self): 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, def path(self, force_first_media=True, force_addon=False,
direct_paths=None): direct_paths=None):
@ -664,12 +678,11 @@ class API(object):
def item_id(self): def item_id(self):
""" """
Returns current playQueueItemID or if unsuccessful the playListItemID Returns current playQueueItemID or if unsuccessful the playListItemID
as Unicode.
If not found, None is returned If not found, None is returned
""" """
answ = self.item.get('playQueueItemID') return _unicode_or_none(self.item.get('playQueueItemID') or
if answ is None: self.item.get('playListItemID'))
answ = self.item.get('playListItemID')
return answ
def _data_from_part_or_media(self, key): def _data_from_part_or_media(self, key):
""" """