PlexKodiConnect/resources/lib/plexnet/media.py

229 lines
6.1 KiB
Python
Raw Normal View History

2018-09-30 21:16:17 +10:00
import plexobjects
import plexstream
import plexrequest
import util
METADATA_RELATED_TRAILER = 1
METADATA_RELATED_DELETED_SCENE = 2
METADATA_RELATED_INTERVIEW = 3
METADATA_RELATED_MUSIC_VIDEO = 4
METADATA_RELATED_BEHIND_THE_SCENES = 5
METADATA_RELATED_SCENE_OR_SAMPLE = 6
METADATA_RELATED_LIVE_MUSIC_VIDEO = 7
METADATA_RELATED_LYRIC_MUSIC_VIDEO = 8
METADATA_RELATED_CONCERT = 9
METADATA_RELATED_FEATURETTE = 10
METADATA_RELATED_SHORT = 11
METADATA_RELATED_OTHER = 12
class MediaItem(plexobjects.PlexObject):
def getIdentifier(self):
identifier = self.get('identifier') or None
if identifier is None:
identifier = self.container.identifier
# HACK
# PMS doesn't return an identifier for playlist items. If we haven't found
# an identifier and the key looks like a library item, then we pretend like
# the identifier was set.
#
if identifier is None: # Modified from Roku code which had no check for None with iPhoto - is that right?
if self.key.startswith('/library/metadata'):
identifier = "com.plexapp.plugins.library"
elif self.isIPhoto():
identifier = "com.plexapp.plugins.iphoto"
return identifier
def getQualityType(self, server=None):
if self.isOnlineItem():
return util.QUALITY_ONLINE
if not server:
server = self.getServer()
return util.QUALITY_LOCAL if server.isLocalConnection() else util.QUALITY_REMOTE
def delete(self):
if not self.ratingKey:
return
req = plexrequest.PlexRequest(self.server, '/library/metadata/{0}'.format(self.ratingKey), method='DELETE')
req.getToStringWithTimeout(10)
self.deleted = req.wasOK()
return self.deleted
def exists(self):
if self.deleted:
return False
data = self.server.query('/library/metadata/{0}'.format(self.ratingKey))
return data.attrib.get('size') != '0'
# req = plexrequest.PlexRequest(self.server, '/library/metadata/{0}'.format(self.ratingKey), method='HEAD')
# req.getToStringWithTimeout(10)
# return not req.wasNotFound()
def fixedDuration(self):
duration = self.duration.asInt()
if duration < 1000:
duration *= 60000
return duration
class Media(plexobjects.PlexObject):
TYPE = 'Media'
def __init__(self, data, initpath=None, server=None, video=None):
plexobjects.PlexObject.__init__(self, data, initpath=initpath, server=server)
self.video = video
self.parts = [MediaPart(elem, initpath=self.initpath, server=self.server, media=self) for elem in data]
def __repr__(self):
title = self.video.title.replace(' ', '.')[0:20]
return '<%s:%s>' % (self.__class__.__name__, title.encode('utf8'))
class MediaPart(plexobjects.PlexObject):
TYPE = 'Part'
def __init__(self, data, initpath=None, server=None, media=None):
plexobjects.PlexObject.__init__(self, data, initpath=initpath, server=server)
self.media = media
self.streams = [MediaPartStream.parse(e, initpath=self.initpath, server=server, part=self) for e in data if e.tag == 'Stream']
def __repr__(self):
return '<%s:%s>' % (self.__class__.__name__, self.id)
def selectedStream(self, stream_type):
streams = filter(lambda x: stream_type == x.type, self.streams)
selected = list(filter(lambda x: x.selected is True, streams))
if len(selected) == 0:
return None
return selected[0]
class MediaPartStream(plexstream.PlexStream):
TYPE = None
STREAMTYPE = None
def __init__(self, data, initpath=None, server=None, part=None):
plexobjects.PlexObject.__init__(self, data, initpath, server)
self.part = part
@staticmethod
def parse(data, initpath=None, server=None, part=None):
STREAMCLS = {
1: VideoStream,
2: AudioStream,
3: SubtitleStream
}
stype = int(data.attrib.get('streamType'))
cls = STREAMCLS.get(stype, MediaPartStream)
return cls(data, initpath=initpath, server=server, part=part)
def __repr__(self):
return '<%s:%s>' % (self.__class__.__name__, self.id)
class VideoStream(MediaPartStream):
TYPE = 'videostream'
STREAMTYPE = plexstream.PlexStream.TYPE_VIDEO
class AudioStream(MediaPartStream):
TYPE = 'audiostream'
STREAMTYPE = plexstream.PlexStream.TYPE_AUDIO
class SubtitleStream(MediaPartStream):
TYPE = 'subtitlestream'
STREAMTYPE = plexstream.PlexStream.TYPE_SUBTITLE
class TranscodeSession(plexobjects.PlexObject):
TYPE = 'TranscodeSession'
class MediaTag(plexobjects.PlexObject):
TYPE = None
ID = 'None'
def __repr__(self):
tag = self.tag.replace(' ', '.')[0:20]
return '<%s:%s:%s>' % (self.__class__.__name__, self.id, tag)
def __eq__(self, other):
if other.__class__ != self.__class__:
return False
return self.id == other.id
def __ne__(self, other):
return not self.__eq__(other)
class Collection(MediaTag):
TYPE = 'Collection'
FILTER = 'collection'
class Country(MediaTag):
TYPE = 'Country'
FILTER = 'country'
class Director(MediaTag):
TYPE = 'Director'
FILTER = 'director'
ID = '4'
class Genre(MediaTag):
TYPE = 'Genre'
FILTER = 'genre'
ID = '1'
class Mood(MediaTag):
TYPE = 'Mood'
FILTER = 'mood'
class Producer(MediaTag):
TYPE = 'Producer'
FILTER = 'producer'
class Role(MediaTag):
TYPE = 'Role'
FILTER = 'actor'
ID = '6'
def sectionRoles(self):
hubs = self.server.hubs(count=10, search_query=self.tag)
for hub in hubs:
if hub.type == 'actor':
break
else:
return None
roles = []
for actor in hub.items:
if actor.id == self.id:
roles.append(actor)
return roles or None
class Similar(MediaTag):
TYPE = 'Similar'
FILTER = 'similar'
class Writer(MediaTag):
TYPE = 'Writer'
FILTER = 'writer'