mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-10 14:14:19 +00:00
Create Playable object to put function specific to media that is playable like getStreamURL etc..
This commit is contained in:
parent
e81f2506e9
commit
50ac2f55e5
4 changed files with 63 additions and 79 deletions
|
@ -3,10 +3,14 @@
|
|||
PlexAPI Audio
|
||||
"""
|
||||
from plexapi import media, utils
|
||||
from plexapi.utils import Playable, PlexPartialObject
|
||||
NA = utils.NA
|
||||
|
||||
|
||||
class Audio(utils.PlexPartialObject):
|
||||
class Audio(PlexPartialObject):
|
||||
|
||||
def __init__(self, server, data, initpath):
|
||||
super(Audio, self).__init__(data, initpath, server)
|
||||
|
||||
def _loadData(self, data):
|
||||
self.addedAt = utils.toDatetime(data.attrib.get('addedAt', NA))
|
||||
|
@ -23,6 +27,13 @@ class Audio(utils.PlexPartialObject):
|
|||
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt', NA))
|
||||
self.viewCount = utils.cast(int, data.attrib.get('viewCount', 0))
|
||||
|
||||
@property
|
||||
def thumbUrl(self):
|
||||
return self.server.url(self.thumb)
|
||||
|
||||
def refresh(self):
|
||||
self.server.query('%s/refresh' % self.key, method=self.server.session.put)
|
||||
|
||||
|
||||
@utils.register_libtype
|
||||
class Artist(Audio):
|
||||
|
@ -32,7 +43,7 @@ class Artist(Audio):
|
|||
super(Artist, self)._loadData(data)
|
||||
self.art = data.attrib.get('art', NA)
|
||||
self.guid = data.attrib.get('guid', NA)
|
||||
self.key = self.key.replace('/children', '') # plex bug? http://bit.ly/1Sc2J3V
|
||||
self.key = self.key.replace('/children', '') # FIX_BUG_50
|
||||
self.location = utils.findLocation(data)
|
||||
if self.isFullObject():
|
||||
self.countries = [media.Country(self.server, e) for e in data if e.tag == media.Country.TYPE]
|
||||
|
@ -40,32 +51,24 @@ class Artist(Audio):
|
|||
self.similar = [media.Similar(self.server, e) for e in data if e.tag == media.Similar.TYPE]
|
||||
|
||||
def albums(self):
|
||||
path = '/library/metadata/%s/children' % self.ratingKey
|
||||
path = '%s/children' % self.key
|
||||
return utils.listItems(self.server, path, Album.TYPE)
|
||||
|
||||
def album(self, title):
|
||||
path = '/library/metadata/%s/children' % self.ratingKey
|
||||
path = '%s/children' % self.key
|
||||
return utils.findItem(self.server, path, title)
|
||||
|
||||
def tracks(self, watched=None):
|
||||
leavesKey = '/library/metadata/%s/allLeaves' % self.ratingKey
|
||||
return utils.listItems(self.server, leavesKey, watched=watched)
|
||||
path = '%s/allLeaves' % self.key
|
||||
return utils.listItems(self.server, path, watched=watched)
|
||||
|
||||
def track(self, title):
|
||||
path = '/library/metadata/%s/allLeaves' % self.ratingKey
|
||||
path = '%s/allLeaves' % self.key
|
||||
return utils.findItem(self.server, path, title)
|
||||
|
||||
def get(self, title):
|
||||
return self.track(title)
|
||||
|
||||
def isFullObject(self):
|
||||
# plex bug? http://bit.ly/1Sc2J3V
|
||||
fixed_key = self.key.replace('/children', '')
|
||||
return self.initpath == fixed_key
|
||||
|
||||
def refresh(self):
|
||||
self.server.query('/library/metadata/%s/refresh' % self.ratingKey)
|
||||
|
||||
|
||||
@utils.register_libtype
|
||||
class Album(Audio):
|
||||
|
@ -74,7 +77,7 @@ class Album(Audio):
|
|||
def _loadData(self, data):
|
||||
super(Album, self)._loadData(data)
|
||||
self.art = data.attrib.get('art', NA)
|
||||
self.key = self.key.replace('/children', '') # plex bug? http://bit.ly/1Sc2J3V
|
||||
self.key = self.key.replace('/children', '') # FIX_BUG_50
|
||||
self.originallyAvailableAt = utils.toDatetime(data.attrib.get('originallyAvailableAt', NA), '%Y-%m-%d')
|
||||
self.parentKey = data.attrib.get('parentKey', NA)
|
||||
self.parentRatingKey = data.attrib.get('parentRatingKey', NA)
|
||||
|
@ -86,21 +89,16 @@ class Album(Audio):
|
|||
self.genres = [media.Genre(self.server, e) for e in data if e.tag == media.Genre.TYPE]
|
||||
|
||||
def tracks(self, watched=None):
|
||||
childrenKey = '/library/metadata/%s/children' % self.ratingKey
|
||||
return utils.listItems(self.server, childrenKey, watched=watched)
|
||||
path = '%s/children' % self.key
|
||||
return utils.listItems(self.server, path, watched=watched)
|
||||
|
||||
def track(self, title):
|
||||
path = '/library/metadata/%s/children' % self.ratingKey
|
||||
path = '%s/children' % self.key
|
||||
return utils.findItem(self.server, path, title)
|
||||
|
||||
def get(self, title):
|
||||
return self.track(title)
|
||||
|
||||
def isFullObject(self):
|
||||
# plex bug? http://bit.ly/1Sc2J3V
|
||||
fixed_key = self.key.replace('/children', '')
|
||||
return self.initpath == fixed_key
|
||||
|
||||
def artist(self):
|
||||
return utils.listItems(self.server, self.parentKey)[0]
|
||||
|
||||
|
@ -112,7 +110,7 @@ class Album(Audio):
|
|||
|
||||
|
||||
@utils.register_libtype
|
||||
class Track(Audio):
|
||||
class Track(Audio, Playable):
|
||||
TYPE = 'track'
|
||||
|
||||
def _loadData(self, data):
|
||||
|
@ -154,6 +152,3 @@ class Track(Audio):
|
|||
|
||||
def artist(self):
|
||||
return utils.listItems(self.server, self.grandparentKey)[0]
|
||||
|
||||
def getStreamURL(self, **params):
|
||||
return self._getStreamURL(**params)
|
||||
|
|
|
@ -4,20 +4,24 @@ PlexPlaylist
|
|||
"""
|
||||
from plexapi import utils
|
||||
from plexapi.utils import cast, toDatetime
|
||||
from plexapi.utils import PlexPartialObject
|
||||
NA = utils.NA
|
||||
|
||||
|
||||
@utils.register_libtype
|
||||
class Playlist(utils.PlexPartialObject):
|
||||
class Playlist(PlexPartialObject):
|
||||
TYPE = 'playlist'
|
||||
|
||||
def __init__(self, server, data, initpath):
|
||||
super(Playlist, self).__init__(data, initpath, server)
|
||||
|
||||
def _loadData(self, data):
|
||||
self.addedAt = toDatetime(data.attrib.get('addedAt', NA))
|
||||
self.composite = data.attrib.get('composite', NA) # url to thumbnail
|
||||
self.duration = cast(int, data.attrib.get('duration', NA))
|
||||
self.durationInSeconds = cast(int, data.attrib.get('durationInSeconds', NA))
|
||||
self.guid = data.attrib.get('guid', NA)
|
||||
self.key = data.attrib.get('key', NA).replace('/items', '') # plex bug? http://bit.ly/1Sc2J3V
|
||||
self.key = data.attrib.get('key', NA).replace('/items', '') # FIX_BUG_50
|
||||
self.leafCount = cast(int, data.attrib.get('leafCount', NA))
|
||||
self.playlistType = data.attrib.get('playlistType', NA)
|
||||
self.ratingKey = data.attrib.get('ratingKey', NA)
|
||||
|
@ -30,8 +34,3 @@ class Playlist(utils.PlexPartialObject):
|
|||
def items(self):
|
||||
path = '%s/items' % self.key
|
||||
return utils.listItems(self.server, path)
|
||||
|
||||
def isFullObject(self):
|
||||
# plex bug? http://bit.ly/1Sc2J3V
|
||||
fixed_key = self.key.replace('/items', '')
|
||||
return self.initpath == fixed_key
|
||||
|
|
|
@ -38,8 +38,8 @@ NA = _NA()
|
|||
# you request is None it will fetch the full object automatically and update itself.
|
||||
class PlexPartialObject(object):
|
||||
|
||||
def __init__(self, server, data, initpath):
|
||||
self.server = server # TODO: This should not be needed here..
|
||||
def __init__(self, data, initpath, server=None):
|
||||
self.server = server
|
||||
self.initpath = initpath
|
||||
self._loadData(data)
|
||||
|
||||
|
@ -62,13 +62,25 @@ class PlexPartialObject(object):
|
|||
if value != NA:
|
||||
super(PlexPartialObject, self).__setattr__(attr, value)
|
||||
|
||||
# TODO: This shouldn't be here, move downstream
|
||||
@property
|
||||
def thumbUrl(self):
|
||||
return self.server.url(self.thumb)
|
||||
def _loadData(self, data):
|
||||
raise Exception('Abstract method not implemented.')
|
||||
|
||||
# TODO: Move to Playable()
|
||||
def _getStreamURL(self, **params):
|
||||
def isFullObject(self):
|
||||
return self.initpath == self.key
|
||||
|
||||
def isPartialObject(self):
|
||||
return not self.isFullObject()
|
||||
|
||||
def reload(self):
|
||||
""" Reload the data for this object from PlexServer XML. """
|
||||
data = self.server.query(self.key)
|
||||
self.initpath = self.key
|
||||
self._loadData(data[0])
|
||||
|
||||
|
||||
class Playable(object):
|
||||
|
||||
def getStreamURL(self, **params):
|
||||
if self.TYPE not in ('movie', 'episode', 'track'):
|
||||
raise Unsupported('Fetching stream URL for %s is unsupported.' % self.TYPE)
|
||||
mvb = params.get('maxVideoBitrate')
|
||||
|
@ -87,35 +99,14 @@ class PlexPartialObject(object):
|
|||
streamtype = 'audio' if self.TYPE in ('track', 'album') else 'video'
|
||||
return self.server.url('/%s/:/transcode/universal/start.m3u8?%s' % (streamtype, urlencode(params)))
|
||||
|
||||
def _loadData(self, data):
|
||||
raise Exception('Abstract method not implemented.')
|
||||
|
||||
def isFullObject(self):
|
||||
return self.initpath == self.key
|
||||
|
||||
def isPartialObject(self):
|
||||
return not self.isFullObject()
|
||||
|
||||
# TODO: Move to Playable()
|
||||
def iterParts(self):
|
||||
for item in self.media:
|
||||
for part in item.parts:
|
||||
yield part
|
||||
|
||||
# TODO: Move to Playable()
|
||||
def play(self, client):
|
||||
client.playMedia(self)
|
||||
|
||||
# TODO: This shouldn't be here, move downstream
|
||||
def refresh(self):
|
||||
self.server.query('%s/refresh' % self.key, method=put)
|
||||
|
||||
def reload(self):
|
||||
""" Reload the data for this object from PlexServer XML. """
|
||||
data = self.server.query(self.key)
|
||||
self.initpath = self.key
|
||||
self._loadData(data[0])
|
||||
|
||||
|
||||
def buildItem(server, elem, initpath, bytag=False):
|
||||
libtype = elem.tag if bytag else elem.attrib.get('type')
|
||||
|
|
|
@ -3,12 +3,16 @@
|
|||
PlexVideo
|
||||
"""
|
||||
from plexapi import media, utils
|
||||
from plexapi.utils import Playable, PlexPartialObject
|
||||
NA = utils.NA
|
||||
|
||||
|
||||
class Video(utils.PlexPartialObject):
|
||||
class Video(PlexPartialObject):
|
||||
TYPE = None
|
||||
|
||||
def __init__(self, server, data, initpath):
|
||||
super(Video, self).__init__(data, initpath, server)
|
||||
|
||||
def _loadData(self, data):
|
||||
self.addedAt = utils.toDatetime(data.attrib.get('addedAt', NA))
|
||||
self.key = data.attrib.get('key', NA)
|
||||
|
@ -23,6 +27,10 @@ class Video(utils.PlexPartialObject):
|
|||
self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt', NA))
|
||||
self.viewCount = utils.cast(int, data.attrib.get('viewCount', 0))
|
||||
|
||||
@property
|
||||
def thumbUrl(self):
|
||||
return self.server.url(self.thumb)
|
||||
|
||||
def analyze(self):
|
||||
""" The primary purpose of media analysis is to gather information about that media
|
||||
item. All of the media you add to a Library has properties that are useful to
|
||||
|
@ -40,15 +48,12 @@ class Video(utils.PlexPartialObject):
|
|||
self.server.query(path)
|
||||
self.reload()
|
||||
|
||||
def play(self, client):
|
||||
client.playMedia(self)
|
||||
|
||||
def refresh(self):
|
||||
self.server.query('%s/refresh' % self.key, method=self.server.session.put)
|
||||
|
||||
|
||||
@utils.register_libtype
|
||||
class Movie(Video):
|
||||
class Movie(Video, Playable):
|
||||
TYPE = 'movie'
|
||||
|
||||
def _loadData(self, data):
|
||||
|
@ -96,9 +101,6 @@ class Movie(Video):
|
|||
def isWatched(self):
|
||||
return bool(self.viewCount > 0)
|
||||
|
||||
def getStreamURL(self, **params):
|
||||
return self._getStreamURL(**params)
|
||||
|
||||
|
||||
@utils.register_libtype
|
||||
class Show(Video):
|
||||
|
@ -198,7 +200,7 @@ class Season(Video):
|
|||
|
||||
|
||||
@utils.register_libtype
|
||||
class Episode(Video):
|
||||
class Episode(Video, Playable):
|
||||
TYPE = 'episode'
|
||||
|
||||
def _loadData(self, data):
|
||||
|
@ -243,9 +245,6 @@ class Episode(Video):
|
|||
def thumbUrl(self):
|
||||
return self.server.url(self.grandparentThumb)
|
||||
|
||||
def getStreamURL(self, **params):
|
||||
return self._getStreamURL(videoResolution='800x600', **params)
|
||||
|
||||
def season(self):
|
||||
return utils.listItems(self.server, self.parentKey)[0]
|
||||
|
||||
|
|
Loading…
Reference in a new issue