5 Commits

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.. 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... 1 year ago
31 changed files with 502 additions and 576 deletions
Split View
  1. +5
    -0
      .gitignore
  2. +2
    -2
      Clip.py
  3. +7
    -7
      ConnectionManager.py
  4. +23
    -23
      ContentDirectory.py
  5. +26
    -22
      DIDLLite.py
  6. +18
    -15
      FSStorage.py
  7. +4
    -3
      FileDIDL.py
  8. +30
    -21
      README.md
  9. +24
    -27
      SSDP.py
  10. +0
    -14
      ZipStorage.py
  11. +12
    -12
      audio.py
  12. +13
    -13
      audioraw.py
  13. +5
    -5
      cdrtoc.py
  14. +3
    -3
      debug.py
  15. +0
    -1
      dvd.py
  16. +10
    -10
      et.py
  17. +1
    -1
      item.py
  18. +0
    -12
      iterrarfile.py
  19. +0
    -37
      itertarfile.py
  20. +0
    -25
      iterzipfile.py
  21. +2
    -2
      mpegts/atschuff.py
  22. +215
    -221
      mpegts/mpegts.py
  23. +0
    -1
      mpegts/tssel.py
  24. +12
    -13
      mpegtsmod.py
  25. +12
    -8
      pymediaserv
  26. +16
    -16
      pymeds.py
  27. +13
    -13
      pyvr.py
  28. +3
    -0
      requirements.txt
  29. +6
    -6
      root-device.xml
  30. +34
    -35
      slinkemod.py
  31. +6
    -8
      soap_lite.py

+ 5
- 0
.gitignore View File

@@ -0,0 +1,5 @@
.DS_Store
__pycache__

# my venv
p

+ 2
- 2
Clip.py View File

@@ -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:


+ 7
- 7
ConnectionManager.py View File

@@ -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())

+ 23
- 23
ContentDirectory.py View File

@@ -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)

+ 26
- 22
DIDLLite.py View File

@@ -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))

+ 18
- 15
FSStorage.py View File

@@ -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


+ 4
- 3
FileDIDL.py View File

@@ -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



README → README.md View File

@@ -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

+ 24
- 27
SSDP.py View File

@@ -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'])


+ 0
- 14
ZipStorage.py View File

@@ -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


+ 12
- 12
audio.py View File

@@ -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))


+ 13
- 13
audioraw.py View File

@@ -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


+ 5
- 5
cdrtoc.py View File

@@ -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()))

+ 3
- 3
debug.py View File

@@ -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.')

+ 0
- 1
dvd.py View File

@@ -9,7 +9,6 @@ default_audio_lang = 'en'

import itertools
import os
import sets

import sys
sys.path.append('mpegts')


+ 10
- 10
et.py View File

@@ -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())

+ 1
- 1
item.py View File

@@ -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])


+ 0
- 12
iterrarfile.py View File

@@ -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)

+ 0
- 37
itertarfile.py View File

@@ -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

+ 0
- 25
iterzipfile.py View File

@@ -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

+ 2
- 2
mpegts/atschuff.py View File

@@ -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

+ 215
- 221
mpegts/mpegts.py View File

@@ -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)

+ 0
- 1
mpegts/tssel.py View File

@@ -32,7 +32,6 @@ sys.path.append('/Users/jgurney/p4/bktrau/info')

import itertools
import mpegts
import sets
import struct
import sys



+ 12
- 13
mpegtsmod.py View File

@@ -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)


+ 12
- 8
pymediaserv View File

@@ -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)


+ 16
- 16
pymeds.py View File

@@ -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
- 13
pyvr.py View File

@@ -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):


+ 3
- 0
requirements.txt View File

@@ -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

+ 6
- 6
root-device.xml View File

@@ -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/>


+ 34
- 35
slinkemod.py View File

@@ -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):


+ 6
- 8
soap_lite.py View File

@@ -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')

Loading…
Cancel
Save