Author | SHA1 | Message | Date |
---|---|---|---|
John-Mark Gurney | fcfa5bdded | convert README to markdown and minor updates.. | 1 year ago |
John-Mark Gurney | a4ed76d890 |
use local forks to fix modern Python issues..
I should think about moving away from these as they are clearly not maintained for quite a few python versions.. |
1 year ago |
John-Mark Gurney | 7666721ed6 | add a date to files using their mtime.. | 1 year ago |
John-Mark Gurney | a8e8337e96 | a string player requires these changes.. | 1 year ago |
John-Mark Gurney | dda96e70f0 |
convert mostly to Python 3.. basic functions work...
add a .gitignore and requirements.txt... the later will be converted to setup.py in time... Also, a fix to SOAPpy is needed.. |
1 year ago |
@@ -0,0 +1,5 @@ | |||
.DS_Store | |||
__pycache__ | |||
# my venv | |||
p |
@@ -35,7 +35,7 @@ class ClipProxyFile: | |||
fp = self.fp | |||
records = iter(self.p[p:]) | |||
while s: | |||
rec = records.next() | |||
rec = next(records) | |||
diff = self.pos - rec[0] | |||
rlen = min(s, rec[1] - diff) | |||
fp.seek(rec[2] + diff) | |||
@@ -76,7 +76,7 @@ class ClipProxy(static.File): | |||
self.origfile = i['file'] | |||
self.date = eval(i['datetuple'], { '__builtins__': {} }) | |||
# date is UTC | |||
p = [ map(int, x.split()) for x in i.get_payload().split('\n') if x ] | |||
p = [ list(map(int, x.split())) for x in i.get_payload().split('\n') if x ] | |||
pos = 0 | |||
self.pos = par = [] | |||
for j in p: | |||
@@ -11,23 +11,23 @@ from upnp import UPnPPublisher | |||
class ConnectionManagerControl(UPnPPublisher): | |||
def soap_GetProtocolInfo(self, *args, **kwargs): | |||
log.msg('GetProtocolInfo(%s, %s)' % (`args`, `kwargs`)) | |||
log.msg('GetProtocolInfo(%s, %s)' % (repr(args), repr(kwargs))) | |||
return { 'Source': 'http-get:*:*:*', 'Sink': '' } | |||
def soap_PrepareForConnection(self, *args, **kwargs): | |||
log.msg('PrepareForConnection(%s, %s)' % (`args`, `kwargs`)) | |||
log.msg('PrepareForConnection(%s, %s)' % (repr(args), repr(kwargs))) | |||
def soap_ConnectionComplete(self, *args, **kwargs): | |||
log.msg('ConnectionComplete(%s, %s)' % (`args`, `kwargs`)) | |||
log.msg('ConnectionComplete(%s, %s)' % (repr(args), repr(kwargs))) | |||
def soap_GetCurrentConnectionIDs(self, *args, **kwargs): | |||
log.msg('GetCurrentConnectionIDs(%s, %s)' % (`args`, `kwargs`)) | |||
log.msg('GetCurrentConnectionIDs(%s, %s)' % (repr(args), repr(kwargs))) | |||
def soap_GetCurrentConnectionInfo(self, *args, **kwargs): | |||
log.msg('GetProtocolInfo(%s, %s)' % (`args`, `kwargs`)) | |||
log.msg('GetProtocolInfo(%s, %s)' % (repr(args), repr(kwargs))) | |||
class ConnectionManagerServer(resource.Resource): | |||
def __init__(self): | |||
resource.Resource.__init__(self) | |||
self.putChild('scpd.xml', static.File('connection-manager-scpd.xml')) | |||
self.putChild('control', ConnectionManagerControl()) | |||
self.putChild(b'scpd.xml', static.File('connection-manager-scpd.xml')) | |||
self.putChild(b'control', ConnectionManagerControl()) |
@@ -27,7 +27,7 @@ reqname = 'requests' | |||
from twisted.python import log | |||
from twisted.web import resource, static | |||
from elementtree.ElementTree import Element, SubElement, tostring | |||
from xml.etree.ElementTree import Element, SubElement, tostring | |||
from upnp import UPnPPublisher, errorCode | |||
from DIDLLite import DIDLElement, Container, Movie, Resource, MusicTrack | |||
@@ -36,7 +36,7 @@ from twisted.python import failure | |||
import debug | |||
import traceback | |||
from urllib import quote | |||
from urllib.parse import quote | |||
class doRecall(defer.Deferred): | |||
'''A class that will upon any callback from the Deferred object passed | |||
@@ -80,7 +80,7 @@ class doRecall(defer.Deferred): | |||
def wrapper(fun, *args, **kwargs): | |||
try: | |||
return fun(*args, **kwargs) | |||
except defer.Deferred, x: | |||
except defer.Deferred as x: | |||
return doRecallgen(x, fun, *args, **kwargs) | |||
def doRecallgen(defer, fun, *args, **kwargs): | |||
@@ -124,17 +124,17 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
return | |||
if hasattr(i, 'content'): | |||
self.webbase.putChild(nid, i.content) | |||
self.webbase.putChild(bytes(nid, 'ascii'), i.content) | |||
#log.msg('children:', `self.children[parent]`, `i`) | |||
self.children[parent].append(i) | |||
self[i.id] = i | |||
return i.id | |||
def has_key(self, key): | |||
return dict.has_key(self, key) | |||
def __in__(self, k): | |||
return dict.__in__(self, k) | |||
def delItem(self, id): | |||
if not self.has_key(id): | |||
if id not in self: | |||
log.msg('already removed:', id) | |||
return | |||
#log.msg('removing:', id) | |||
@@ -195,7 +195,7 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
def soap_Browse(self, *args): | |||
l = {} | |||
debug.appendnamespace(reqname, l) | |||
if self.has_key(args[0]): | |||
if args[0] in self: | |||
l['object'] = self[args[0]] | |||
l['query'] = 'Browse(ObjectID=%s, BrowseFlags=%s, Filter=%s, ' \ | |||
'StartingIndex=%s RequestedCount=%s SortCriteria=%s)' % \ | |||
@@ -261,8 +261,8 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
log.msg('Search(ContainerID=%s, SearchCriteria=%s, Filter=%s, ' \ | |||
'StartingIndex=%s, RequestedCount=%s, SortCriteria=%s)' % | |||
(`ContainerID`, `SearchCriteria`, `Filter`, | |||
`StartingIndex`, `RequestedCount`, `SortCriteria`)) | |||
(repr(ContainerID), repr(SearchCriteria), repr(Filter), | |||
repr(StartingIndex), repr(RequestedCount), repr(SortCriteria))) | |||
def soap_CreateObject(self, *args, **kwargs): | |||
"""Create a new object.""" | |||
@@ -270,14 +270,14 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
(ContainerID, Elements) = args | |||
log.msg('CreateObject(ContainerID=%s, Elements=%s)' % | |||
(`ContainerID`, `Elements`)) | |||
(repr(ContainerID), repr(Elements))) | |||
def soap_DestroyObject(self, *args, **kwargs): | |||
"""Destroy the specified object.""" | |||
(ObjectID) = args | |||
log.msg('DestroyObject(ObjectID=%s)' % `ObjectID`) | |||
log.msg('DestroyObject(ObjectID=%s)' % repr(ObjectID)) | |||
def soap_UpdateObject(self, *args, **kwargs): | |||
"""Modify, delete or insert object metadata.""" | |||
@@ -285,8 +285,8 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
(ObjectID, CurrentTagValue, NewTagValue) = args | |||
log.msg('UpdateObject(ObjectID=%s, CurrentTagValue=%s, ' \ | |||
'NewTagValue=%s)' % (`ObjectID`, `CurrentTagValue`, | |||
`NewTagValue`)) | |||
'NewTagValue=%s)' % (repr(ObjectID), repr(CurrentTagValue), | |||
repr(NewTagValue))) | |||
def soap_ImportResource(self, *args, **kwargs): | |||
"""Transfer a file from a remote source to a local | |||
@@ -295,7 +295,7 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
(SourceURI, DestinationURI) = args | |||
log.msg('ImportResource(SourceURI=%s, DestinationURI=%s)' % | |||
(`SourceURI`, `DestinationURI`)) | |||
(repr(SourceURI), repr(DestinationURI))) | |||
def soap_ExportResource(self, *args, **kwargs): | |||
"""Transfer a file from a local source to a remote | |||
@@ -304,7 +304,7 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
(SourceURI, DestinationURI) = args | |||
log.msg('ExportResource(SourceURI=%s, DestinationURI=%s)' % | |||
(`SourceURI`, `DestinationURI`)) | |||
(repr(SourceURI), repr(DestinationURI))) | |||
def soap_StopTransferResource(self, *args, **kwargs): | |||
"""Stop a file transfer initiated by ImportResource or | |||
@@ -322,15 +322,15 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
log.msg('GetTransferProgress(TransferID=%s, TransferStatus=%s, ' \ | |||
'TransferLength=%s, TransferTotal=%s)' % | |||
(`TransferId`, `TransferStatus`, `TransferLength`, | |||
`TransferTotal`)) | |||
(repr(TransferId), repr(TransferStatus), repr(TransferLength), | |||
repr(TransferTotal))) | |||
def soap_DeleteResource(self, *args, **kwargs): | |||
"""Delete a specified resource.""" | |||
(ResourceURI) = args | |||
log.msg('DeleteResource(ResourceURI=%s)' % `ResourceURI`) | |||
log.msg('DeleteResource(ResourceURI=%s)' % repr(ResourceURI)) | |||
def soap_CreateReference(self, *args, **kwargs): | |||
"""Create a reference to an existing object.""" | |||
@@ -338,14 +338,14 @@ class ContentDirectoryControl(UPnPPublisher, dict): | |||
(ContainerID, ObjectID) = args | |||
log.msg('CreateReference(ContainerID=%s, ObjectID=%s)' % | |||
(`ContainerID`, `ObjectID`)) | |||
(repr(ContainerID), repr(ObjectID))) | |||
def __repr__(self): | |||
return '<ContentDirectoryControl: cnt: %d, urlbase: %s, nextID: %d>' % (len(self), `self.urlbase`, self.nextID) | |||
return '<ContentDirectoryControl: cnt: %d, urlbase: %s, nextID: %d>' % (len(self), repr(self.urlbase), self.nextID) | |||
class ContentDirectoryServer(resource.Resource): | |||
def __init__(self, title, *args, **kwargs): | |||
resource.Resource.__init__(self) | |||
self.putChild('scpd.xml', static.File('content-directory-scpd.xml')) | |||
self.putChild(b'scpd.xml', static.File('content-directory-scpd.xml')) | |||
self.control = ContentDirectoryControl(title, *args, **kwargs) | |||
self.putChild('control', self.control) | |||
self.putChild(b'control', self.control) |
@@ -7,11 +7,12 @@ | |||
__version__ = '$Change: 1665 $' | |||
# $Id: //depot/python/pymeds/main/DIDLLite.py#32 $ | |||
import functools | |||
import itertools | |||
import unittest | |||
import et | |||
for i in [ 'Element', 'SubElement', 'tostring', '_ElementInterface' ]: | |||
for i in [ 'Element', 'SubElement', 'tostring', ]: | |||
locals()[i] = getattr(et.ET, i) | |||
class Resource(object): | |||
@@ -53,7 +54,7 @@ class Resource(object): | |||
try: | |||
return self.attrs[key.lower()] | |||
except KeyError: | |||
raise AttributeError, key | |||
raise AttributeError(key) | |||
def __setattr__(self, key, value): | |||
key = key.lower() | |||
@@ -72,15 +73,15 @@ class Resource(object): | |||
value = getattr(self, funname)(value) | |||
else: | |||
value = str(value) | |||
assert isinstance(value, basestring), \ | |||
'value is not a string: %s' % `value` | |||
assert isinstance(value, str), \ | |||
'value is not a string: %s' % repr(value) | |||
root.attrib[attr] = value | |||
return root | |||
@staticmethod | |||
def format_duration(s): | |||
if isinstance(s, basestring): | |||
if isinstance(s, str): | |||
return s | |||
# assume it is a number | |||
@@ -104,7 +105,7 @@ class ResourceList(list): | |||
def append(self, k): | |||
assert isinstance(k, Resource) | |||
mt = k.protocolInfo.split(':')[2] | |||
if self._mt.has_key(mt): | |||
if mt in self._mt: | |||
return | |||
list.append(self, k) | |||
@@ -204,12 +205,12 @@ class Object(object): | |||
else: | |||
self.restricted = '0' | |||
if kwargs.has_key('content'): | |||
if 'content' in kwargs: | |||
self._content = kwargs.pop('content') | |||
for i in kwargs: | |||
if i not in self._optionattrs: | |||
raise TypeError('invalid keyword arg: %s' % `i`) | |||
raise TypeError('invalid keyword arg: %s' % repr(i)) | |||
setattr(self, i, kwargs[i]) | |||
def __cmp__(self, other): | |||
@@ -245,12 +246,12 @@ class Object(object): | |||
if obj is None: | |||
continue | |||
SubElement(root, '%s:%s' % (self._optionattrs[i], | |||
i)).text = unicode(getattr(self, i)) | |||
i)).text = str(getattr(self, i)) | |||
if self.res is not None: | |||
try: | |||
resiter = iter(self.res) | |||
except TypeError, x: | |||
except TypeError as x: | |||
resiter = [ self.res ] | |||
for res in resiter: | |||
root.append(res.toElement()) | |||
@@ -374,8 +375,11 @@ class Container(Object, list): | |||
raise NotImplementedError | |||
def sort(self, fun=lambda x, y: cmp(x.title, y.title)): | |||
return list.sort(self, fun) | |||
def sort(self, fun=None): | |||
if fun is not None: | |||
return list.sort(self, key=functools.cmp_to_key(fun)) | |||
else: | |||
return list.sort(self, key=lambda x: x.title) | |||
def doUpdate(self): | |||
if self.doingUpdate: | |||
@@ -396,12 +400,12 @@ class Container(Object, list): | |||
# Delete the old object that no longer exists. | |||
# Make a mapping of current names to ids. | |||
names = {} | |||
print 'i:', `self`, `self.genCurrent`, `self.__class__` | |||
print('i:', repr(self), repr(self.genCurrent), repr(self.__class__)) | |||
for id, i in tuple(self.genCurrent()): | |||
if i not in children: | |||
didupdate = True | |||
# delete | |||
print 'del:', `id`, `i` | |||
print('del:', repr(id), repr(i)) | |||
self.cd.delItem(id) | |||
self.needcontupdate = True | |||
else: | |||
@@ -413,7 +417,7 @@ class Container(Object, list): | |||
for i in children: | |||
if i in names: | |||
if isdict: | |||
print 'oc:', `oldchildren[i]`, `children[i]` | |||
print('oc:', repr(oldchildren[i]), repr(children[i])) | |||
if oldchildren[i] == children[i]: | |||
continue | |||
@@ -433,7 +437,7 @@ class Container(Object, list): | |||
#print 'i:', `i`, `isdict`, `args`, `self` | |||
pass | |||
except UnicodeEncodeError: | |||
print 'i decode error' | |||
print('i decode error') | |||
klass, name, args, kwargs = self.createObject(i, *args) | |||
if klass is not None: | |||
@@ -457,7 +461,7 @@ class Container(Object, list): | |||
if self.id == '0': | |||
self.updateID = (self.updateID + 1) | |||
else: | |||
self.updateID = (self.updateID + 1) % (1l << 32) | |||
self.updateID = (self.updateID + 1) % (1 << 32) | |||
Container.didUpdate(self.cd['0']) | |||
def _addSet(self, e, items): | |||
@@ -502,7 +506,7 @@ class MockContainer(object): | |||
self.itemiter = itertools.count(1) | |||
def addItem(self, *args, **kwargs): | |||
return self.itemiter.next() | |||
return next(self.itemiter) | |||
def __getitem__(self, id): | |||
return Container(None, '0', None, None) | |||
@@ -570,10 +574,10 @@ class StorageFolder(Container): | |||
storageUsed = -1 | |||
class DIDLElement(_ElementInterface): | |||
class DIDLElement(Element): | |||
def __init__(self): | |||
_ElementInterface.__init__(self, 'DIDL-Lite', {}) | |||
self.attrib['xmlns'] = 'urn:schemas-upnp-org:metadata-1-0/DIDL-Lite' | |||
super().__init__('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' | |||
@@ -594,4 +598,4 @@ if __name__ == '__main__': | |||
root.addItem(Container(None, '0\Photo\\', '0\\', 'Photo')) | |||
root.addItem(Container(None, '0\OnlineMedia\\', '0\\', 'OnlineMedia')) | |||
print tostring(root) | |||
print(tostring(root)) |
@@ -9,18 +9,18 @@ ffmpeg_path = '/usr/local/bin/ffmpeg' | |||
ffmpeg_path = '/a/home/jmg/src/ffmpeg.tmp/ffmpeg' | |||
ffmpeg_path = '/usr/local/bin/ffmpeg-devel' | |||
import datetime | |||
import FileDIDL | |||
import errno | |||
import itertools | |||
import os | |||
import sets | |||
import stat | |||
from DIDLLite import StorageFolder, Item, Resource, ResourceList | |||
from twisted.web import resource, server, static | |||
from twisted.python import log | |||
from twisted.internet import abstract, interfaces, process, protocol, reactor | |||
from zope.interface import implements | |||
from zope.interface import implementer | |||
__all__ = [ 'registerklassfun', 'registerfiletoignore', | |||
'FSObject', 'FSItem', 'FSDirectory', | |||
@@ -71,7 +71,7 @@ class FSObject(object): | |||
self.pstat = nstat | |||
self.doUpdate(**kwargs) | |||
except OSError, x: | |||
except OSError as x: | |||
log.msg('os.stat, OSError: %s' % x) | |||
if x.errno in (errno.ENOENT, errno.ENOTDIR, errno.EPERM, ): | |||
# We can't access it anymore, delete it | |||
@@ -83,17 +83,17 @@ class FSObject(object): | |||
def __repr__(self): | |||
return '<%s.%s: path: %s, id: %s, parent: %s, title: %s>' % \ | |||
(self.__class__.__module__, self.__class__.__name__, | |||
`self.FSpath`, self.id, self.parentID, `self.title`) | |||
class NullConsumer(file, abstract.FileDescriptor): | |||
implements(interfaces.IConsumer) | |||
def __init__(self): | |||
file.__init__(self, '/dev/null', 'w') | |||
abstract.FileDescriptor.__init__(self) | |||
def write(self, data): | |||
pass | |||
repr(self.FSpath), self.id, self.parentID, repr(self.title)) | |||
#@implementer(interfaces.IConsumer) | |||
#class NullConsumer(file, abstract.FileDescriptor): | |||
# | |||
# def __init__(self): | |||
# file.__init__(self, '/dev/null', 'w') | |||
# abstract.FileDescriptor.__init__(self) | |||
# | |||
# def write(self, data): | |||
# pass | |||
class DynamTransfer(protocol.ProcessProtocol): | |||
def __init__(self, path, mods, request): | |||
@@ -166,7 +166,7 @@ class DynamTransfer(protocol.ProcessProtocol): | |||
#'-vb', '8000k', | |||
#'-sc_threshold', '500000', '-b_strategy', '1', '-max_b_frames', '6', | |||
] + optdict[vcodec] + [ '-', ] | |||
log.msg(*[`i` for i in args]) | |||
log.msg(*[repr(i) for i in args]) | |||
self.proc = process.Process(reactor, ffmpeg_path, args, | |||
None, None, self) | |||
self.proc.closeStdin() | |||
@@ -203,6 +203,9 @@ class FSItem(FSObject, Item): | |||
mimetype = kwargs.pop('mimetype') | |||
kwargs['content'] = DynamicTrans(self.FSpath, | |||
static.File(self.FSpath, mimetype)) | |||
kwargs['date'] = datetime.datetime.utcfromtimestamp(os.stat(self.FSpath).st_mtime).isoformat() + '+00:00' | |||
Item.__init__(self, *args, **kwargs) | |||
self.url = '%s/%s' % (self.cd.urlbase, self.id) | |||
self.mimetype = mimetype | |||
@@ -30,6 +30,7 @@ mimetoclass = { | |||
def getClassMT(name, mimetype = None, fp = None): | |||
'''Return a tuple of the DIDLLite class and mimetype responsible for the named/mimetyped/fpd file.''' | |||
if mimetype is None: | |||
fn, ext = os.path.splitext(name) | |||
ext = ext.lower() | |||
@@ -40,9 +41,9 @@ def getClassMT(name, mimetype = None, fp = None): | |||
return None, None | |||
ty = mimetype.split('/')[0] | |||
if mimetoclass.has_key(mimetype): | |||
if mimetype in mimetoclass: | |||
klass = mimetoclass[mimetype] | |||
elif mimetoclass.has_key(ty): | |||
elif ty in mimetoclass: | |||
klass = mimetoclass[ty] | |||
else: | |||
# XXX - We could fall file -i on it | |||
@@ -64,7 +65,7 @@ def buildClassMT(baseklass, name, *args, **kwargs): | |||
class ret(baseklass, klass): | |||
pass | |||
ret.__name__ = '+'.join(map(lambda x: '%s.%s' % (x.__module__, x.__name__), (baseklass, klass))) | |||
ret.__name__ = '+'.join(['%s.%s' % (x.__module__, x.__name__) for x in (baseklass, klass)]) | |||
classdict[(baseklass, klass)] = ret | |||
@@ -1,39 +1,39 @@ | |||
This code is based upon code by Tim Potter. | |||
It is licensed under the MIT license at: | |||
http://opensource.org/licenses/mit-license.php | |||
PyMedS | |||
====== | |||
I got a D-Link DSM-520 but I needed a UPnP Media Server to stream data | |||
with. I tried one, but it had issues running under FreeBSD's Linux | |||
emulation. Since I know Python, I went looking for a python server | |||
and found this code. The code was a good framework, so I expanded upon | |||
it. | |||
This is a UPnP Media Server based upon a plugable architecture to allow | |||
other media repositories than just a file system. | |||
Tested basic functionality with the following devices and/or programs: | |||
Sony PlayStation 3 | |||
VLC | |||
BubbleUPnP (Android) | |||
Historically tested basic functionality with the following devices and/or programs: | |||
Cidero UPnP A/V Controller | |||
Intel's Media Control Point and Media Renderer | |||
D-Link DSM-520 | |||
Sony PlayStation 3 | |||
Linksys DMC-250 | |||
The Intel tools are good for testing (though Windows only) but have been | |||
moved. Not sure where they are located now. | |||
Usage | |||
----- | |||
Either make a directory media and put the files there, or make a symlink | |||
named media to your media files. Either will work. Run it as: | |||
./pymediaserv <localip> [ <http server port> ] | |||
``` | |||
./pymediaserv <localip> [ <http server port> ] | |||
``` | |||
The following packages are required to run the media server: | |||
* Twisted (tested w/ 8.2.0) - http://twistedmatrix.com/trac/ | |||
* ElementTree (only pre-Python 2.5) - | |||
http://effbot.org/zone/element-index.htm | |||
* SOAPpy - http://pywebsvcs.sourceforge.net/ | |||
* fpconst (required by SOAPpy) - | |||
http://sourceforge.net/project/showfiles.php?group_id=71248 | |||
* Twisted (tested w/ 22.10.0) - https://twisted.org/ | |||
* SOAPpy-py3 - https://github.com/Synerty/SOAPpy-py3 | |||
The requirements are in `requirements.txt` and can be installed | |||
via `pip intall -r requirements.txt`. | |||
Optional software packages: | |||
* rarfile - http://grue.l-t.ee/~marko/src/rarfile/ | |||
* CDDB-py - http://cddb-py.sourceforge.net/ | |||
Misc Issues | |||
----------- | |||
Thanks to Coherence for soap_lite that solved the issues w/ PS3 not seeing | |||
the media server. The PS3 with the latest firmware (2.50 and later) now | |||
@@ -50,6 +50,15 @@ Good Luck! | |||
John-Mark Gurney <jmg@funkthat.com> | |||
License Information | |||
------------------- | |||
This code is based upon code by Tim Potter. | |||
It is licensed under the MIT license at: | |||
http://opensource.org/licenses/mit-license.php | |||
Ideas for future improvements: | |||
I have received a few ECONNABORTED errors at times. The patch | |||
twisted.internet.tcp.py.patch catches this error, and handles |
@@ -52,27 +52,24 @@ class SSDPServer(DatagramProtocol): | |||
def doStop(self): | |||
'''Make sure we send out the byebye notifications.''' | |||
for st in self.known.keys(): | |||
for st in list(self.known.keys()): | |||
self.doByebye(st) | |||
del self.known[st] | |||
DatagramProtocol.doStop(self) | |||
def datagramReceived(self, data, (host, port)): | |||
def datagramReceived(self, data, hostporttup): | |||
"""Handle a received multicast datagram.""" | |||
# Break up message in to command and headers | |||
# TODO: use the email module after trimming off the request line.. | |||
# This gets us much better header support. | |||
host, port = hostporttup | |||
data = data.decode('ascii') | |||
header, payload = data.split('\r\n\r\n') | |||
lines = header.split('\r\n') | |||
cmd = string.split(lines[0], ' ') | |||
lines = map(lambda x: x.replace(': ', ':', 1), lines[1:]) | |||
lines = filter(lambda x: len(x) > 0, lines) | |||
cmd = lines[0].split(' ') | |||
lines = [x.replace(': ', ':', 1) for x in lines[1:]] | |||
lines = [x for x in lines if len(x) > 0] | |||
headers = [string.split(x, ':', 1) for x in lines] | |||
headers = dict(map(lambda x: (x[0].lower(), x[1]), headers)) | |||
headers = [x.split(':', 1) for x in lines] | |||
headers = dict([(x[0].lower(), x[1]) for x in headers]) | |||
if cmd[0] == 'M-SEARCH' and cmd[1] == '*': | |||
# SSDP discovery | |||
@@ -83,20 +80,20 @@ class SSDPServer(DatagramProtocol): | |||
else: | |||
log.msg('Unknown SSDP command %s %s' % cmd) | |||
def discoveryRequest(self, headers, (host, port)): | |||
def discoveryRequest(self, headers, hostporttup): | |||
"""Process a discovery request. The response must be sent to | |||
the address specified by (host, port).""" | |||
host, port = hostporttup | |||
log.msg('Discovery request for %s' % headers['st']) | |||
# Do we know about this service? | |||
if headers['st'] == 'ssdp:all': | |||
for i in self.known: | |||
hcopy = dict(headers.iteritems()) | |||
hcopy = dict(headers.items()) | |||
hcopy['st'] = i | |||
self.discoveryRequest(hcopy, (host, port)) | |||
return | |||
if not self.known.has_key(headers['st']): | |||
if headers['st'] not in self.known: | |||
return | |||
#print 'responding' | |||
@@ -110,7 +107,7 @@ class SSDPServer(DatagramProtocol): | |||
response.extend(('', '')) | |||
delay = random.randint(0, int(headers['mx'])) | |||
reactor.callLater(delay, self.transport.write, | |||
'\r\n'.join(response), (host, port)) | |||
b'\r\n'.join((bytes(x, 'ascii') for x in response)), (host, port)) | |||
def register(self, usn, st, location): | |||
"""Register a service or device that this SSDP server will | |||
@@ -144,12 +141,12 @@ class SSDPServer(DatagramProtocol): | |||
'Host: %s:%d' % (SSDP_ADDR, SSDP_PORT), | |||
'NTS: ssdp:byebye', | |||
] | |||
stcpy = dict(self.known[st].iteritems()) | |||
stcpy = dict(self.known[st].items()) | |||
stcpy['NT'] = stcpy['ST'] | |||
del stcpy['ST'] | |||
resp.extend(map(lambda x: ': '.join(x), stcpy.iteritems())) | |||
resp.extend([': '.join(x) for x in stcpy.items()]) | |||
resp.extend(('', '')) | |||
resp = '\r\n'.join(resp) | |||
resp = b'\r\n'.join(bytes(x, 'ascii') for x in resp) | |||
self.transport.write(resp, (SSDP_ADDR, SSDP_PORT)) | |||
self.transport.write(resp, (SSDP_ADDR, SSDP_PORT)) | |||
@@ -162,19 +159,19 @@ class SSDPServer(DatagramProtocol): | |||
'Host: %s:%d' % (SSDP_ADDR, SSDP_PORT), | |||
'NTS: ssdp:alive', | |||
] | |||
stcpy = dict(self.known[st].iteritems()) | |||
stcpy = dict(self.known[st].items()) | |||
stcpy['NT'] = stcpy['ST'] | |||
del stcpy['ST'] | |||
resp.extend(map(lambda x: ': '.join(x), stcpy.iteritems())) | |||
resp.extend([': '.join(x) for x in stcpy.items()]) | |||
resp.extend(('', '')) | |||
self.transport.write('\r\n'.join(resp), (SSDP_ADDR, SSDP_PORT)) | |||
self.transport.write(b'\r\n'.join(bytes(x, 'ascii') for x in resp), (SSDP_ADDR, SSDP_PORT)) | |||
def notifyReceived(self, headers, (host, port)): | |||
def notifyReceived(self, headers, hostporttup): | |||
"""Process a presence announcement. We just remember the | |||
details of the SSDP service announced.""" | |||
host, port = hostporttup | |||
if headers['nts'] == 'ssdp:alive': | |||
if not self.elements.has_key(headers['nt']): | |||
if headers['nt'] not in self.elements: | |||
# Register device/service | |||
self.elements[headers['nt']] = {} | |||
self.elements[headers['nt']]['USN'] = headers['usn'] | |||
@@ -182,7 +179,7 @@ class SSDPServer(DatagramProtocol): | |||
log.msg('Detected presence of %s' % headers['nt']) | |||
#log.msg('headers: %s' % `headers`) | |||
elif headers['nts'] == 'ssdp:byebye': | |||
if self.elements.has_key(headers['nt']): | |||
if headers['nt'] in self.elements: | |||
# Unregister device/service | |||
del(self.elements[headers['nt']]) | |||
log.msg('Detected absence for %s' % headers['nt']) | |||
@@ -6,21 +6,7 @@ __version__ = '$Change$' | |||
import itertools | |||
import os.path | |||
import sets | |||
import time | |||
import iterzipfile | |||
zipfile = iterzipfile | |||
import itertarfile | |||
tarfile = itertarfile | |||
try: | |||
import iterrarfile | |||
rarfile = iterrarfile | |||
except ImportError: | |||
class rarfile: | |||
pass | |||
rarfile = rarfile() | |||
rarfile.is_rarfile = lambda x: False | |||
import FileDIDL | |||
from DIDLLite import StorageFolder, Item, VideoItem, AudioItem, TextItem, ImageItem, Resource | |||
@@ -28,7 +28,7 @@ def bytespersecmt(mt): | |||
try: | |||
r = mttobytes[tmp[0].lower()] | |||
except KeyError: | |||
raise ValueError('invalid audio type: %s' % `tmp[0]`) | |||
raise ValueError('invalid audio type: %s' % repr(tmp[0])) | |||
v = set(('rate', 'channels')) | |||
for i in tmp[1:]: | |||
@@ -38,7 +38,7 @@ def bytespersecmt(mt): | |||
r *= int(value) | |||
else: | |||
raise ValueError('invalid audio parameter %s in %s' % | |||
(`arg`, `mt`)) | |||
(repr(arg), repr(mt))) | |||
return r | |||
@@ -67,7 +67,7 @@ class AudioPlayer(FileDescriptor): | |||
self._writeDisconnected = True | |||
def writeSomeData(self, data): | |||
print 'wsd:', len(data) | |||
print('wsd:', len(data)) | |||
return fdesc.writeToFD(self.fileno(), data) | |||
def doRead(self): | |||
@@ -76,7 +76,7 @@ class AudioPlayer(FileDescriptor): | |||
def connectionLost(self, reason): | |||
FileDescriptor.connectionLost(self, reason) | |||
print 'AP, connectionLost' | |||
print('AP, connectionLost') | |||
self.fileno = lambda: -1 | |||
self.setparameters = None | |||
if self._dev is not None: | |||
@@ -85,7 +85,7 @@ class AudioPlayer(FileDescriptor): | |||
self.attached = None | |||
def stopProducing(self): | |||
print 'AP, sp' | |||
print('AP, sp') | |||
self.writefun = lambda x: None | |||
FileDescriptor.stopProducing(self) | |||
@@ -137,13 +137,13 @@ class AudioResource(resource.Resource): | |||
nchan = int(nchan) | |||
rate = int(rate) | |||
except AttributeError: | |||
raise ValueError('Invalid audio format: %s' % `origfmt`) | |||
raise ValueError('Invalid audio format: %s' % repr(origfmt)) | |||
try: | |||
mt = self.mtformat[fmt] | |||
except KeyError: | |||
raise KeyError('No mime-type for audio format: %s.' % | |||
`origfmt`) | |||
repr(origfmt)) | |||
return '%s;rate=%d;channels=%d' % (mt, rate, nchan) | |||
@@ -158,7 +158,7 @@ class AudioResource(resource.Resource): | |||
try: | |||
request.setHeader('content-type', | |||
self.getmimetype(fmt, nchan, rate)) | |||
except (ValueError, AttributeError, KeyError), x: | |||
except (ValueError, AttributeError, KeyError) as x: | |||
return error.ErrorPage(http.UNSUPPORTED_MEDIA_TYPE, | |||
'Unsupported Media Type', str(x)).render(request) | |||
@@ -188,7 +188,7 @@ class ossaudiodev_fmts: | |||
pass | |||
for i in (k for k in dir(ossaudiodev) if k[:5] == 'AFMT_' and \ | |||
isinstance(getattr(ossaudiodev, k), (int, long))): | |||
isinstance(getattr(ossaudiodev, k), int)): | |||
setattr(ossaudiodev_fmts, i, getattr(ossaudiodev, i)) | |||
class AudioSource(AudioItem): | |||
@@ -219,7 +219,7 @@ def getfmtstrings(f): | |||
r.append(i) | |||
while f: | |||
print f, f & -f | |||
print(f, f & -f) | |||
r.append(f & -f) | |||
f ^= f & -f | |||
@@ -263,10 +263,10 @@ class FileConsumer: | |||
if __name__ == '__main__': | |||
if False: | |||
i = ossaudiodev.open('/dev/dsp2', 'r') | |||
print getfmtstrings(i.getfmts()) | |||
print(getfmtstrings(i.getfmts())) | |||
i.setparameters(ossaudiodev.AFMT_S16_BE, 2, 44100, True) | |||
print `i.read(16)` | |||
print(repr(i.read(16))) | |||
else: | |||
aplr = AudioPlayer('/dev/dsp2', 'r', | |||
(ossaudiodev.AFMT_S16_BE, 2, 44100, True)) | |||
@@ -29,7 +29,7 @@ def makeaudiomt(bitsps, rate, nchan): | |||
mt = mtformat[bitsps] | |||
except KeyError: | |||
raise KeyError('No mime-type for audio format: %s.' % | |||
`bitsps`) | |||
repr(bitsps)) | |||
return '%s;rate=%d;channels=%d' % (mt, rate, nchan) | |||
@@ -53,7 +53,7 @@ class DecoderProducer: | |||
self.resumeProducing() | |||
def __repr__(self): | |||
return '<DecoderProducer: decoder: %s, bytes left: %d, skip: %d>' % (`self.decoder`, self.tbytes, self.skipbytes) | |||
return '<DecoderProducer: decoder: %s, bytes left: %d, skip: %d>' % (repr(self.decoder), self.tbytes, self.skipbytes) | |||
def pauseProducing(self): | |||
# XXX - bug in Twisted 8.2.0 on pipelined requests this is | |||
@@ -99,11 +99,11 @@ class AudioResource(resource.Resource): | |||
self.cnt = cnt | |||
def __repr__(self): | |||
return '<AudioResource file: %s, dec: %s, start:%d, cnt: %d>' % (`self.f`, self.dec, self.start, self.cnt) | |||
return '<AudioResource file: %s, dec: %s, start:%d, cnt: %d>' % (repr(self.f), self.dec, self.start, self.cnt) | |||
def calcrange(self, rng, l): | |||
rng = rng.strip() | |||
unit, rangeset = rng.split('=') | |||
assert unit == 'bytes', `unit` | |||
assert unit == 'bytes', repr(unit) | |||
start, end = rangeset.split('-') | |||
start = int(start) | |||
if end: | |||
@@ -238,10 +238,10 @@ class AudioDisc(FSObject, MusicAlbum): | |||
return track['offset'] + index['offset'] | |||
def createObject(self, i, arg=None): | |||
'''This function returns the (class, name, *args, **kwargs) | |||
that will be passed to the addItem method of the | |||
ContentDirectory. arg will be passed the value of the dict | |||
keyed by i if genChildren is a dict.''' | |||
'''This function returns the (class, name, *args, **kwargs) | |||
that will be passed to the addItem method of the | |||
ContentDirectory. arg will be passed the value of the dict | |||
keyed by i if genChildren is a dict.''' | |||
oi = i | |||
i = int(i) | |||
@@ -273,7 +273,7 @@ class AudioDisc(FSObject, MusicAlbum): | |||
if tt in tags: | |||
if len(tags[tt]) != 1: | |||
# XXX - track this? | |||
print 'hun? ttitle:', `tags[tt]` | |||
print('hun? ttitle:', repr(tags[tt])) | |||
ttitle = tags[tt][0] | |||
if ' / ' in ttitle: | |||
@@ -338,8 +338,8 @@ class AudioRawBase(FSObject): | |||
self.res.append(r) | |||
def doUpdate(self): | |||
print 'dU:', `self`, self.baseObject.doUpdate | |||
print self.__class__.__bases__ | |||
print('dU:', repr(self), self.baseObject.doUpdate) | |||
print(self.__class__.__bases__) | |||
#import traceback | |||
#traceback.print_stack() | |||
self.baseObject.doUpdate(self) | |||
@@ -351,7 +351,7 @@ class AudioRawTrack(AudioRawBase, MusicTrack): | |||
baseObject = MusicTrack | |||
def detectaudioraw(origpath, fobj): | |||
for i in decoders.itervalues(): | |||
for i in decoders.values(): | |||
try: | |||
obj = i(origpath) | |||
# XXX - don't support down sampling yet | |||
@@ -378,7 +378,7 @@ def detectaudioraw(origpath, fobj): | |||
pass | |||
except: | |||
import traceback | |||
print 'WARNING: failed to parse toc:' | |||
print('WARNING: failed to parse toc:') | |||
traceback.print_exc() | |||
args['cuesheet'] = obj.cuesheet | |||
@@ -23,13 +23,13 @@ def decodestrend(i, pos): | |||
r.append('"') | |||
pos = bspos + 2 | |||
elif c in string.digits: | |||
r.append(unichr(int(i[bspos + 1:bspos + 4], 8))) | |||
r.append(chr(int(i[bspos + 1:bspos + 4], 8))) | |||
pos = bspos + 4 | |||
elif c == 'n': | |||
r.append('\n') | |||
pos = bspos + 2 | |||
else: | |||
raise ValueError('unknown escape char: %s' % `c`) | |||
raise ValueError('unknown escape char: %s' % repr(c)) | |||
else: | |||
r.append(i[pos:dqpos]) | |||
break | |||
@@ -92,7 +92,7 @@ def parsetoc(toc): | |||
elif key == '//': | |||
pass | |||
else: | |||
raise ValueError('unknown line: %s' % `i`) | |||
raise ValueError('unknown line: %s' % repr(i)) | |||
elif state == 1: | |||
if key == 'LANGUAGE_MAP': | |||
state = 2 | |||
@@ -135,5 +135,5 @@ if __name__ == '__main__': | |||
import sys | |||
for i in sys.argv[1:]: | |||
print 'file:', `i` | |||
print parsetoc(open(i).read()) | |||
print('file:', repr(i)) | |||
print(parsetoc(open(i).read())) |
@@ -28,7 +28,7 @@ class RingBuffer: | |||
self.cur=0 | |||
self.__class__ = RingBufferFull | |||
def get(self): | |||
""" return a list of elements from the oldest to the newest""" | |||
""" return a list of elements from the oldest to the newest""" | |||
return self.data | |||
class RingBufferFull: | |||
@@ -47,7 +47,7 @@ def doDebugging(opt): | |||
global insertnamespace, appendnamespace, insertringbuf | |||
def insertnamespace(k, v): | |||
assert isinstance(k, basestring) | |||
assert isinstance(k, str) | |||
sf.namespace[k] = v | |||
def appendnamespace(k, v): | |||
@@ -71,4 +71,4 @@ def doDebugging(opt): | |||
try: | |||
reactor.listenTCP(56283, sf) | |||
except twisted.internet.error.CannotListenError: | |||
print 'WARNING: cannot bind to debugger port.' | |||
print('WARNING: cannot bind to debugger port.') |
@@ -9,7 +9,6 @@ default_audio_lang = 'en' | |||
import itertools | |||
import os | |||
import sets | |||
import sys | |||
sys.path.append('mpegts') | |||
@@ -29,7 +29,7 @@ except ImportError: | |||
from xml import etree as elementtree | |||
except ImportError: | |||
#print "no ElementTree module found, critical error" | |||
raise ImportError, "no ElementTree module found, critical error" | |||
raise ImportError("no ElementTree module found, critical error") | |||
utf8_escape = re.compile(eval(r'u"[&<>\"]+"')) | |||
escape = re.compile(eval(r'u"[&<>\"\u0080-\uffff]+"')) | |||
@@ -60,12 +60,12 @@ def new_encode_entity(text, pattern=utf8_escape): | |||
if t is None: | |||
t = "&#%d;" % ord(char) | |||
append(t) | |||
if type(text) == unicode: | |||
if isinstance(text, str): | |||
return ''.join(out) | |||
else: | |||
return u''.encode('utf-8').join(out) | |||
return ''.encode('utf-8').join(out) | |||
try: | |||
if type(text) == unicode: | |||
if isinstance(text, str): | |||
return elementtree.ElementTree._encode(escape.sub(escape_entities, text), 'ascii') | |||
else: | |||
return elementtree.ElementTree._encode(utf8_escape.sub(escape_entities, text.decode('utf-8')), 'utf-8') | |||
@@ -95,7 +95,7 @@ def namespace_map_update(namespaces): | |||
elementtree.ElementTree._namespace_map.update(namespaces) | |||
class ElementInterface(elementtree.ElementTree._ElementInterface): | |||
class ElementInterface(elementtree.ElementTree.Element): | |||
""" helper class """ | |||
def indent(elem, level=0): | |||
@@ -128,8 +128,8 @@ def parse_xml(data, encoding="utf-8"): | |||
data = data.encode(encoding) | |||
except UnicodeDecodeError: | |||
pass | |||
except Exception, error: | |||
print "parse_xml encode Exception", error | |||
except Exception as error: | |||
print("parse_xml encode Exception", error) | |||
import traceback | |||
traceback.print_exc() | |||
@@ -137,9 +137,9 @@ def parse_xml(data, encoding="utf-8"): | |||
data = data.replace('\x00','') | |||
try: | |||
p.feed(data) | |||
except Exception, error: | |||
print "parse_xml feed Exception", error | |||
print error, repr(data) | |||
except Exception as error: | |||
print("parse_xml feed Exception", error) | |||
print(error, repr(data)) | |||
return None | |||
else: | |||
return ET.ElementTree(p.close()) |
@@ -54,7 +54,7 @@ class ItemObject(FSObject, Item): | |||
pt = getElementText(rtpel[0]) | |||
pi = 'rtsp-rtp-udp:*:%s:*' % pt | |||
else: | |||
print 'missing mimetype or rtppayloadtype element, skipping...' | |||
print('missing mimetype or rtppayloadtype element, skipping...') | |||
continue | |||
url = getElementText(i.getElementsByTagName('url')[0]) | |||
@@ -1,12 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Copyright 2008 John-Mark Gurney <jmg@funkthat.com> | |||
__version__ = '$Change$' | |||
# $Id$ | |||
import rarfile | |||
from rarfile import * | |||
class RarFile(rarfile.RarFile): | |||
def readiter(self, name, blksize=16384): | |||
yield self.read(name) |
@@ -1,37 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Copyright 2006 John-Mark Gurney <jmg@funkthat.com> | |||
__version__ = '$Change$' | |||
# $Id$ | |||
import tarfile | |||
from tarfile import * | |||
TAR_PLAIN = tarfile.TAR_PLAIN | |||
TAR_GZIPPED = tarfile.TAR_GZIPPED | |||
TAR_BZ2 = 'bz2' | |||
__all__ = tarfile.__all__ | |||
class TarFileCompat(tarfile.TarFileCompat): | |||
def __init__(self, file, mode="r", compression=TAR_PLAIN): | |||
if compression != TAR_BZ2: | |||
tarfile.TarFileCompat.__init__(self, file, mode, compression) | |||
return | |||
self.tarfile = TarFile.bz2open(file, mode) | |||
if mode[0:1] == "r": | |||
members = self.tarfile.getmembers() | |||
for i in xrange(len(members)): | |||
m = members[i] | |||
m.filename = m.name | |||
m.file_size = m.size | |||
m.date_time = time.gmtime(m.mtime)[:6] | |||
def readiter(self, name, blksize=16384): | |||
f = self.tarfile.extractfile(self.tarfile.getmember(name)) | |||
while True: | |||
data = f.read(blksize) | |||
if data == '': | |||
break | |||
yield data |
@@ -1,25 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Copyright 2006 John-Mark Gurney <jmg@funkthat.com> | |||
__version__ = '$Change$' | |||
# $Id$ | |||
import binascii | |||
import os | |||
import twisted.python.zipstream | |||
import zipfile | |||
from zipfile import * | |||
__all__ = zipfile.__all__ | |||
class ZipFile(twisted.python.zipstream.ChunkingZipFile): | |||
def readiter(self, name, blksize=16384): | |||
"""Return file bytes (as a string) for name.""" | |||
#print 'ri:', `self`, `name` | |||
fp = self.readfile(name) | |||
while True: | |||
d = fp.read(blksize) | |||
if not d: | |||
break | |||
yield d |
@@ -60,10 +60,10 @@ try: | |||
except ImportError: | |||
def foo(*args): | |||
raise NotImplementedError, 'Failed to import ctypes' | |||
raise NotImplementedError('Failed to import ctypes') | |||
decode_title = decode_description = foo | |||
except OSError: | |||
def foo(*args): | |||
raise NotImplementedError, 'Failed to find library huffdecode' | |||
raise NotImplementedError('Failed to find library huffdecode') | |||
decode_title = decode_description = foo |
@@ -30,18 +30,18 @@ | |||
import atschuff | |||
import itertools | |||
import os | |||
import sets | |||
import struct | |||
import time | |||
import traceback | |||
from functools import reduce | |||
TSSYNC = '\x47' | |||
TSPKTLEN = 188 | |||
READBLK = 1024 | |||
def attribreprlist(obj, attrs): | |||
return map(lambda x, y = obj: '%s: %s' % (x, repr(getattr(y, x))), | |||
itertools.ifilter(lambda x, y = obj: hasattr(y, x), attrs)) | |||
return list(map(lambda x, y = obj: '%s: %s' % (x, repr(getattr(y, x))), | |||
list(filter(lambda x, y = obj: hasattr(y, x), attrs)))) | |||
class UnReadSTR: | |||
def __init__(self, s): | |||
@@ -51,7 +51,7 @@ class UnReadSTR: | |||
self._buf = [] | |||
self._buftot = 0 | |||
def __nonzero__(self): | |||
def __bool__(self): | |||
return self._buftot or self.pos < len(self.s) | |||
def tell(self): | |||
@@ -122,7 +122,7 @@ def DVDAudioFilter(itr, subchan): | |||
for i in itr: | |||
j = Pack(UnReadSTR(i)) | |||
if filter(checksubchan, j): | |||
if list(filter(checksubchan, j)): | |||
yield i | |||
def findcodes(buf): | |||
@@ -138,53 +138,54 @@ def findcodes(buf): | |||
i = j + 4 | |||
return ret | |||
class UnRead(file): | |||
def __init__(self, *args, **kwargs): | |||
super(UnRead, self).__init__(*args, **kwargs) | |||
self._buf = [] | |||
self._buftot = 0 | |||
def unread(self, buf): | |||
self._buf.append(buf) | |||
self._buftot += len(buf) | |||
def peek(self, size): | |||
r = self.read(size) | |||
self.unread(r) | |||
return r | |||
def read(self, size = None): | |||
if size is None and self._buf: | |||
ret = self._buf.pop() | |||
self._buftot -= len(ret) | |||
elif size is None: | |||
ret = super(UnRead, self).read() | |||
else: | |||
ret = [] | |||
while size and self._buftot: | |||
ret.append(self._buf[-1][:size]) | |||
l = len(ret[-1]) | |||
if size > l: | |||
assert len(self._buf[-1]) == l | |||
self._buf.pop() | |||
else: | |||
self._buf[-1] = self._buf[-1][size:] | |||
self._buftot -= l | |||
size -= l | |||
if False: | |||
class UnRead(file): | |||
def __init__(self, *args, **kwargs): | |||
super(UnRead, self).__init__(*args, **kwargs) | |||
self._buf = [] | |||
self._buftot = 0 | |||
def unread(self, buf): | |||
self._buf.append(buf) | |||
self._buftot += len(buf) | |||
def peek(self, size): | |||
r = self.read(size) | |||
self.unread(r) | |||
return r | |||
def read(self, size = None): | |||
if size is None and self._buf: | |||
ret = self._buf.pop() | |||
self._buftot -= len(ret) | |||
elif size is None: | |||
ret = super(UnRead, self).read() | |||
else: | |||
ret = [] | |||
while size and self._buftot: | |||
ret.append(self._buf[-1][:size]) | |||
l = len(ret[-1]) | |||
if size > l: | |||
assert len(self._buf[-1]) == l | |||
self._buf.pop() | |||
else: | |||
self._buf[-1] = self._buf[-1][size:] | |||
self._buftot -= l | |||
size -= l | |||
if size: | |||
ret.append(super(UnRead, self).read(size)) | |||
if size: | |||
ret.append(super(UnRead, self).read(size)) | |||
ret = ''.join(ret) | |||
ret = ''.join(ret) | |||
return ret | |||
return ret | |||
def read_timestamp(buf): | |||
assert len(buf) == 5 | |||
assert (ord(buf[0]) & 0x1) == 1 | |||
assert (ord(buf[2]) & 0x1) == 1 | |||
assert (ord(buf[4]) & 0x1) == 1 | |||
return (long(ord(buf[0]) & 0xe) << 29) | (ord(buf[1]) << 21) | \ | |||
return (int(ord(buf[0]) & 0xe) << 29) | (ord(buf[1]) << 21) | \ | |||
((ord(buf[2]) & 0xfe) << 14) | (ord(buf[3]) << 7) | \ | |||
((ord(buf[4]) & 0xfe) >> 1) | |||
@@ -193,7 +194,7 @@ def read_escr(buf): | |||
assert (ord(buf[0]) & 0x4) == 0x4 and (ord(buf[2]) & 0x4) == 0x4 | |||
assert (ord(buf[4]) & 0x4) == 0x4 and (ord(buf[5]) & 0x1) == 0x1 | |||
base = (long(ord(buf[0]) & 0x38) << 27) | ((ord(buf[0]) & 0x3) << 28) |\ | |||
base = (int(ord(buf[0]) & 0x38) << 27) | ((ord(buf[0]) & 0x3) << 28) |\ | |||
(ord(buf[1]) << 20) | ((ord(buf[2]) & 0xf8) << 15) | \ | |||
((ord(buf[2]) & 0x3) << 13) | (ord(buf[3]) << 5) | \ | |||
((ord(buf[4]) & 0xf8) >> 3) | |||
@@ -240,7 +241,7 @@ class PES: | |||
else: | |||
self.length += 6 | |||
if len(buf) < self.length: | |||
raise IndexError, 'not enough data' | |||
raise IndexError('not enough data') | |||
if self.stream_id == self.PADDING_ID: | |||
# Validate padding? | |||
@@ -280,8 +281,7 @@ class PES: | |||
self.DTS = read_timestamp(buf[i:i + 5]) | |||
i += 5 | |||
elif ptsdts_flag == 0x1: | |||
raise ValueError, \ | |||
"ptsdts flag forbidden: %d" % ptsdts_flag | |||
raise ValueError("ptsdts flag forbidden: %d" % ptsdts_flag) | |||
if escr_flag: | |||
self.ESCR = read_escr(buf[i:i + 6]) | |||
i += 6 | |||
@@ -373,7 +373,7 @@ class Pack(list): | |||
assert (ord(d[4]) & 0xc0) == 0x40 | |||
self.SCR = read_escr(d[4:10]) | |||
assert ord(d[12]) & 0x3 == 0x3 | |||
m = map(ord, d[10:13]) | |||
m = list(map(ord, d[10:13])) | |||
self.muxr = (m[0] << 14) | (m[1] << 6) | (m[2] >> 2) | |||
self.stuff_len = ord(d[13]) & 0x7 | |||
f.read(self.stuff_len) | |||
@@ -384,7 +384,7 @@ class Pack(list): | |||
f.read(6) | |||
hlen = (ord(d[4]) << 8) | ord(d[5]) | |||
header = f.read(hlen) | |||
oh = map(ord, header) | |||
oh = list(map(ord, header)) | |||
assert (oh[0] & 0x80) == 0x80 and \ | |||
(oh[2] & 0x1) == 0x1 | |||
self.rate_bound = ((oh[0] & 0x7f) << 15) | \ | |||
@@ -401,7 +401,7 @@ class Pack(list): | |||
d = f.peek(1) | |||
self.streams = {} | |||
while ord(d) & 0x80: | |||
d = map(ord, f.read(3)) | |||
d = list(map(ord, f.read(3))) | |||
assert (d[1] & 0xc0) == 0xc0 | |||
scaleflag = bool(d[1] & 0x20) | |||
self.streams[d[0]] = (((d[1] & 0x1f) << | |||
@@ -437,8 +437,8 @@ class Pack(list): | |||
def __str__(self): | |||
buf = [] | |||
buf.append('\x00\x00\x01\xba') | |||
clock = (1l << 46) | (((self.SCR[0] >> 30) & 0x7) << 43) | \ | |||
(1l << 42) | (((self.SCR[0] >> 15) & 0x7ffff) << 27) | \ | |||
clock = (1 << 46) | (((self.SCR[0] >> 30) & 0x7) << 43) | \ | |||
(1 << 42) | (((self.SCR[0] >> 15) & 0x7ffff) << 27) | \ | |||
(1 << 26) | ((self.SCR[0] & 0x7fff) << 11) | (1 << 10) | \ | |||
((self.SCR[1] << 1) & 0x3fe) | 0x1 | |||
for i in range(6): | |||
@@ -449,7 +449,7 @@ class Pack(list): | |||
buf.append(chr(((muxr << 2) & 0xfc) | 0x3)) | |||
buf.append(chr(0xf8 | (self.stuff_len & 7))) | |||
buf.append('\xff' * self.stuff_len) | |||
buf.extend(map(str, self)) | |||
buf.extend(list(map(str, self))) | |||
return ''.join(buf) | |||
# These are strings due to the floating point numbers | |||
@@ -491,7 +491,7 @@ class ISO639LangDescriptor(list): | |||
assert len(b) % 4 == 0 | |||
for i in range(len(b) / 4): | |||
lang = unicode(b[i * 4:i * 4 + 3], 'iso8859-1') | |||
lang = str(b[i * 4:i * 4 + 3], 'iso8859-1') | |||
atype = self.atypedict[ord(b[i * 4 + 3])] | |||
self.append((lang, atype)) | |||
@@ -601,9 +601,7 @@ class AC3Descriptor: | |||
else: | |||
assert NotImplementedError, \ | |||
'the following code is untested' | |||
self.text = ''.join(map(lambda x: | |||
unichr(ord(x[0]) * 256 + ord(x[1])), | |||
[txt[i:i+2] for i in range(0, len(txt), 2)])) | |||
self.text = ''.join([chr(ord(x[0]) * 256 + ord(x[1])) for x in [txt[i:i+2] for i in range(0, len(txt), 2)]]) | |||
def __repr__(self): | |||
v = ['sample_rate', 'bsid', 'br_exact', 'bitrate', | |||
@@ -619,11 +617,11 @@ class ContentAdvisory(list): | |||
cnt = ord(data[0]) & 0x3f | |||
i = 1 | |||
for j in xrange(cnt): | |||
for j in range(cnt): | |||
region, dim = struct.unpack('>BB', data[i: i + 2]) | |||
i += 2 | |||
d = {} | |||
for j in xrange(dim): | |||
for j in range(dim): | |||
d[ord(data[i])] = ord(data[i + 1]) & 0xf | |||
i += 2 | |||
desclen = ord(data[i]) | |||
@@ -669,13 +667,13 @@ class MultiStringStruct(dict): | |||
return data.decode('UTF-16-BE') | |||
elif mode == 0x3e: | |||
# http://www.unicode.org/reports/tr6/ | |||
raise NotImplementedError, 'Unicode Technical Report #6, A Standard Compression Scheme for Unicode' | |||
raise NotImplementedError('Unicode Technical Report #6, A Standard Compression Scheme for Unicode') | |||
# There are additional limitations | |||
assert mode < 0x34, 'Invalid mode: %#x' % mode | |||
return ''.join(map(lambda x, y = mode * 256: | |||
unichr(ord(x) + y), data)) | |||
chr(ord(x) + y), data)) | |||
assert (comp == 1 or comp == 2) and mode == 0xff, \ | |||
'Invalid comp: %#x, mode: %#x' % (comp, mode) | |||
@@ -707,7 +705,7 @@ class ComponentNameDescriptor(MultiStringStruct): | |||
MultiStringStruct.__repr__(self) | |||
def FindMe(data): | |||
raise RuntimeError, 'found me' | |||
raise RuntimeError('found me') | |||
Descriptors = { | |||
# 0-63 Are listed in ISO 13818-1 Table 2-40 | |||
@@ -738,82 +736,82 @@ PIDs = { | |||
} | |||
def psip_calc_crc32(data, verbose = False, table = ( | |||
0x00000000l, 0x04c11db7l, 0x09823b6el, 0x0d4326d9l, | |||
0x130476dcl, 0x17c56b6bl, 0x1a864db2l, 0x1e475005l, | |||
0x2608edb8l, 0x22c9f00fl, 0x2f8ad6d6l, 0x2b4bcb61l, | |||
0x350c9b64l, 0x31cd86d3l, 0x3c8ea00al, 0x384fbdbdl, | |||
0x4c11db70l, 0x48d0c6c7l, 0x4593e01el, 0x4152fda9l, | |||
0x5f15adacl, 0x5bd4b01bl, 0x569796c2l, 0x52568b75l, | |||
0x6a1936c8l, 0x6ed82b7fl, 0x639b0da6l, 0x675a1011l, | |||
0x791d4014l, 0x7ddc5da3l, 0x709f7b7al, 0x745e66cdl, | |||
0x9823b6e0l, 0x9ce2ab57l, 0x91a18d8el, 0x95609039l, | |||
0x8b27c03cl, 0x8fe6dd8bl, 0x82a5fb52l, 0x8664e6e5l, | |||
0xbe2b5b58l, 0xbaea46efl, 0xb7a96036l, 0xb3687d81l, | |||
0xad2f2d84l, 0xa9ee3033l, 0xa4ad16eal, 0xa06c0b5dl, | |||
0xd4326d90l, 0xd0f37027l, 0xddb056fel, 0xd9714b49l, | |||
0xc7361b4cl, 0xc3f706fbl, 0xceb42022l, 0xca753d95l, | |||
0xf23a8028l, 0xf6fb9d9fl, 0xfbb8bb46l, 0xff79a6f1l, | |||
0xe13ef6f4l, 0xe5ffeb43l, 0xe8bccd9al, 0xec7dd02dl, | |||
0x34867077l, 0x30476dc0l, 0x3d044b19l, 0x39c556ael, | |||
0x278206abl, 0x23431b1cl, 0x2e003dc5l, 0x2ac12072l, | |||
0x128e9dcfl, 0x164f8078l, 0x1b0ca6a1l, 0x1fcdbb16l, | |||
0x018aeb13l, 0x054bf6a4l, 0x0808d07dl, 0x0cc9cdcal, | |||
0x7897ab07l, 0x7c56b6b0l, 0x71159069l, 0x75d48ddel, | |||
0x6b93dddbl, 0x6f52c06cl, 0x6211e6b5l, 0x66d0fb02l, | |||
0x5e9f46bfl, 0x5a5e5b08l, 0x571d7dd1l, 0x53dc6066l, | |||
0x4d9b3063l, 0x495a2dd4l, 0x44190b0dl, 0x40d816bal, | |||
0xaca5c697l, 0xa864db20l, 0xa527fdf9l, 0xa1e6e04el, | |||
0xbfa1b04bl, 0xbb60adfcl, 0xb6238b25l, 0xb2e29692l, | |||
0x8aad2b2fl, 0x8e6c3698l, 0x832f1041l, 0x87ee0df6l, | |||
0x99a95df3l, 0x9d684044l, 0x902b669dl, 0x94ea7b2al, | |||
0xe0b41de7l, 0xe4750050l, 0xe9362689l, 0xedf73b3el, | |||
0xf3b06b3bl, 0xf771768cl, 0xfa325055l, 0xfef34de2l, | |||
0xc6bcf05fl, 0xc27dede8l, 0xcf3ecb31l, 0xcbffd686l, | |||
0xd5b88683l, 0xd1799b34l, 0xdc3abdedl, 0xd8fba05al, | |||
0x690ce0eel, 0x6dcdfd59l, 0x608edb80l, 0x644fc637l, | |||
0x7a089632l, 0x7ec98b85l, 0x738aad5cl, 0x774bb0ebl, | |||
0x4f040d56l, 0x4bc510e1l, 0x46863638l, 0x42472b8fl, | |||
0x5c007b8al, 0x58c1663dl, 0x558240e4l, 0x51435d53l, | |||
0x251d3b9el, 0x21dc2629l, 0x2c9f00f0l, 0x285e1d47l, | |||
0x36194d42l, 0x32d850f5l, 0x3f9b762cl, 0x3b5a6b9bl, | |||
0x0315d626l, 0x07d4cb91l, 0x0a97ed48l, 0x0e56f0ffl, | |||
0x1011a0fal, 0x14d0bd4dl, 0x19939b94l, 0x1d528623l, | |||
0xf12f560el, 0xf5ee4bb9l, 0xf8ad6d60l, 0xfc6c70d7l, | |||
0xe22b20d2l, 0xe6ea3d65l, 0xeba91bbcl, 0xef68060bl, | |||
0xd727bbb6l, 0xd3e6a601l, 0xdea580d8l, 0xda649d6fl, | |||
0xc423cd6al, 0xc0e2d0ddl, 0xcda1f604l, 0xc960ebb3l, | |||
0xbd3e8d7el, 0xb9ff90c9l, 0xb4bcb610l, 0xb07daba7l, | |||
0xae3afba2l, 0xaafbe615l, 0xa7b8c0ccl, 0xa379dd7bl, | |||
0x9b3660c6l, 0x9ff77d71l, 0x92b45ba8l, 0x9675461fl, | |||
0x8832161al, 0x8cf30badl, 0x81b02d74l, 0x857130c3l, | |||
0x5d8a9099l, 0x594b8d2el, 0x5408abf7l, 0x50c9b640l, | |||
0x4e8ee645l, 0x4a4ffbf2l, 0x470cdd2bl, 0x43cdc09cl, | |||
0x7b827d21l, 0x7f436096l, 0x7200464fl, 0x76c15bf8l, | |||
0x68860bfdl, 0x6c47164al, 0x61043093l, 0x65c52d24l, | |||
0x119b4be9l, 0x155a565el, 0x18197087l, 0x1cd86d30l, | |||
0x029f3d35l, 0x065e2082l, 0x0b1d065bl, 0x0fdc1becl, | |||
0x3793a651l, 0x3352bbe6l, 0x3e119d3fl, 0x3ad08088l, | |||
0x2497d08dl, 0x2056cd3al, 0x2d15ebe3l, 0x29d4f654l, | |||
0xc5a92679l, 0xc1683bcel, 0xcc2b1d17l, 0xc8ea00a0l, | |||
0xd6ad50a5l, 0xd26c4d12l, 0xdf2f6bcbl, 0xdbee767cl, | |||
0xe3a1cbc1l, 0xe760d676l, 0xea23f0afl, 0xeee2ed18l, | |||
0xf0a5bd1dl, 0xf464a0aal, 0xf9278673l, 0xfde69bc4l, | |||
0x89b8fd09l, 0x8d79e0bel, 0x803ac667l, 0x84fbdbd0l, | |||
0x9abc8bd5l, 0x9e7d9662l, 0x933eb0bbl, 0x97ffad0cl, | |||
0xafb010b1l, 0xab710d06l, 0xa6322bdfl, 0xa2f33668l, | |||
0xbcb4666dl, 0xb8757bdal, 0xb5365d03l, 0xb1f740b4l | |||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, | |||
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, | |||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, | |||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, | |||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, | |||
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, | |||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, | |||
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, | |||
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, | |||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, | |||
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, | |||
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, | |||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, | |||
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, | |||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, | |||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, | |||
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, | |||
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, | |||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, | |||
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, | |||
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, | |||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, | |||
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, | |||
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, | |||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, | |||
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, | |||
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, | |||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, | |||
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, | |||
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, | |||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, | |||
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, | |||
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, | |||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, | |||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, | |||
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, | |||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, | |||
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, | |||
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, | |||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, | |||
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, | |||
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, | |||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, | |||
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, | |||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, | |||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, | |||
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, | |||
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, | |||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, | |||
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, | |||
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, | |||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, | |||
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, | |||
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, | |||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, | |||
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, | |||
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, | |||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, | |||
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, | |||
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, | |||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, | |||
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, | |||
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, | |||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 | |||
)): | |||
'''Validate a PSIP CRC. Include the CRC in the data. The return value will be the valid data, or an exception will be raised if invalid.''' | |||
if verbose: | |||
i_crc = 0xffffffffl | |||
i_crc = 0xffffffff | |||
for i in data: | |||
i_crc = ((i_crc << 8) & 0xffffffffl) ^ table[(i_crc >> | |||
i_crc = ((i_crc << 8) & 0xffffffff) ^ table[(i_crc >> | |||
24) ^ ord(i)] | |||
print hex(i_crc) | |||
print(hex(i_crc)) | |||
else: | |||
i_crc = reduce(lambda x, y: ((x << 8) & 0xffffffffl) ^ | |||
table[(x >> 24) ^ ord(y)], data, 0xffffffffl) | |||
i_crc = reduce(lambda x, y: ((x << 8) & 0xffffffff) ^ | |||
table[(x >> 24) ^ ord(y)], data, 0xffffffff) | |||
return i_crc | |||
def psip_crc32(data): | |||
@@ -824,7 +822,7 @@ def getdescriptors(tb): | |||
i = 0 | |||
while i < len(tb): | |||
t = ord(tb[i]) | |||
if d.has_key(t): | |||
if t in d: | |||
l = ord(tb[i + 1]) | |||
data = tb[i + 2: i + 2 + l] | |||
#print repr(d[t]), t, repr(data) | |||
@@ -918,9 +916,8 @@ and the key is the table number.''' | |||
# XXX I may need to include the skipped part | |||
# above in the crc calculations. | |||
if not psip_crc32(payload[:self.sect_len]): | |||
raise ValueError, \ | |||
'CRC check failed: %s' % \ | |||
`payload[:self.sect_len]` | |||
raise ValueError('CRC check failed: %s' % \ | |||
repr(payload[:self.sect_len])) | |||
self.extension = (ord(payload[3]) << 8) | \ | |||
ord(payload[4]) | |||
self.version = (ord(payload[5]) & 0x3e) >> 1 | |||
@@ -1007,7 +1004,7 @@ class PAT(PSIPObject, dict): | |||
self.clear() | |||
def has_pid(self, pid): | |||
return self.pid_dict.has_key(pid) | |||
return pid in self.pid_dict | |||
def get_prog(self, pid): | |||
return self.pid_dict[pid] | |||
@@ -1036,8 +1033,8 @@ def getaudiovideopids(pmt, lang = None): | |||
vpids.append(cpid) | |||
elif i[0] == 129: | |||
apids.append(cpid) | |||
elif j.has_key(5) and i[0] != 5: | |||
assert 'AC-3' in map(lambda x: x[:4], j[5]), (i, j) | |||
elif 5 in j and i[0] != 5: | |||
assert 'AC-3' in [x[:4] for x in j[5]], (i, j) | |||
if lang is None or lang == j[10][0][0]: | |||
apids.append(cpid) | |||
else: | |||
@@ -1067,7 +1064,7 @@ class PMT(PSIPObject, dict): | |||
self.clear() | |||
del self.es[:] | |||
def __nonzero__(self): | |||
def __bool__(self): | |||
return len(self) or bool(self.es) | |||
def parse_table(self, psip): | |||
@@ -1092,7 +1089,7 @@ class PMT(PSIPObject, dict): | |||
def repr_part(self): | |||
return [ 'PCRpid: %d' % self.pcrpid, dict.__repr__(self), | |||
'ES: %s' % `self.es` ] | |||
'ES: %s' % repr(self.es) ] | |||
def channelmajorminorsort(x, y): | |||
if x['major'] != y['major']: | |||
@@ -1131,7 +1128,7 @@ class STT(PSIPObject): | |||
self.ds_hour = ds_hour | |||
def repr_part(self, v=('ds_status', 'ds_day_of_month', 'ds_hour', )): | |||
return [ `time.ctime(self.utc)`, ] + attribreprlist(self, v) | |||
return [ repr(time.ctime(self.utc)), ] + attribreprlist(self, v) | |||
class MGT(list): | |||
def __init__(self, pidtable): | |||
@@ -1149,7 +1146,7 @@ class MGT(list): | |||
ntables = struct.unpack('>H', psip.table[1:3])[0] | |||
i = 3 | |||
for foo in xrange(ntables): | |||
for foo in range(ntables): | |||
type, pid, version, nbytes, desclen = \ | |||
struct.unpack('>HHBIH', psip.table[i:i + 11]) | |||
i += 11 | |||
@@ -1162,7 +1159,7 @@ class MGT(list): | |||
# start watch | |||
if type >= 0x100 and type <= 0x17f: | |||
if self.pidtable.has_key(pid): | |||
if pid in self.pidtable: | |||
# XXX - check that it's in watch | |||
pass | |||
else: | |||
@@ -1171,7 +1168,7 @@ class MGT(list): | |||
self.pidtable[pid] = TSPSIPHandler({ | |||
0xcb: EIT() }) | |||
elif type >= 0x200 and type <= 0x27f: | |||
if self.pidtable.has_key(pid): | |||
if pid in self.pidtable: | |||
# XXX - check that it's in watch | |||
pass | |||
else: | |||
@@ -1189,7 +1186,7 @@ class MGT(list): | |||
#print `self` | |||
def __repr__(self): | |||
return '<MGT: descriptors: %s, loop: %s>' % (`self.desc`, | |||
return '<MGT: descriptors: %s, loop: %s>' % (repr(self.desc), | |||
list.__repr__(self)) | |||
class EIT(list): | |||
@@ -1206,7 +1203,7 @@ class EIT(list): | |||
ntables = ord(psip.table[1]) | |||
i = 2 | |||
for foo in xrange(ntables): | |||
for foo in range(ntables): | |||
event_id, start_time, lochilen, lolength, titlelen = \ | |||
struct.unpack('>HIBHB', psip.table[i:i + 10]) | |||
i += 10 | |||
@@ -1249,9 +1246,9 @@ class TVCT(PSIPObject, dict): | |||
chancnt = ord(tb[i]) | |||
i += 1 | |||
for foo in range(chancnt): | |||
shrtnm = ''.join(map(lambda x: unichr((ord(x[0]) << | |||
8) | ord(x[1])), [tb[i + x * 2:i + (x + 1) * 2] for | |||
x in range(7)])).rstrip(unichr(0)) | |||
shrtnm = ''.join([chr((ord(x[0]) << | |||
8) | ord(x[1])) for x in [tb[i + x * 2:i + (x + 1) * 2] for | |||
x in range(7)]]).rstrip(chr(0)) | |||
i += 7 * 2 | |||
major = (((ord(tb[i]) << 8) | ord(tb[i + 1])) >> 2) & \ | |||
0x3ff | |||
@@ -1337,7 +1334,7 @@ class TSPESHandler: | |||
payload = p.payload | |||
if payload[:3] != '\x00\x00\x01': | |||
raise ValueError, 'packet start code invalid' | |||
raise ValueError('packet start code invalid') | |||
self.stream_id = ord(payload[3]) | |||
self.pes_len = (ord(payload[4]) << 8) | ord(payload[5]) | |||
if not self.is_video(): | |||
@@ -1373,7 +1370,7 @@ class TSPESHandler: | |||
def read_clock(buf): | |||
assert len(buf) == 6 | |||
base = (long(ord(buf[0])) << 25) | (ord(buf[1]) << 17) | \ | |||
base = (int(ord(buf[0])) << 25) | (ord(buf[1]) << 17) | \ | |||
(ord(buf[2]) << 9) | (ord(buf[3]) << 1) | \ | |||
(ord(buf[4]) >> 7) | |||
extension = ((ord(buf[4]) & 0x1) << 8) | ord(buf[5]) | |||
@@ -1609,27 +1606,27 @@ import re | |||
import sys | |||
def usage(): | |||
print 'Usage: %s -lmty <mpegtsstream>' % sys.argv[0] | |||
print ' %s -k <pid> <mpegtsstream>' % sys.argv[0] | |||
print ' %s -b [ -p ] <mpegtsstream>' % sys.argv[0] | |||
print ' %s -c <channel> -o <output> <mpegtsstream>' % sys.argv[0] | |||
print '' | |||
print ' -l list channels' | |||
print ' -m print PAT and PMT' | |||
print ' -t print TVCT' | |||
print '' | |||
print ' -b bandwidth' | |||
print ' -p sort by percentage' | |||
print '' | |||
print ' -c channel to capture' | |||
print ' -o file to output channel' | |||
print '' | |||
print ' -k print PCR of pid stream' | |||
print '' | |||
print 'Options for all:' | |||
print ' -y file offset when done' | |||
print ' -s <start> Starting pos' | |||
print ' -e <end> Ending pos' | |||
print('Usage: %s -lmty <mpegtsstream>' % sys.argv[0]) | |||
print(' %s -k <pid> <mpegtsstream>' % sys.argv[0]) | |||
print(' %s -b [ -p ] <mpegtsstream>' % sys.argv[0]) | |||
print(' %s -c <channel> -o <output> <mpegtsstream>' % sys.argv[0]) | |||
print('') | |||
print(' -l list channels') | |||
print(' -m print PAT and PMT') | |||
print(' -t print TVCT') | |||
print('') | |||
print(' -b bandwidth') | |||
print(' -p sort by percentage') | |||
print('') | |||
print(' -c channel to capture') | |||
print(' -o file to output channel') | |||
print('') | |||
print(' -k print PCR of pid stream') | |||
print('') | |||
print('Options for all:') | |||
print(' -y file offset when done') | |||
print(' -s <start> Starting pos') | |||
print(' -e <end> Ending pos') | |||
def findchannel(tvct, chan): | |||
for i in tvct['channels']: | |||
@@ -1661,18 +1658,18 @@ def GetTVCT(tsstream): | |||
} | |||
def getpmt(pid, pm = pmts, psp = psippids): | |||
if not pm.has_key(pid): | |||
if pid not in pm: | |||
pm[pid] = PMT() | |||
psp[pid] = TSPSIPHandler({ 0x02: pm[pid] }) | |||
def needpmts(pm = pmts): | |||
for i in pm.itervalues(): | |||
for i in pm.values(): | |||
if not i: | |||
return True | |||
return False | |||
for i in itertools.imap(TSPacket, tsstream): | |||
for i in map(TSPacket, tsstream): | |||
try: | |||
psippids[i.pid](i) | |||
except ValueError: | |||
@@ -1689,7 +1686,7 @@ def GetTVCT(tsstream): | |||
if needpat and pat: | |||
needpat = False | |||
for j in pat.itervalues(): | |||
for j in pat.values(): | |||
getpmt(j) | |||
if not (needtvct or needpat or needpmts()): | |||
@@ -1700,11 +1697,10 @@ def GetTVCT(tsstream): | |||
lst.sort(channelmajorminorsort) | |||
except KeyError: | |||
# unable to find TVCT | |||
lst = pat.items() | |||
lst.sort() | |||
lst = map(lambda x, y: { 'name': 'PAT%d' % x[1], | |||
lst = sorted(list(pat.items())) | |||
lst = list(map(lambda x, y: { 'name': 'PAT%d' % x[1], | |||
'prog_num': x[1], 'major': '?', 'minor': y}, lst, | |||
range(1, len(pat) + 1)) | |||
list(range(1, len(pat) + 1)))) | |||
tvct = { 'channels': lst } | |||
for i in lst: | |||
@@ -1817,12 +1813,12 @@ def main(): | |||
}) | |||
def getpmt(pid, pm = pmts, psp = psippids): | |||
if not pm.has_key(pid): | |||
if pid not in pm: | |||
pm[pid] = PMT() | |||
psp[pid] = TSPSIPHandler({ 0x02: pm[pid] }) | |||
def needpmts(pm = pmts): | |||
for i in pm.itervalues(): | |||
for i in pm.values(): | |||
if not i: | |||
return True | |||
@@ -1831,7 +1827,7 @@ def main(): | |||
lastpcr = None | |||
lastpatpos = None | |||
for i in itertools.imap(TSPacket, s): | |||
for i in map(TSPacket, s): | |||
#if hasattr(i, 'splice_countdown') or hasattr(i, 'DTS_next_AU'): | |||
# print 'splice_countdown:', repr(i) | |||
#if hasattr(i, 'PCR'): | |||
@@ -1847,15 +1843,15 @@ def main(): | |||
if lastpcr is not None: | |||
# I've only seen 2703 as the largest | |||
if i.PCR[0] - lastpcr[0] > 3000: | |||
print lastpatpos | |||
print(lastpatpos) | |||
lastpcr = i.PCR | |||
try: | |||
psippids[i.pid](i) | |||
except ValueError, x: | |||
except ValueError as x: | |||
#import traceback | |||
#print traceback.print_exc() | |||
print >>sys.stderr, 'bad crc:', repr(i) | |||
print('bad crc:', repr(i), file=sys.stderr) | |||
continue | |||
except KeyError: | |||
pass | |||
@@ -1888,7 +1884,7 @@ def main(): | |||
if needpat and pat: | |||
needpat = False | |||
for pn, j in pat.iteritems(): | |||
for pn, j in pat.items(): | |||
if pn == 0: | |||
# XXX - NIT | |||
continue | |||
@@ -1896,8 +1892,8 @@ def main(): | |||
getpmt(j) | |||
if needallmaps and pat and pmts: | |||
for i in pat.itervalues(): | |||
if not pmts.has_key(i): | |||
for i in pat.values(): | |||
if i not in pmts: | |||
break | |||
needallmaps = False | |||
@@ -1914,11 +1910,11 @@ def main(): | |||
output)) | |||
if allmaps: | |||
print repr(pat) | |||
print repr(pmts) | |||
print(repr(pat)) | |||
print(repr(pmts)) | |||
if printtvct: | |||
print repr(tvct) | |||
print(repr(tvct)) | |||
if listchan: | |||
#List channels | |||
@@ -1935,16 +1931,15 @@ def main(): | |||
if i['prog_num'] != 0 and i['prog_num'] != 0xffff: | |||
#print repr(pmts[pat[i['prog_num']]]) | |||
av = getaudiovideopids(pmts[pat[i['prog_num']]]) | |||
prog_info = '\t'.join(map(lambda x: | |||
','.join(map(str, x)), av)) | |||
prog_info = '\t'.join([','.join(map(str, x)) for x in av]) | |||
else: | |||
prog_info = '' | |||
print ('%(major)d.%(minor)d\t%(name)s\t' % i) + \ | |||
prog_info | |||
print(('%(major)d.%(minor)d\t%(name)s\t' % i) + \ | |||
prog_info) | |||
if printbandwidth: | |||
totpkts = sum(pidcnt.itervalues()) | |||
i = pidcnt.items() | |||
totpkts = sum(pidcnt.values()) | |||
i = list(pidcnt.items()) | |||
if printbandwidthpercent: | |||
def secondfirst(x, y): | |||
if x[1] == y[1]: | |||
@@ -1954,11 +1949,11 @@ def main(): | |||
else: | |||
i.sort() | |||
for pid, cnt in i: | |||
print '%4d\t%d\t%5.2f' % (pid, cnt, | |||
float(cnt) * 100 / totpkts) | |||
print('%4d\t%d\t%5.2f' % (pid, cnt, | |||
float(cnt) * 100 / totpkts)) | |||
if printbyteoffset: | |||
print inp.tell() | |||
print(inp.tell()) | |||
def justprint(v, p): | |||
'''v is pid, p is the data''' | |||
@@ -1966,15 +1961,15 @@ def justprint(v, p): | |||
return | |||
pes = PES(p) | |||
if pes.data[3] != '\x00': | |||
print `pes` | |||
print(repr(pes)) | |||
return | |||
fc = findcodes(pes.data) | |||
print 'justprint', v, len(p), repr(pes), repr(pes.data[:20]), fc | |||
for i in filter(lambda x: x[1] == '\x00', fc): | |||
print `pes.data[i[0] + 3: i[0] + 7]` | |||
print('justprint', v, len(p), repr(pes), repr(pes.data[:20]), fc) | |||
for i in [x for x in fc if x[1] == '\x00']: | |||
print(repr(pes.data[i[0] + 3: i[0] + 7])) | |||
if ((ord(pes.data[i[0] + 5]) & 0x38) >> 3) in (2, 3): | |||
print 'non I frame found: %d' % \ | |||
((ord(pes.data[i[0] + 5]) & 0x38) >> 3) | |||
print('non I frame found: %d' % \ | |||
((ord(pes.data[i[0] + 5]) & 0x38) >> 3)) | |||
if __name__ == '__main__': | |||
if True: | |||
@@ -1984,7 +1979,7 @@ if __name__ == '__main__': | |||
if False: | |||
ps = UnRead(sys.argv[1]) | |||
while ps: | |||
print `Pack(ps)` | |||
print(repr(Pack(ps))) | |||
sys.exit() | |||
s = TSPStream(open(sys.argv[1])) | |||
@@ -2007,7 +2002,7 @@ if __name__ == '__main__': | |||
0x1ffb: TSPSIPHandler({ 0xc8: tvct }), | |||
} | |||
first = last = None | |||
for j in itertools.imap(TSPacket, s): | |||
for j in map(TSPacket, s): | |||
count += 1 | |||
if j.pid == 8191 or (j.pid != 0 and j.pid != 48): | |||
skipped += 1 | |||
@@ -2019,24 +2014,24 @@ if __name__ == '__main__': | |||
pidhandlers[j.pid](j) | |||
except KeyError: | |||
pass | |||
except ValueError, x: | |||
print 'VE:', x | |||
except ValueError as x: | |||
print('VE:', x) | |||
#if pidhandlers[0x1ffb][0xc8]: | |||
# print repr(pidhandlers[0x1ffb][0xc8]) | |||
# We should probably cache which ones we've added, and remove | |||
# Ones that aren't there. Or do a clean_up callback. | |||
for k in pidhandlers[0][0].itervalues(): | |||
if pmts.has_key(k): | |||
for k in pidhandlers[0][0].values(): | |||
if k in pmts: | |||
continue | |||
pmts[k] = PMT() | |||
pidhandlers[k] = TSPSIPHandler({ 0x02: pmts[k] }) | |||
for k in itertools.ifilter(lambda x: x.es, pmts.itervalues()): | |||
for k in filter(lambda x: x.es, iter(pmts.values())): | |||
#print repr(k) | |||
for l in k.es: | |||
if pesstreams.has_key(l[1]): | |||
if l[1] in pesstreams: | |||
continue | |||
print repr(l) | |||
print(repr(l)) | |||
pesstreams[l[1]] = TSPESHandler(lambda x, y = | |||
l[1]: justprint(y, x)) | |||
pidhandlers[l[1]] = pesstreams[l[1]] | |||
@@ -2053,8 +2048,7 @@ if __name__ == '__main__': | |||
pids[j.pid] += 1 | |||
except KeyError: | |||
pids[j.pid] = 1 | |||
p = pids.items() | |||
p.sort() | |||
print p | |||
print 'skipped:', skipped | |||
print 'total:', count | |||
p = sorted(list(pids.items())) | |||
print(p) | |||
print('skipped:', skipped) | |||
print('total:', count) |
@@ -32,7 +32,6 @@ sys.path.append('/Users/jgurney/p4/bktrau/info') | |||
import itertools | |||
import mpegts | |||
import sets | |||
import struct | |||
import sys | |||
@@ -9,9 +9,9 @@ tsselpypath = 'mpegts/tssel.py' | |||
default_audio_lang = 'eng' | |||
import array | |||
import io | |||
import itertools | |||
import os | |||
import sets | |||
import struct | |||
import sys | |||
@@ -29,10 +29,9 @@ from twisted.spread import pb | |||
from twisted.internet import abstract, process, protocol, reactor | |||
from twisted.web import error, http, resource, server | |||
class _LimitedFile(file): | |||
class _LimitedFile(io.FileIO): | |||
def __init__(self, *args, **kwargs): | |||
self.__size = kwargs['size'] | |||
del kwargs['size'] | |||
self.__size = kwargs.pop('size') | |||
file.__init__(self, *args, **kwargs) | |||
def remain(self): | |||
@@ -67,7 +66,7 @@ class MPEGTSTransfer(pb.Viewable): | |||
return | |||
# get data and write to request. | |||
try: | |||
data = self.iter.next() | |||
data = next(self.iter) | |||
if data: | |||
# this .write will spin the reactor, calling | |||
# .doWrite and then .resumeProducing again, so | |||
@@ -117,9 +116,9 @@ class DynamTSTransfer(pb.Viewable): | |||
data = self.fp.read(min(abstract.FileDescriptor.bufferSize, | |||
self.size - self.written) // 188 * 188) | |||
dataarray = array.array('B', data) | |||
for i in xrange(0, len(data), 188): | |||
for i in range(0, len(data), 188): | |||
if data[i] != 'G': | |||
print 'bad sync' | |||
print('bad sync') | |||
continue | |||
frst = dataarray[i + 1] | |||
pid = (frst & 0x1f) << 8 | dataarray[i + 2] | |||
@@ -141,7 +140,7 @@ class DynamTSTransfer(pb.Viewable): | |||
# Remaining fields before array | |||
startpmt += 5 | |||
arraysize -= 5 | |||
for startpmt in xrange(startpmt, | |||
for startpmt in range(startpmt, | |||
min(i + 188 - 3, startpmt + arraysize), 4): | |||
prognum, ppid = struct.unpack('>2H', | |||
data[startpmt:startpmt + 4]) | |||
@@ -149,7 +148,7 @@ class DynamTSTransfer(pb.Viewable): | |||
if ppid == self.pmt: | |||
break | |||
else: | |||
raise KeyError, 'unable to find pmt(%d) in pkt: %s' % (pmt, `data[i:i + 188]`) | |||
raise KeyError('unable to find pmt(%d) in pkt: %s' % (pmt, repr(data[i:i + 188]))) | |||
self.pats = itertools.cycle(tssel.genpats( | |||
self.pmt, prognum)) | |||
@@ -157,14 +156,14 @@ class DynamTSTransfer(pb.Viewable): | |||
if pid == 0 and self.didpat: | |||
assert data[i + 4] =='\x00' and \ | |||
data[i + 5] == '\x00', 'error: %s' % `data[i:i + 10]` | |||
data[i + 5] == '\x00', 'error: %s' % repr(data[i:i + 10]) | |||
repcnt += 1 | |||
pn = self.pats.next() | |||
pn = next(self.pats) | |||
data = data[:i] + pn + data[i + | |||
188:] | |||
if repcnt > 1: | |||
print 'repcnt:', repcnt, 'len(data):', len(data) | |||
print('repcnt:', repcnt, 'len(data):', len(data)) | |||
if data: | |||
self.written += len(data) | |||
@@ -195,7 +194,7 @@ class DynamTSTransfer(pb.Viewable): | |||
try: | |||
self.fp = open(path) | |||
except IOError, e: | |||
except IOError as e: | |||
import errno | |||
if e[0] == errno.EACCESS: | |||
return error.ForbiddenResource().render(request) | |||
@@ -6,11 +6,15 @@ | |||
from twisted.internet import reactor | |||
from twisted.application import service | |||
from twisted.python import log, usage | |||
import ConfigParser | |||
import configparser | |||
import pymeds | |||
import os.path | |||
import sys | |||
#fix for wstools | |||
import collections | |||
collections.MutableMapping = collections.abc.MutableMapping | |||
defconfigfile = 'pymeds.ini' | |||
class ConfigFile(pymeds.Options): | |||
optParameters = [ [ 'config', 'c', defconfigfile, | |||
@@ -21,10 +25,10 @@ if __name__ == '__main__': | |||
try: | |||
config.checkpath = False | |||
config.parseOptions() | |||
print `config` | |||
print(repr(config)) | |||
if os.path.exists(config['config']): | |||
print 'foo' | |||
scp = ConfigParser.SafeConfigParser() | |||
print('foo') | |||
scp = configparser.SafeConfigParser() | |||
scp.read(config['config']) | |||
config.update(scp.items('pymeds')) | |||
@@ -32,12 +36,12 @@ if __name__ == '__main__': | |||
config.checkpath = True | |||
config.postOptions() | |||
elif config['config'] != defconfigfile: | |||
print 'bar' | |||
print('bar') | |||
raise usage.UsageError( | |||
'config file %s does not exist' % config['config']) | |||
except usage.UsageError, errortext: | |||
print '%s: %s' % (sys.argv[0], errortext) | |||
print '%s: Try --help for usage details.' % sys.argv[0] | |||
except usage.UsageError as errortext: | |||
print('%s: %s' % (sys.argv[0], errortext)) | |||
print('%s: Try --help for usage details.' % sys.argv[0]) | |||
sys.exit(1) | |||
log.startLogging(sys.stdout) | |||
@@ -13,15 +13,15 @@ __version__ = '$Change: 1740 $' | |||
# stage, where we simulate a namespace to either be thrown away when the | |||
# time comes, or merge into the correct one) | |||
import debug # my debugging module | |||
debug.doDebugging(True) # open up debugging port | |||
debug.doDebugging(False) # open up debugging port | |||
# Modules to import, maybe config file or something? | |||
def tryloadmodule(mod): | |||
try: | |||
return __import__(mod) | |||
except ImportError: | |||
#import traceback | |||
#traceback.print_exc() | |||
import traceback | |||
traceback.print_exc() | |||
pass | |||
# ZipStorage w/ tar support should be last as it will gobble up empty files. | |||
@@ -50,7 +50,7 @@ checkmodules = [ x for x in modmap if modmap[x] is None ] | |||
if checkmodules: | |||
checkmodules.sort() | |||
print 'The following modules were not loaded:', ', '.join(checkmodules) | |||
print('The following modules were not loaded:', ', '.join(checkmodules)) | |||
from FSStorage import FSDirectory | |||
import os | |||
@@ -58,12 +58,12 @@ import os.path | |||
import random | |||
import socket | |||
import string | |||
import urlparse | |||
import urllib.parse | |||
from twisted.application import internet, service | |||
from twisted.python import usage | |||
def generateuuid(): | |||
return ''.join([ 'uuid:'] + map(lambda x: random.choice(string.letters), xrange(20))) | |||
return ''.join([ 'uuid:'] + [random.choice(string.ascii_letters) for x in range(20)]) | |||
class Options(usage.Options): | |||
checkpath = True | |||
@@ -75,14 +75,14 @@ class Options(usage.Options): | |||
def postOptions(self): | |||
p = self['path'] | |||
if self.checkpath and not os.path.isdir(p): | |||
raise usage.UsageError, 'path %s does not exist' % `p` | |||
raise usage.UsageError('path %s does not exist' % repr(p)) | |||
def parseArgs(self, *args): | |||
# XXX - twisted doesn't let you provide a message on what | |||
# arguments are required, so we will do our own work in here. | |||
if len(args) not in (1, 2): | |||
raise usage.UsageError, 'Arguments: addr [ port ]' | |||
raise usage.UsageError('Arguments: addr [ port ]') | |||
self['addr'] = args[0] | |||
if len(args) == 1: | |||
@@ -154,8 +154,8 @@ def makeService(config): | |||
'uuid': uuid, | |||
'urlbase': urlbase, | |||
} | |||
d = file('root-device.xml').read() % r | |||
static.Data.__init__(self, d, 'text/xml') | |||
d = open('root-device.xml').read() % r | |||
static.Data.__init__(self, bytes(d, 'ascii'), 'text/xml') | |||
root = WebServer() | |||
debug.insertnamespace('root', root) | |||
@@ -163,14 +163,14 @@ def makeService(config): | |||
# This sets up the root to be the media dir so we don't have to | |||
# enumerate the directory. | |||
cds = ContentDirectoryServer(config['title'], klass=FSDirectory, | |||
path=config['path'], urlbase=urlparse.urljoin(urlbase, 'content'), | |||
path=config['path'], urlbase=urllib.parse.urljoin(urlbase, 'content'), | |||
webbase=content) | |||
debug.insertnamespace('cds', cds) | |||
root.putChild('ContentDirectory', cds) | |||
root.putChild(b'ContentDirectory', cds) | |||
cds = cds.control | |||
root.putChild('ConnectionManager', ConnectionManagerServer()) | |||
root.putChild('root-device.xml', RootDevice()) | |||
root.putChild('content', content) | |||
root.putChild(b'ConnectionManager', ConnectionManagerServer()) | |||
root.putChild(b'root-device.xml', RootDevice()) | |||
root.putChild(b'content', content) | |||
fixupmimetypes() | |||
@@ -186,7 +186,7 @@ def makeService(config): | |||
def startService(self): | |||
service.MultiService.startService(self) | |||
rdxml = urlparse.urljoin(urlbase, 'root-device.xml') | |||
rdxml = urllib.parse.urljoin(urlbase, 'root-device.xml') | |||
s.register('%s::upnp:rootdevice' % uuid, | |||
'upnp:rootdevice', rdxml) | |||
@@ -13,8 +13,8 @@ import time | |||
from twisted.internet import reactor | |||
from twisted.python import log | |||
import twisted.web | |||
import urlparse | |||
import urllib2 | |||
import urllib.parse | |||
import urllib.request, urllib.error, urllib.parse | |||
def getPage(url, contextFactory=None, *args, **kwargs): | |||
"""Download a web page as a string. | |||
@@ -47,10 +47,10 @@ class PYVRShow(VideoItem): | |||
VideoItem.__init__(self, *args, **kwargs) | |||
url = self.info['link'] | |||
sc = urlparse.urlparse(url)[0] | |||
sc = urllib.parse.urlparse(url)[0] | |||
if not sc: | |||
# need to combine w/ base url | |||
url = urlparse.urljoin(baseurl, url) | |||
url = urllib.parse.urljoin(baseurl, url) | |||
self.res = Resource(url, | |||
'http-get:*:%s:*' % self.info['mimetype']) | |||
self.res.duration = self.info['duration'] | |||
@@ -126,7 +126,7 @@ class PYVRShows(Container): | |||
i = 1 | |||
while True: | |||
title = '%s Copy %d' % (ep['subtitle'], i) | |||
if not eps.has_key(title): | |||
if title not in eps: | |||
return title | |||
i += 1 | |||
@@ -135,8 +135,8 @@ class PYVRShows(Container): | |||
ret = {} | |||
for pos, i in enumerate(eps): | |||
title = i['subtitle'] | |||
if ret.has_key(title): | |||
print 'WARNING: dup:', `i`, `ret[title]` | |||
if title in ret: | |||
print('WARNING: dup:', repr(i), repr(ret[title])) | |||
title = PYVRShows.getunique(ret, i) | |||
i['pos'] = pos | |||
ret[title] = i | |||
@@ -184,9 +184,9 @@ class PYVR(FSObject, Container): | |||
def runCheck(self): | |||
while True: | |||
try: | |||
self.page = urllib2.urlopen(self.url) | |||
self.page = urllib.request.urlopen(self.url) | |||
break | |||
except urllib2.HTTPError: | |||
except urllib.error.HTTPError: | |||
time.sleep(.1) | |||
#self.page = getPage(self.url, method='HEAD') | |||
#self.page.deferred.addErrback(self.errCheck).addCallback( | |||
@@ -195,7 +195,7 @@ class PYVR(FSObject, Container): | |||
return self.doCheck(self.page) | |||
def errCheck(self, x): | |||
print 'errCheck:', `x` | |||
print('errCheck:', repr(x)) | |||
self.runCheck() | |||
def doCheck(self, x): | |||
@@ -225,14 +225,14 @@ class PYVR(FSObject, Container): | |||
#self.pend = None | |||
self.newobjs = recxmltoobj(page.read()) | |||
print 'pp:', `self.newobjs` | |||
print('pp:', repr(self.newobjs)) | |||
self.doUpdate() | |||
def genChildren(self): | |||
return self.newobjs.keys() | |||
return list(self.newobjs.keys()) | |||
def createObject(self, i, arg=None): | |||
print 'co:', `i`, `arg` | |||
print('co:', repr(i), repr(arg)) | |||
return PYVRShows, i, (), { 'show': i, 'pyvr': self } | |||
def doUpdate(self): | |||
@@ -0,0 +1,3 @@ | |||
twisted | |||
-e git+https://www.funkthat.com/gitea/jmg/SOAPpy@main#egg=SOAPpy-py3 | |||
-e git+https://www.funkthat.com/gitea/jmg/wstools-py3@main#egg=wstools-py3 |
@@ -21,16 +21,16 @@ | |||
<service> | |||
<serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType> | |||
<serviceId>urn:upnp-org:serviceId:urn:schemas-upnp-org:service:ConnectionManager</serviceId> | |||
<SCPDURL>ConnectionManager/scpd.xml</SCPDURL> | |||
<controlURL>ConnectionManager/control</controlURL> | |||
<eventSubURL>ConnectionManager/event</eventSubURL> | |||
<SCPDURL>/ConnectionManager/scpd.xml</SCPDURL> | |||
<controlURL>/ConnectionManager/control</controlURL> | |||
<eventSubURL>/ConnectionManager/event</eventSubURL> | |||
</service> | |||
<service> | |||
<serviceType>urn:schemas-upnp-org:service:ContentDirectory:1</serviceType> | |||
<serviceId>urn:upnp-org:serviceId:urn:schemas-upnp-org:service:ContenDirectory</serviceId> | |||
<SCPDURL>ContentDirectory/scpd.xml</SCPDURL> | |||
<controlURL>ContentDirectory/control</controlURL> | |||
<eventSubURL>ContentDirectory/event</eventSubURL> | |||
<SCPDURL>/ContentDirectory/scpd.xml</SCPDURL> | |||
<controlURL>/ContentDirectory/control</controlURL> | |||
<eventSubURL>/ContentDirectory/event</eventSubURL> | |||
</service> | |||
</serviceList> | |||
<deviceList/> | |||
@@ -57,7 +57,7 @@ class LimitedAudioProducer(object): | |||
return r | |||
def shutdown(self): | |||
print 'lap: shutdown', `self.consumer` | |||
print('lap: shutdown', repr(self.consumer)) | |||
# XXX - I still get writes after I've asked my producer to stop | |||
self.write = lambda x: None | |||
self.producer.stopProducing() | |||
@@ -74,19 +74,19 @@ class LimitedAudioProducer(object): | |||
return self.producer.resumeProducing() | |||
def stopProducing(self): | |||
print 'lap: sp' | |||
print('lap: sp') | |||
self.shutdown() | |||
# IConsumer | |||
def registerProducer(self, producer, streaming): | |||
print 'lap: regp' | |||
print('lap: regp') | |||
self.producer = producer | |||
self.streamingProducer = streaming | |||
self.consumer.registerProducer(self, streaming) | |||
def unregisterProducer(): | |||
print 'lap: unregp' | |||
print('lap: unregp') | |||
self.shutdown() | |||
def write(self, data): | |||
@@ -122,7 +122,7 @@ class ChangerTrack(resource.Resource): | |||
return self._res.getmimetype() | |||
def render(self, request): | |||
print 'CTrender:', `request.postpath`, `request.method`, `request` | |||
print('CTrender:', repr(request.postpath), repr(request.method), repr(request)) | |||
self.setlength(request) | |||
if request.method == 'HEAD': | |||
@@ -156,7 +156,7 @@ class ChangerTrack(resource.Resource): | |||
'content-length', [ str(r) ]) | |||
def docleanup(self, nf, request): | |||
print 'docleanup' | |||
print('docleanup') | |||
nf.addBoth(self.dostop) | |||
nf.addBoth(lambda x: self.dounlock(request)) | |||
@@ -168,19 +168,19 @@ class ChangerTrack(resource.Resource): | |||
return None | |||
def dostop(self, arg): | |||
print 'dostop' | |||
print('dostop') | |||
d = self._obj.stop() | |||
# Make sure we have stopped before we continue | |||
d.addBoth(lambda x: arg) | |||
return d | |||
def logerr(self, exc, *args): | |||
print 'logerr:', `args` | |||
print('logerr:', repr(args)) | |||
exc.printTraceback() | |||
#exc.printDetailedTraceback() | |||
def failed(self, exc, request): | |||
print 'in this failed case', self._obj.haslock(request), `request` | |||
print('in this failed case', self._obj.haslock(request), repr(request)) | |||
if self._obj.haslock(request): | |||
self.dounlock(request) | |||
# XXX - look at queue and decide | |||
@@ -192,7 +192,7 @@ class ChangerTrack(resource.Resource): | |||
return exc | |||
def printarg(self, args): | |||
print 'pa:', `self`, `args` | |||
print('pa:', repr(self), repr(args)) | |||
def unregisterProducer(self): | |||
resource.Resource.unregisterProducer(self) | |||
@@ -298,15 +298,15 @@ class SLinkEChangerDisc(MusicAlbum): | |||
# ContentDirectory calls this | |||
def checkUpdate(self): | |||
print 'cU' | |||
print('cU') | |||
curid = self.getID() | |||
if self._lastid != curid: | |||
print 'dU' | |||
print('dU') | |||
self.doUpdate() | |||
self._lastid = curid | |||
def genChildren(self): | |||
return dict(('%02d' % i, i) for i in xrange(1, self.getID()[1] + 1)) | |||
return dict(('%02d' % i, i) for i in range(1, self.getID()[1] + 1)) | |||
def createObject(self, i, arg): | |||
return SLinkEChangerDiscTrack, i, (), { 'discobj': self, 'track': arg } | |||
@@ -335,7 +335,7 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
config['audiodefault']) | |||
def aftershutdown(self): | |||
print 'in SLinkEChanger after shutdown' | |||
print('in SLinkEChanger after shutdown') | |||
self._s.close() | |||
self._s = None | |||
@@ -350,7 +350,7 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
self._poweroff.cancel() | |||
self._poweroff = None | |||
self._lock = obj | |||
print 'tl: locked:', `self._lock` | |||
print('tl: locked:', repr(self._lock)) | |||
return defer.succeed(True) | |||
d = defer.Deferred() | |||
@@ -372,24 +372,24 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
return False | |||
def unlock(self, obj): | |||
print 'unlock:', `obj` | |||
print('unlock:', repr(obj)) | |||
if self._lock is None: | |||
print 'ul: not locked' | |||
print('ul: not locked') | |||
raise RuntimeError('unlocked when not locked') | |||
if obj is not self._lock: | |||
print 'ul: wrong obj' | |||
raise ValueError('unlocking when not locked by: %s, was locked by: %s' % (`obj`, self._lock)) | |||
print('ul: wrong obj') | |||
raise ValueError('unlocking when not locked by: %s, was locked by: %s' % (repr(obj), self._lock)) | |||
if not self._pendinglocks: | |||
print 'really unlocked' | |||
print('really unlocked') | |||
self._lock = None | |||
self._poweroff = reactor.callLater(300, self.turnoff) | |||
return | |||
pobj = self._pendinglocks.pop(0) | |||
self._lock = pobj[1] | |||
print 'passing lock:', `self._lock` | |||
print('passing lock:', repr(self._lock)) | |||
pobj[2].cancel() | |||
pobj[0].callback(True) | |||
@@ -402,7 +402,7 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
a = defer.waitForDeferred(self.checkids()) | |||
yield a | |||
a.getResult() | |||
print 'powering cd changer off' | |||
print('powering cd changer off') | |||
# checkids may have rescheduled us. If we don't cancel it, | |||
# we'd wake up every five minutes just to turn off again. | |||
@@ -415,13 +415,12 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
@defer.deferredGenerator | |||
def checkids(self): | |||
print 'starting checkids' | |||
print('starting checkids') | |||
a = defer.waitForDeferred(self.transport.poweron()) | |||
yield a | |||
print 'power should be on:', `a.getResult()` | |||
discs = list(self.transport.discs()) | |||
discs.sort() | |||
print discs | |||
print('power should be on:', repr(a.getResult())) | |||
discs = sorted(self.transport.discs()) | |||
print(discs) | |||
for i in self.transport: | |||
discnum = i | |||
i = str(i) | |||
@@ -433,7 +432,7 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
except KeyError: | |||
pass | |||
print 'missing:', `i` | |||
print('missing:', repr(i)) | |||
# No ID, fetch it. | |||
a = defer.waitForDeferred(self.trylock(5, self)) | |||
@@ -447,12 +446,12 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
a = defer.waitForDeferred(threads.deferToThread(CDDB.query, cddbid)) | |||
yield a | |||
queryres = a.getResult() | |||
print 'res:', `i`, `queryres` | |||
print('res:', repr(i), repr(queryres)) | |||
self._s[i] = { 'query': queryres, | |||
'cddbid': cddbid, } | |||
self._changed = True | |||
except slinke.NoDisc: | |||
print 'Disc not present: %d' % discnum | |||
print('Disc not present: %d' % discnum) | |||
continue | |||
finally: | |||
self.unlock(self) | |||
@@ -488,7 +487,7 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
# 210 multiple matches | |||
return q[1][0] | |||
else: | |||
raise ValueError('what to do? %s' % `self._s[disc]`) | |||
raise ValueError('what to do? %s' % repr(self._s[disc])) | |||
def getDiscTitle(self, disc, wait=False): | |||
m = self.getMatch(disc, wait) | |||
@@ -502,17 +501,17 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
t = t.decode('iso8859-1') | |||
if t.count('/') > 1: | |||
print 'tcount:', `t` | |||
print('tcount:', repr(t)) | |||
try: | |||
return t.split('/', 1)[1] | |||
except IndexError: | |||
print 'ie:', `t` | |||
print('ie:', repr(t)) | |||
return t | |||
# CDPlayerProtocol interface | |||
def connectionMade(self): | |||
super(SLinkEChanger, self).connectionMade() | |||
print 'attached to cdplayer' | |||
print('attached to cdplayer') | |||
self._changed = True | |||
# Make sure we start out off, or if we are missing CDDB id's, | |||
@@ -520,7 +519,7 @@ class SLinkEChanger(StorageSystem, slinke.CDPlayerProtocol): | |||
self.turnoff() | |||
def stateChange(self): | |||
print 'sC' | |||
print('sC') | |||
# ContentDirectory calls this | |||
def checkUpdate(self): | |||
@@ -82,18 +82,16 @@ def build_soap_call(method, arguments, is_response=False, | |||
# append the arguments | |||
if isinstance(arguments,dict): | |||
type_map = {str: 'xsd:string', | |||
unicode: 'xsd:string', | |||
bytes: 'xsd:string', | |||
int: 'xsd:int', | |||
long: 'xsd:int', | |||
float: 'xsd:float', | |||
bool: 'xsd:boolean'} | |||
for arg_name, arg_val in arguments.iteritems(): | |||
for arg_name, arg_val in arguments.items(): | |||
arg_type = type_map[type(arg_val)] | |||
if arg_type == 'xsd:string' and type(arg_val) == unicode: | |||
arg_val = arg_val.encode('utf-8') | |||
if arg_type == 'xsd:int' or arg_type == 'xsd:float': | |||
arg_val = str(arg_val) | |||
if isinstance(arg_val, bytes): | |||
arg_val = arg_val.decode('utf-8') | |||
arg_val = str(arg_val) | |||
if arg_type == 'xsd:boolean': | |||
arg_val = arg_val.lower() | |||
@@ -109,4 +107,4 @@ def build_soap_call(method, arguments, is_response=False, | |||
preamble = """<?xml version="1.0" encoding="utf-8"?>""" | |||
return preamble + ET.tostring(envelope,'utf-8') | |||
return bytes(preamble + ET.tostring(envelope, 'unicode'), 'ascii') |