@@ -1,5 +1,6 @@
#!/usr/bin/env python
#!/usr/bin/env python
# Copyright 2009 John-Mark Gurney <jmg@funkthat.com>
# Copyright 2009 John-Mark Gurney <jmg@funkthat.com>
'''Audio Raw Converter'''
'''Audio Raw Converter'''
from DIDLLite import AudioItem, Album, Resource, ResourceList
from DIDLLite import AudioItem, Album, Resource, ResourceList
@@ -38,17 +39,25 @@ class DecoderProducer:
implements(IPullProducer)
implements(IPullProducer)
def __init__(self, consumer, decoder, tbytes, skipbytes):
def __init__(self, consumer, decoder, tbytes, skipbytes):
'''skipbytes should always be small. It is here in case
someone requests the middle of a sample.'''
self.decoder = decoder
self.decoder = decoder
self.consumer = consumer
self.consumer = consumer
self.tbytes = tbytes
self.tbytes = tbytes
self.skipbytes = skipbytes
self.skipbytes = skipbytes
#print 'DPregP', `self`, `self.tbytes`, `self.skipbytes`
consumer.registerProducer(self, False)
consumer.registerProducer(self, False)
self.resumeProducing()
def pauseProducing(self):
def pauseProducing(self):
print 'DPpP, doing nothing'
# XXX - bug in Twisted 8.2.0 on pipelined requests this is
# called: http://twistedmatrix.com/trac/ticket/3919
pass
def resumeProducing(self):
def resumeProducing(self):
r = self.decoder.read(8*1024)
#print 'DPrP', `self`
r = self.decoder.read(oneblk=True)
if r:
if r:
#print 'DPrP:', len(r)
#print 'DPrP:', len(r)
if self.skipbytes:
if self.skipbytes:
@@ -60,16 +69,19 @@ class DecoderProducer:
r = r[:send]
r = r[:send]
self.tbytes -= len(r)
self.tbytes -= len(r)
self.consumer.write(r)
self.consumer.write(r)
#print 'write %d bytes, remaining %d' % (len(r), self.tbytes)
if self.tbytes:
if self.tbytes:
return
return
print 'DPurP'
# print 'DPurP', `self`
self.consumer.unregisterProducer()
self.consumer.unregisterProducer()
self.consumer.finish()
def stopProducing(self):
def stopProducing(self):
print 'DPsP'
# print 'DPsP', `self`
self.decoder.close()
self.decoder.close()
self.decoder = None
self.decoder = None
self.consumer = None
class AudioResource(resource.Resource):
class AudioResource(resource.Resource):
isLeaf = True
isLeaf = True
@@ -95,6 +107,7 @@ class AudioResource(resource.Resource):
return start, end - start + 1
return start, end - start + 1
def render(self, request):
def render(self, request):
#print 'render:', `request`
decoder = self.dec(self.f)
decoder = self.dec(self.f)
request.setHeader('content-type', makemtfromdec(decoder))
request.setHeader('content-type', makemtfromdec(decoder))
bytespersample = decoder.channels * decoder.bitspersample / 8
bytespersample = decoder.channels * decoder.bitspersample / 8
@@ -105,15 +118,15 @@ class AudioResource(resource.Resource):
request.setHeader('accept-ranges', 'bytes')
request.setHeader('accept-ranges', 'bytes')
if request.requestHeaders.hasHeader('range'):
if request.requestHeaders.hasHeader('range'):
print 'range req:', `request.requestHeaders.getRawHeaders('range')`
# print 'range req:', `request.requestHeaders.getRawHeaders('range')`
start, cnt = self.calcrange(
start, cnt = self.calcrange(
request.requestHeaders.getRawHeaders('range')[0],
request.requestHeaders.getRawHeaders('range')[0],
tbytes)
tbytes)
skipbytes = start % bytespersample
skipbytes = start % bytespersample
print 'going:', start / bytespersample
# print 'going:', start / bytespersample
decoder.goto(self.start + start / bytespersample)
decoder.goto(self.start + start / bytespersample)
print 'there'
# print 'there'
request.setHeader('content-length', cnt)
request.setHeader('content-length', cnt)
request.setHeader('content-range', 'bytes %s-%s/%s' %
request.setHeader('content-range', 'bytes %s-%s/%s' %
@@ -126,7 +139,7 @@ class AudioResource(resource.Resource):
return ''
return ''
DecoderProducer(request, decoder, tbytes, skipbytes)
DecoderProducer(request, decoder, tbytes, skipbytes)
print 'producing render'
# print 'producing render', `decoder`, `tbytes`, `skipbytes`
# and make sure the connection doesn't get closed
# and make sure the connection doesn't get closed
return server.NOT_DONE_YET
return server.NOT_DONE_YET
@@ -149,10 +162,10 @@ class AudioDisc(FSObject, Album):
# XXX - exclude track 1 pre-gap?
# XXX - exclude track 1 pre-gap?
kwargs['content'] = AudioResource(self.file,
kwargs['content'] = AudioResource(self.file,
kwargs.pop('decoder'), 0, kwargs['samples'])
kwargs.pop('decoder'), 0, kwargs['samples'])
print 'doing construction'
# print 'doing construction'
Album.__init__(self, *args, **kwargs)
Album.__init__(self, *args, **kwargs)
print 'adding resource'
# print 'adding resource'
self.url = '%s/%s' % (self.cd.urlbase, self.id)
self.url = '%s/%s' % (self.cd.urlbase, self.id)
self.res = ResourceList()
self.res = ResourceList()
r = Resource(self.url, 'http-get:*:%s:*' % makeaudiomt(bitsps,
r = Resource(self.url, 'http-get:*:%s:*' % makeaudiomt(bitsps,
@@ -164,7 +177,7 @@ class AudioDisc(FSObject, Album):
r.bitsPerSample = bitsps
r.bitsPerSample = bitsps
r.nrAudioChannels = nchan
r.nrAudioChannels = nchan
self.res.append(r)
self.res.append(r)
print 'completed'
# print 'completed'
def sort(self, fun=lambda x, y: cmp(int(x.title), int(y.title))):
def sort(self, fun=lambda x, y: cmp(int(x.title), int(y.title))):
return list.sort(self, fun)
return list.sort(self, fun)
@@ -173,7 +186,7 @@ class AudioDisc(FSObject, Album):
r = [ str(x['number']) for x in
r = [ str(x['number']) for x in
self.cuesheet['tracks_array'] if x['number'] not in
self.cuesheet['tracks_array'] if x['number'] not in
(170, 255) ]
(170, 255) ]
print 'gC:', `r`
# print 'gC:', `r`
return r
return r
def findtrackidx(self, trk):
def findtrackidx(self, trk):