Browse Source

add routine to calculate cddbid... This only works on audio only

discs, so it shouldn't be used yet...

mark some items private by using _...

document some routines..

[git-p4: depot-paths = "//depot/": change = 1430]
main
John-Mark Gurney 15 years ago
parent
commit
1175fd948c
1 changed files with 62 additions and 10 deletions
  1. +62
    -10
      flac.py

+ 62
- 10
flac.py View File

@@ -5,6 +5,8 @@ import UserDict


from ctypes import * from ctypes import *


__all__ = [ 'FLACDec' ]

# Find out if we need to endian swap the buffer # Find out if we need to endian swap the buffer
t = array.array('H', '\x00\x01') t = array.array('H', '\x00\x01')
if t[0] == 1: if t[0] == 1:
@@ -407,28 +409,74 @@ def clientdatawrapper(fun):


return newfun return newfun


def getindex(ar, idx):
for i in ar:
if idx == i['number']:
return i

raise ValueError('index %d not present: %s' % (idx, `ar`))

def _checksum(n):
ret = 0

while n > 0:
n, m = divmod(n, 10)
ret += m

return ret

def _cuetotrackinfo(cuesheet):
'''XXX - do not use. This will not work because the cuesheet does
not include data tracks!'''
if not cuesheet['is_cd']:
raise ValueError('cuesheet isn\'t for a cd')

tracks = []
ta = cuesheet['tracks_array']
tot = 0
cksum = 0
for i in xrange(1, len(ta)):
offstart = ta[i - 1]['offset']
offend = ta[i]['offset']
secs = offend / 44100 - offstart / 44100
#print ta[i - 1]['number'], secs, offstart / (2352 / 4), (offend - offstart) / (2352 / 4)
tot += secs
cksum += _checksum(offstart / 44100 + 2)

#print tot
tracks.append(divmod(tot, 60))

#print `tracks`
return (long(cksum) % 0xff) << 24 | tot << 8 | (len(ta) - 1), 0

class FLACDec(object): class FLACDec(object):
'''Class to support flac decoding.'''

channels = property(lambda x: x._channels) channels = property(lambda x: x._channels)
samplerate = property(lambda x: x._samplerate) samplerate = property(lambda x: x._samplerate)
bitspersample = property(lambda x: x._bitspersample) bitspersample = property(lambda x: x._bitspersample)
totalsamples = property(lambda x: x._totalsamples) totalsamples = property(lambda x: x._totalsamples)
bytespersample = property(lambda x: x._bytespersample) bytespersample = property(lambda x: x._bytespersample)
vorbis = property(lambda x: x._vorbis)
cuesheet = property(lambda x: x._cuesheet)


def __len__(self): def __len__(self):
return self._total_samps return self._total_samps


def __init__(self, file): def __init__(self, file):
'''Pass in the file name. We currently do not support file objects.'''

self.flacdec = None self.flacdec = None
self._lasterror = None self._lasterror = None


# We need to keep references to the callback functions # We need to keep references to the callback functions
# around so they won't be garbage collected. # around so they won't be garbage collected.
self.write_wrap = FLAC__StreamDecoderWriteCallback( self.write_wrap = FLAC__StreamDecoderWriteCallback(
clientdatawrapper(self.cb_write))
clientdatawrapper(self._cb_write))
self.metadata_wrap = FLAC__StreamDecoderMetadataCallback( self.metadata_wrap = FLAC__StreamDecoderMetadataCallback(
clientdatawrapper(self.cb_metadata))
clientdatawrapper(self._cb_metadata))
self.error_wrap = FLAC__StreamDecoderErrorCallback( self.error_wrap = FLAC__StreamDecoderErrorCallback(
clientdatawrapper(self.cb_error))
clientdatawrapper(self._cb_error))


self.flacdec = flaclib.FLAC__stream_decoder_new() self.flacdec = flaclib.FLAC__stream_decoder_new()
if self.flacdec == 0: if self.flacdec == 0:
@@ -448,8 +496,8 @@ class FLACDec(object):
raise ValueError( raise ValueError(
FLAC__StreamDecoderInitStatusString[status]) FLAC__StreamDecoderInitStatusString[status])


self.vorbis = None
self.cuesheet = None
self._vorbis = None
self._cuesheet = None


flaclib.FLAC__stream_decoder_process_until_end_of_metadata( flaclib.FLAC__stream_decoder_process_until_end_of_metadata(
self.flacdec) self.flacdec)
@@ -463,6 +511,8 @@ class FLACDec(object):
self.vorbis = '', VorbisComments() self.vorbis = '', VorbisComments()


def close(self): def close(self):
'''Finish decoding and close all the objects.'''

if self.flacdec is None: if self.flacdec is None:
return return


@@ -481,7 +531,7 @@ class FLACDec(object):
pass pass
#raise ValueError('invalid md5') #raise ValueError('invalid md5')


def cb_write(self, frame_p, buffer_pp):
def _cb_write(self, frame_p, buffer_pp):
frame = frame_p[0] frame = frame_p[0]
#print 'write:', `frame` #print 'write:', `frame`
#for i in xrange(frame.header.channels): #for i in xrange(frame.header.channels):
@@ -512,7 +562,7 @@ class FLACDec(object):


return 0 return 0


def cb_metadata(self, metadata_p):
def _cb_metadata(self, metadata_p):
md = metadata_p[0] md = metadata_p[0]
#print 'metadata:', `md` #print 'metadata:', `md`
if md.type == FLAC__METADATA_TYPE_STREAMINFO: if md.type == FLAC__METADATA_TYPE_STREAMINFO:
@@ -525,17 +575,17 @@ class FLACDec(object):
si.bits_per_sample / 8 si.bits_per_sample / 8
#print `si` #print `si`
elif md.type == FLAC__METADATA_TYPE_VORBIS_COMMENT: elif md.type == FLAC__METADATA_TYPE_VORBIS_COMMENT:
self.vorbis = md.data.vorbis_comment.asobj()
self._vorbis = md.data.vorbis_comment.asobj()
#print 'vc:', `md.data.vorbis_comment` #print 'vc:', `md.data.vorbis_comment`
#print 'v:', `self.vorbis` #print 'v:', `self.vorbis`
elif md.type == FLAC__METADATA_TYPE_CUESHEET: elif md.type == FLAC__METADATA_TYPE_CUESHEET:
self.cuesheet = md.data.cue_sheet.asobj()
self._cuesheet = md.data.cue_sheet.asobj()
#print 'cs:', `md.data.cue_sheet` #print 'cs:', `md.data.cue_sheet`
#print 'c:', `self.cuesheet` #print 'c:', `self.cuesheet`
else: else:
print 'unknown metatype:', md.type print 'unknown metatype:', md.type


def cb_error(self, errstatus):
def _cb_error(self, errstatus):
#print 'error:', `errstatus` #print 'error:', `errstatus`
self._lasterror = errstatus self._lasterror = errstatus


@@ -546,6 +596,8 @@ class FLACDec(object):
state = property(getstate) state = property(getstate)


def goto(self, pos): def goto(self, pos):
'''Go to sample possition.'''

if self.flacdec is None: if self.flacdec is None:
raise ValueError('closed') raise ValueError('closed')




Loading…
Cancel
Save