so that data can be accessed.. This will give the ability for custom objects to add their data instead of depending upon the FS... the url may need to be set after object creation, instead of having it in Object, as we don't generate the name, the cd does... slight layering violation, but it works.. [git-p4: depot-paths = "//depot/": change = 801]v0.3
@@ -32,6 +32,8 @@ from urllib import quote | |||||
class ContentDirectoryControl(UPnPPublisher, dict): | class ContentDirectoryControl(UPnPPublisher, dict): | ||||
"""This class implements the CDS actions over SOAP.""" | """This class implements the CDS actions over SOAP.""" | ||||
urlbase = property(lambda x: x._urlbase) | |||||
def getnextID(self): | def getnextID(self): | ||||
ret = str(self.nextID) | ret = str(self.nextID) | ||||
self.nextID += 1 | self.nextID += 1 | ||||
@@ -43,9 +45,12 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||||
return ret | return ret | ||||
def addItem(self, parent, klass, *args, **kwargs): | def addItem(self, parent, klass, *args, **kwargs): | ||||
'''Takes an optional arg, content, which is a twisted.web.resource.Resource that this item provides.''' | |||||
assert isinstance(self[parent], Container) | assert isinstance(self[parent], Container) | ||||
nid = self.getnextID() | nid = self.getnextID() | ||||
i = klass(self, nid, parent, *args, **kwargs) | i = klass(self, nid, parent, *args, **kwargs) | ||||
if hasattr(i, 'content'): | |||||
self.webbase.putChild(nid, i.content) | |||||
self.children[parent].append(i) | self.children[parent].append(i) | ||||
self[i.id] = i | self[i.id] = i | ||||
return i.id | return i.id | ||||
@@ -66,6 +71,9 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||||
def __init__(self, title, *args, **kwargs): | def __init__(self, title, *args, **kwargs): | ||||
super(ContentDirectoryControl, self).__init__(*args) | super(ContentDirectoryControl, self).__init__(*args) | ||||
self.webbase = kwargs['webbase'] | |||||
self._urlbase = kwargs['urlbase'] | |||||
del kwargs['webbase'], kwargs['urlbase'] | |||||
fakeparent = '-1' | fakeparent = '-1' | ||||
self.nextID = 0 | self.nextID = 0 | ||||
self.children = { fakeparent: []} | self.children = { fakeparent: []} | ||||
@@ -35,9 +35,10 @@ class Object: | |||||
creator = None | creator = None | ||||
res = None | res = None | ||||
writeStatus = None | writeStatus = None | ||||
content = property(lambda x: x._content) | |||||
def __init__(self, cd, id, parentID, title, restricted = False, | def __init__(self, cd, id, parentID, title, restricted = False, | ||||
creator = None): | |||||
creator = None, **kwargs): | |||||
self.cd = cd | self.cd = cd | ||||
self.id = id | self.id = id | ||||
@@ -50,6 +51,9 @@ class Object: | |||||
else: | else: | ||||
self.restricted = '0' | self.restricted = '0' | ||||
if kwargs.has_key('content'): | |||||
self._content = kwargs['content'] | |||||
def checkUpdate(self): | def checkUpdate(self): | ||||
return self | return self | ||||
@@ -52,12 +52,11 @@ class FSItem(FSObject, Item): | |||||
def __init__(self, *args, **kwargs): | def __init__(self, *args, **kwargs): | ||||
FSObject.__init__(self, kwargs['path']) | FSObject.__init__(self, kwargs['path']) | ||||
del kwargs['path'] | del kwargs['path'] | ||||
urlbase = kwargs['urlbase'] | |||||
del kwargs['urlbase'] | |||||
mimetype = kwargs['mimetype'] | mimetype = kwargs['mimetype'] | ||||
del kwargs['mimetype'] | del kwargs['mimetype'] | ||||
kwargs['content'] = static.File(self.FSpath) | |||||
Item.__init__(self, *args, **kwargs) | Item.__init__(self, *args, **kwargs) | ||||
self.url = '%s%s' % (urlbase, self.FSpath) | |||||
self.url = '%s/%s' % (self.cd.urlbase, self.id) | |||||
self.mimetype = mimetype | self.mimetype = mimetype | ||||
def doUpdate(self): | def doUpdate(self): | ||||
@@ -85,7 +84,7 @@ mimetoklass = { | |||||
'image': FSImageItem, | 'image': FSImageItem, | ||||
} | } | ||||
def dofileadd(cd, parent, urlbase, path, name): | |||||
def dofileadd(cd, parent, path, name): | |||||
fn, ext = os.path.splitext(name) | fn, ext = os.path.splitext(name) | ||||
ext = ext.lower() | ext = ext.lower() | ||||
try: | try: | ||||
@@ -103,21 +102,18 @@ def dofileadd(cd, parent, urlbase, path, name): | |||||
log.msg('no item for mt: %s' % mt) | log.msg('no item for mt: %s' % mt) | ||||
return | return | ||||
return cd.addItem(parent, klass, name, urlbase = urlbase, | |||||
return cd.addItem(parent, klass, name, | |||||
path = os.path.join(path, name), mimetype = mt) | path = os.path.join(path, name), mimetype = mt) | ||||
class FSDirectory(FSObject, StorageFolder): | class FSDirectory(FSObject, StorageFolder): | ||||
def __init__(self, *args, **kwargs): | def __init__(self, *args, **kwargs): | ||||
path = kwargs['path'] | path = kwargs['path'] | ||||
del kwargs['path'] | del kwargs['path'] | ||||
urlbase = kwargs['urlbase'] | |||||
del kwargs['urlbase'] | |||||
StorageFolder.__init__(self, *args, **kwargs) | StorageFolder.__init__(self, *args, **kwargs) | ||||
FSObject.__init__(self, path) | FSObject.__init__(self, path) | ||||
# mapping from path to objectID | # mapping from path to objectID | ||||
self.pathObjmap = {} | self.pathObjmap = {} | ||||
self.urlbase = urlbase | |||||
def doUpdate(self): | def doUpdate(self): | ||||
# We need to rescan this dir, and see if our children has | # We need to rescan this dir, and see if our children has | ||||
@@ -137,10 +133,10 @@ class FSDirectory(FSObject, StorageFolder): | |||||
# new object | # new object | ||||
if os.path.isdir(fname): | if os.path.isdir(fname): | ||||
# new dir | # new dir | ||||
nf = self.cd.addContainer(self.id, i, klass = FSDirectory, path = fname, urlbase = self.urlbase) | |||||
nf = self.cd.addContainer(self.id, i, klass = FSDirectory, path = fname) | |||||
elif os.path.isfile(fname): | elif os.path.isfile(fname): | ||||
# new file | # new file | ||||
nf = dofileadd(self.cd, self.id, self.urlbase, self.FSpath, i) | |||||
nf = dofileadd(self.cd, self.id, self.FSpath, i) | |||||
else: | else: | ||||
nf = None | nf = None | ||||
log.msg('skipping: %s' % fname) | log.msg('skipping: %s' % fname) | ||||
@@ -65,11 +65,13 @@ class RootDevice(static.Data): | |||||
static.Data.__init__(self, d, 'text/xml') | static.Data.__init__(self, d, 'text/xml') | ||||
root = WebServer() | root = WebServer() | ||||
cds = ContentDirectoryServer('My Media Server', klass = FSDirectory, path = 'media', urlbase = urlbase) # This sets up the root to be the media dir so we don't have to enumerate the directory | |||||
content = resource.Resource() | |||||
cds = ContentDirectoryServer('My Media Server', klass = FSDirectory, path = 'media', urlbase = os.path.join(urlbase, 'content'), webbase = content) # This sets up the root to be the media dir so we don't have to enumerate the directory | |||||
root.putChild('ContentDirectory', cds) | root.putChild('ContentDirectory', cds) | ||||
cds = cds.control | cds = cds.control | ||||
root.putChild('ConnectionManager', ConnectionManagerServer()) | root.putChild('ConnectionManager', ConnectionManagerServer()) | ||||
root.putChild('root-device.xml', RootDevice()) | root.putChild('root-device.xml', RootDevice()) | ||||
root.putChild('content', content) | |||||
# Area of server to serve media files from | # Area of server to serve media files from | ||||
@@ -83,6 +85,7 @@ medianode.contentTypes.update( { | |||||
'.ts': 'video/mpeg', # we may want this instead of mp2t | '.ts': 'video/mpeg', # we may want this instead of mp2t | ||||
#'.mp4': 'video/mp4', | #'.mp4': 'video/mp4', | ||||
'.mp4': 'video/mpeg', | '.mp4': 'video/mpeg', | ||||
'.dat': 'video/mpeg', # VCD tracks | |||||
'.ogm': 'application/ogg', | '.ogm': 'application/ogg', | ||||
'.vob': 'video/mpeg', | '.vob': 'video/mpeg', | ||||
#'.m4a': 'audio/mp4', # D-Link can't seem to play AAC files. | #'.m4a': 'audio/mp4', # D-Link can't seem to play AAC files. | ||||