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 *

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



Loading…
Cancel
Save