# Licensed under the MIT license # http://opensource.org/licenses/mit-license.php # Copyright 2005, Tim Potter from elementtree.ElementTree import Element, SubElement, tostring, _ElementInterface class Resource: """An object representing a resource.""" def __init__(self, data, protocolInfo): self.data = data self.protocolInfo = protocolInfo self.bitrate = None self.size = None def toElement(self): root = Element('res') root.attrib['protocolInfo'] = self.protocolInfo root.text = self.data if self.bitrate is not None: root.attrib['bitrate'] = str(self.bitrate) if self.size is not None: root.attrib['size'] = str(self.size) return root class Object: """The root class of the entire content directory class heirachy.""" klass = 'object' creator = None res = None writeStatus = None def __init__(self, id, parentID, title, restricted = False, creator = None): self.id = id self.parentID = parentID self.title = title self.creator = creator if restricted: self.restricted = '1' else: self.restricted = '0' def toElement(self): root = Element(self.elementName) root.attrib['id'] = self.id root.attrib['parentID'] = self.parentID SubElement(root, 'dc:title').text = self.title SubElement(root, 'upnp:class').text = self.klass root.attrib['restricted'] = self.restricted if self.creator is not None: SubElement(root, 'dc:creator').text = self.creator if self.res is not None: root.append(self.res.toElement()) if self.writeStatus is not None: SubElement(root, 'upnp:writeStatus').text = self.writeStatus return root def toString(self): return tostring(self.toElement()) class Item(Object): """A class used to represent atomic (non-container) content objects.""" klass = Object.klass + '.item' elementName = 'item' refID = None def toElement(self): root = Object.toElement(self) if self.refID is not None: SubElement(root, 'refID').text = self.refID return root class ImageItem(Item): klass = Item.klass + '.imageItem' class Photo(ImageItem): klass = ImageItem.klass + '.photo' class AudioItem(Item): """A piece of content that when rendered generates some audio.""" klass = Item.klass + '.audioItem' genre = None description = None longDescription = None publisher = None language = None relation = None rights = None def toElement(self): root = Item.toElement(self) if self.genre is not None: SubElement(root, 'upnp:genre').text = self.genre if self.description is not None: SubElement(root, 'dc:description').text = self.description if self.longDescription is not None: SubElement(root, 'upnp:longDescription').text = \ self.longDescription if self.publisher is not None: SubElement(root, 'dc:publisher').text = self.publisher if self.language is not None: SubElement(root, 'dc:language').text = self.language if self.relation is not None: SubElement(root, 'dc:relation').text = self.relation if self.rights is not None: SubElement(root, 'dc:rights').text = self.rights return root class MusicTrack(AudioItem): """A discrete piece of audio that should be interpreted as music.""" klass = AudioItem.klass + '.musicTrack' artist = None album = None originalTrackNumber = None playlist = None storageMedium = None contributor = None date = None def toElement(self): root = AudioItem.toElement(self) if self.artist is not None: SubElement(root, 'upnp:artist').text = self.artist if self.album is not None: SubElement(root, 'upnp:album').text = self.album if self.originalTrackNumber is not None: SubElement(root, 'upnp:originalTrackNumber').text = \ self.originalTrackNumber if self.playlist is not None: SubElement(root, 'upnp:playlist').text = self.playlist if self.storageMedium is not None: SubElement(root, 'upnp:storageMedium').text = self.storageMedium if self.contributor is not None: SubElement(root, 'dc:contributor').text = self.contributor if self.date is not None: SubElement(root, 'dc:date').text = self.date return root class AudioBroadcast(AudioItem): klass = AudioItem.klass + '.audioBroadcast' class AudioBook(AudioItem): klass = AudioItem.klass + '.audioBook' class VideoItem(Item): klass = Item.klass + '.videoItem' class Movie(VideoItem): klass = VideoItem.klass + '.movie' class VideoBroadcast(VideoItem): klass = VideoItem.klass + '.videoBroadcast' class MusicVideoClip(VideoItem): klass = VideoItem.klass + '.musicVideoClip' class PlaylistItem(Item): klass = Item.klass + '.playlistItem' class TextItem(Item): klass = Item.klass + '.textItem' class Container(Object): """An object that can contain other objects.""" klass = Object.klass + '.container' elementName = 'container' childCount = 0 createClass = None searchClass = None searchable = None def __init__(self, id, parentID, title, restricted = 0, creator = None): Object.__init__(self, id, parentID, title, restricted, creator) def toElement(self): root = Object.toElement(self) root.attrib['childCount'] = str(self.childCount) if self.createClass is not None: SubElement(root, 'upnp:createclass').text = self.createClass if self.searchClass is not None: if not isinstance(self.searchClass, (list, tuple)): self.searchClass = ['searchClass'] for i in searchClass: SubElement(root, 'upnp:searchclass').text = i if self.searchable is not None: root.attrib['searchable'] = str(self.searchable) return root class Person(Container): klass = Container.klass + '.person' class MusicArtist(Person): klass = Person.klass + '.musicArtist' class PlaylistContainer(Container): klass = Container.klass + '.playlistContainer' class Album(Container): klass = Container.klass + '.album' class MusicAlbum(Album): klass = Album.klass + '.musicAlbum' class PhotoAlbum(Album): klass = Album.klass + '.photoAlbum' class Genre(Container): klass = Container.klass + '.genre' class MusicGenre(Genre): klass = Genre.klass + '.musicGenre' class MovieGenre(Genre): klass = Genre.klass + '.movieGenre' class StorageSystem(Container): klass = Container.klass + '.storageSystem' total = -1 used = -1 free = -1 maxpartition = -1 medium = 'UNKNOWN' def toElement(self): root = Container.toElement(self) SubElement(root, 'upnp:storageTotal').text = str(self.total) SubElement(root, 'upnp:storageUsed').text = str(self.used) SubElement(root, 'upnp:storageFree').text = str(self.free) SubElement(root, 'upnp:storageMaxPartition').text = str(self.maxpartition) SubElement(root, 'upnp:storageMedium').text = self.medium return root class StorageVolume(Container): klass = Container.klass + '.storageVolume' total = -1 used = -1 free = -1 medium = 'UNKNOWN' def toElement(self): root = Container.toElement(self) SubElement(root, 'upnp:storageTotal').text = str(self.total) SubElement(root, 'upnp:storageUsed').text = str(self.used) SubElement(root, 'upnp:storageFree').text = str(self.free) SubElement(root, 'upnp:storageMedium').text = self.medium return root class StorageFolder(Container): klass = Container.klass + '.storageFolder' used = -1 def toElement(self): root = Container.toElement(self) if self.used is not None: SubElement(root, 'upnp:storageUsed').text = str(self.used) return root class DIDLElement(_ElementInterface): def __init__(self): _ElementInterface.__init__(self, 'DIDL-Lite', {}) self.attrib['xmlns'] = 'urn:schemas-upnp-org:metadata-1-0/DIDL-Lite' self.attrib['xmlns:dc'] = 'http://purl.org/dc/elements/1.1/' self.attrib['xmlns:upnp'] = 'urn:schemas-upnp-org:metadata-1-0/upnp' def addContainer(self, id, parentID, title, restricted = False): e = Container(id, parentID, title, restricted, creator = '') self.append(e.toElement()) def addItem(self, item): self.append(item.toElement()) def numItems(self): return len(self) def toString(self): return tostring(self) if __name__ == '__main__': root = DIDLElement() root.addContainer('0\Movie\\', '0\\', 'Movie') root.addContainer('0\Music\\', '0\\', 'Music') root.addContainer('0\Photo\\', '0\\', 'Photo') root.addContainer('0\OnlineMedia\\', '0\\', 'OnlineMedia') print tostring(root)