|
- # Licensed under the MIT license
- # http://opensource.org/licenses/mit-license.php
-
- # (c) 2005, Tim Potter <tpot@samba.org>
-
- #
- # This module implements the Content Directory Service (CDS) service
- # type as documented in the ContentDirectory:1 Service Template
- # Version 1.01
- #
-
- #
- # TODO: Figure out a nicer pattern for debugging soap server calls as
- # twisted swallows the tracebacks. At the moment I'm going:
- #
- # try:
- # ....
- # except:
- # traceback.print_exc(file = log.logfile)
- #
-
- from twisted.python import log
- from twisted.web import resource, static
-
- from elementtree.ElementTree import Element, SubElement, tostring
- from upnp import UPnPPublisher
- from DIDLLite import DIDLElement, Container, Movie, Resource, MusicTrack
-
- import traceback
- from urllib import quote
-
- class ContentDirectoryControl(UPnPPublisher):
- """This class implements the CDS actions over SOAP."""
-
- # Required actions
-
- def soap_GetSearchCapabilities(self, *args, **kwargs):
- """Return the searching capabilities supported by the device."""
-
- log.msg('GetSearchCapabilities()')
-
- def soap_GetSortCapabilities(self, *args, **kwargs):
- """Return the CSV list of meta-data tags that can be used in
- sortCriteria."""
-
- log.msg('GetSortCapabilities()')
-
- def soap_GetSystemUpdateID(self, *args, **kwargs):
- """Return the current value of state variable SystemUpdateID."""
-
- log.msg('GetSystemUpdateID()')
-
- BrowseFlags = ('BrowseMetaData', 'BrowseDirectChildren')
-
- def soap_Browse(self, *args):
- """Incrementally browse the native heirachy of the Content
- Directory objects exposed by the Content Directory Service."""
-
- (ObjectID, BrowseFlag, Filter, StartingIndex, RequestedCount,
- SortCriteria) = args
-
- log.msg('Browse(ObjectID=%s, BrowseFlags=%s, Filter=%s, '
- 'StartingIndex=%s RequestedCount=%s SortCriteria=%s)' %
- (`ObjectID`, `BrowseFlag`, `Filter`, `StartingIndex`,
- `RequestedCount`, `SortCriteria`))
-
- didl = DIDLElement()
-
- try:
-
- if ObjectID == '0\\Music\\':
-
- c = Container('0\\Music\\Spotty\\', '0\\Music\\', 'Spotty')
- c.childCount = 6
- c.searchable = 0
- didl.addItem(c)
-
- c = Container('0\\Music\\Foot\\', '0\\Music\\', 'Foot')
- c.childCount = 1
- c.searchable = 0
- didl.addItem(c)
-
-
- if ObjectID == '0\\Music\\Spotty\\':
-
- m = MusicTrack('0\\Music\\media\\foo.mp3', '0\\Music\\', 'foo.mp3')
-
- m.res = Resource('http://192.168.1.105:8080/media/foo.mp3', 'http-get:*:audio/mpeg:*')
- m.res.size = 1234
- m.res.bitrate = 256
- m.genre = 'Others'
- m.artist = 'Others'
- m.album = 'Others'
-
- didl.addItem(m)
-
- result = {'BrowseResponse': {'Result': didl.toString() ,
- 'NumberReturned': didl.numItems(),
- 'TotalMatches': didl.numItems(),
- 'UpdateID': 0}}
-
- except:
- traceback.print_exc(file=log.logfile)
-
- log.msg('Returning: %s' % result)
-
- return result
-
- # Optional actions
-
- def soap_Search(self, *args, **kwargs):
- """Search for objects that match some search criteria."""
-
- (ContainerID, SearchCriteria, Filter, StartingIndex,
- RequestedCount, SortCriteria) = args
-
- log.msg('Search(ContainerID=%s, SearchCriteria=%s, Filter=%s, ' \
- 'StartingIndex=%s, RequestedCount=%s, SortCriteria=%s)' %
- (`ContainerID`, `SearchCriteria`, `Filter`,
- `StartingIndex`, `RequestedCount`, `SortCriteria`))
-
- def soap_CreateObject(self, *args, **kwargs):
- """Create a new object."""
-
- (ContainerID, Elements) = args
-
- log.msg('CreateObject(ContainerID=%s, Elements=%s)' %
- (`ContainerID`, `Elements`))
-
- def soap_DestroyObject(self, *args, **kwargs):
- """Destroy the specified object."""
-
- (ObjectID) = args
-
- log.msg('DestroyObject(ObjectID=%s)' % `ObjectID`)
-
- def soap_UpdateObject(self, *args, **kwargs):
- """Modify, delete or insert object metadata."""
-
- (ObjectID, CurrentTagValue, NewTagValue) = args
-
- log.msg('UpdateObject(ObjectID=%s, CurrentTagValue=%s, ' \
- 'NewTagValue=%s)' % (`ObjectID`, `CurrentTagValue`,
- `NewTagValue`))
-
- def soap_ImportResource(self, *args, **kwargs):
- """Transfer a file from a remote source to a local
- destination in the Content Directory Service."""
-
- (SourceURI, DestinationURI) = args
-
- log.msg('ImportResource(SourceURI=%s, DestinationURI=%s)' %
- (`SourceURI`, `DestinationURI`))
-
- def soap_ExportResource(self, *args, **kwargs):
- """Transfer a file from a local source to a remote
- destination."""
-
- (SourceURI, DestinationURI) = args
-
- log.msg('ExportResource(SourceURI=%s, DestinationURI=%s)' %
- (`SourceURI`, `DestinationURI`))
-
- def soap_StopTransferResource(self, *args, **kwargs):
- """Stop a file transfer initiated by ImportResource or
- ExportResource."""
-
- (TransferID) = args
-
- log.msg('StopTransferResource(TransferID=%s)' % TransferID)
-
- def soap_GetTransferProgress(self, *args, **kwargs):
- """Query the progress of a file transfer initiated by
- an ImportResource or ExportResource action."""
-
- (TransferID, TransferStatus, TransferLength, TransferTotal) = args
-
- log.msg('GetTransferProgress(TransferID=%s, TransferStatus=%s, ' \
- 'TransferLength=%s, TransferTotal=%s)' %
- (`TransferId`, `TransferStatus`, `TransferLength`,
- `TransferTotal`))
-
- def soap_DeleteResource(self, *args, **kwargs):
- """Delete a specified resource."""
-
- (ResourceURI) = args
-
- log.msg('DeleteResource(ResourceURI=%s)' % `ResourceURI`)
-
- def soap_CreateReference(self, *args, **kwargs):
- """Create a reference to an existing object."""
-
- (ContainerID, ObjectID) = args
-
- log.msg('CreateReference(ContainerID=%s, ObjectID=%s)' %
- (`ContainerID`, `ObjectID`))
-
- class ContentDirectoryServer(resource.Resource):
- def __init__(self):
- resource.Resource.__init__(self)
- self.putChild('scpd.xml', static.File('content-directory-scpd.xml'))
- self.putChild('control', ContentDirectoryControl())
|