From 1175fd948c231832c701f7d05bfef38210611aee Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Sun, 17 Jan 2010 23:46:44 -0800 Subject: [PATCH] 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] --- flac.py | 72 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/flac.py b/flac.py index b34e9e7..be57371 100644 --- a/flac.py +++ b/flac.py @@ -5,6 +5,8 @@ import UserDict from ctypes import * +__all__ = [ 'FLACDec' ] + # Find out if we need to endian swap the buffer t = array.array('H', '\x00\x01') if t[0] == 1: @@ -407,28 +409,74 @@ def clientdatawrapper(fun): 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 to support flac decoding.''' + channels = property(lambda x: x._channels) samplerate = property(lambda x: x._samplerate) bitspersample = property(lambda x: x._bitspersample) totalsamples = property(lambda x: x._totalsamples) bytespersample = property(lambda x: x._bytespersample) + vorbis = property(lambda x: x._vorbis) + cuesheet = property(lambda x: x._cuesheet) def __len__(self): return self._total_samps def __init__(self, file): + '''Pass in the file name. We currently do not support file objects.''' + self.flacdec = None self._lasterror = None # We need to keep references to the callback functions # around so they won't be garbage collected. self.write_wrap = FLAC__StreamDecoderWriteCallback( - clientdatawrapper(self.cb_write)) + clientdatawrapper(self._cb_write)) self.metadata_wrap = FLAC__StreamDecoderMetadataCallback( - clientdatawrapper(self.cb_metadata)) + clientdatawrapper(self._cb_metadata)) self.error_wrap = FLAC__StreamDecoderErrorCallback( - clientdatawrapper(self.cb_error)) + clientdatawrapper(self._cb_error)) self.flacdec = flaclib.FLAC__stream_decoder_new() if self.flacdec == 0: @@ -448,8 +496,8 @@ class FLACDec(object): raise ValueError( FLAC__StreamDecoderInitStatusString[status]) - self.vorbis = None - self.cuesheet = None + self._vorbis = None + self._cuesheet = None flaclib.FLAC__stream_decoder_process_until_end_of_metadata( self.flacdec) @@ -463,6 +511,8 @@ class FLACDec(object): self.vorbis = '', VorbisComments() def close(self): + '''Finish decoding and close all the objects.''' + if self.flacdec is None: return @@ -481,7 +531,7 @@ class FLACDec(object): pass #raise ValueError('invalid md5') - def cb_write(self, frame_p, buffer_pp): + def _cb_write(self, frame_p, buffer_pp): frame = frame_p[0] #print 'write:', `frame` #for i in xrange(frame.header.channels): @@ -512,7 +562,7 @@ class FLACDec(object): return 0 - def cb_metadata(self, metadata_p): + def _cb_metadata(self, metadata_p): md = metadata_p[0] #print 'metadata:', `md` if md.type == FLAC__METADATA_TYPE_STREAMINFO: @@ -525,17 +575,17 @@ class FLACDec(object): si.bits_per_sample / 8 #print `si` 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 'v:', `self.vorbis` 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 'c:', `self.cuesheet` else: print 'unknown metatype:', md.type - def cb_error(self, errstatus): + def _cb_error(self, errstatus): #print 'error:', `errstatus` self._lasterror = errstatus @@ -546,6 +596,8 @@ class FLACDec(object): state = property(getstate) def goto(self, pos): + '''Go to sample possition.''' + if self.flacdec is None: raise ValueError('closed')