Browse Source

fix up path for finding the _interleave.so library... try to

find it in the current dir if there is no path for this module...

add support for reading out pictures, and use a more sane mapping
for the names...

[git-p4: depot-paths = "//depot/": change = 1667]
main
John-Mark Gurney 12 years ago
parent
commit
ffa780b8d9
1 changed files with 78 additions and 14 deletions
  1. +78
    -14
      flac.py

+ 78
- 14
flac.py View File

@@ -22,7 +22,11 @@ is_little_endian = _islittleendian()
inter = {}

try:
interleavelib = CDLL(os.path.join(os.path.dirname(__file__), '_interleave.so'))
dname = os.path.dirname(__file__)
if not dname:
dname = '.'
path = os.path.join(dname, '_interleave.so')
interleavelib = CDLL(path)
for i in (16, ):
f = getattr(interleavelib, 'interleave%d' % i)
f.restype = None
@@ -56,6 +60,9 @@ FLAC__MAX_CHANNELS = 8
FLAC__MAX_LPC_ORDER = 32
FLAC__MAX_FIXED_ORDER = 4

FLAC__byte = c_uint8
FLAC__byte_p = POINTER(FLAC__byte)

# Data
FLAC__StreamDecoderStateString = (c_char_p * 10).in_dll(flaclib,
'FLAC__StreamDecoderStateString')
@@ -63,6 +70,8 @@ FLAC__StreamDecoderInitStatusString = (c_char_p * 6).in_dll(flaclib,
'FLAC__StreamDecoderInitStatusString')
FLAC__StreamDecoderErrorStatusString = (c_char_p * 4).in_dll(flaclib,
'FLAC__StreamDecoderErrorStatusString')
FLAC__StreamMetadata_Picture_TypeString = (c_char_p * 21).in_dll(flaclib,
'FLAC__StreamMetadata_Picture_TypeString')

# Enums
FLAC__STREAM_DECODER_SEARCH_FOR_METADATA = 0
@@ -84,6 +93,33 @@ FLAC__SUBFRAME_TYPE_VERBATIM = 1
FLAC__SUBFRAME_TYPE_FIXED = 2
FLAC__SUBFRAME_TYPE_LPC = 3

FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER = 0 # < Other */
FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD = 1 # < 32x32 pixels 'file icon' (PNG only) */
FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON = 2 # < Other file icon */
FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER = 3 # < Cover (front) */
FLAC__STREAM_METADATA_PICTURE_TYPE_BACK_COVER = 4 # < Cover (back) */
FLAC__STREAM_METADATA_PICTURE_TYPE_LEAFLET_PAGE = 5 # < Leaflet page */
FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA = 6 # < Media (e.g. label side of CD) */
FLAC__STREAM_METADATA_PICTURE_TYPE_LEAD_ARTIST = 7 # < Lead artist/lead performer/soloist */
FLAC__STREAM_METADATA_PICTURE_TYPE_ARTIST = 8 # < Artist/performer */
FLAC__STREAM_METADATA_PICTURE_TYPE_CONDUCTOR = 9 # < Conductor */
FLAC__STREAM_METADATA_PICTURE_TYPE_BAND = 10 # < Band/Orchestra */
FLAC__STREAM_METADATA_PICTURE_TYPE_COMPOSER = 11 # < Composer */
FLAC__STREAM_METADATA_PICTURE_TYPE_LYRICIST = 12 # < Lyricist/text writer */
FLAC__STREAM_METADATA_PICTURE_TYPE_RECORDING_LOCATION = 13 # < Recording Location */
FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_RECORDING = 14 # < During recording */
FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_PERFORMANCE = 15 # < During performance */
FLAC__STREAM_METADATA_PICTURE_TYPE_VIDEO_SCREEN_CAPTURE = 16 # < Movie/video screen capture */
FLAC__STREAM_METADATA_PICTURE_TYPE_FISH = 17 # < A bright coloured fish */
FLAC__STREAM_METADATA_PICTURE_TYPE_ILLUSTRATION = 18 # < Illustration */
FLAC__STREAM_METADATA_PICTURE_TYPE_BAND_LOGOTYPE = 19 # < Band/artist logotype */
FLAC__STREAM_METADATA_PICTURE_TYPE_PUBLISHER_LOGOTYPE = 20 # < Publisher/Studio logotype */

pictnamemap = dict(enumerate(('other', 'icon', 'icon', 'cover', 'backcover',
'leaflet', 'media', 'lead', 'artist', 'conductor', 'band', 'composer',
'lyricist', 'location', 'recording', 'performance', 'video', 'fish',
'illustration', 'bandlogo', 'publogo')))

OrigStructure = Structure
class Structure(Structure):
def getarray(self, base):
@@ -128,7 +164,10 @@ class Structure(Structure):
def __repr__(self, fields=None):
cls = self.__class__
if fields is None:
fields = self._fields_
if hasattr(self, '_material_'):
fields = self._material_
else:
fields = self._fields_
return '<%s.%s: %s>' % (cls.__module__, cls.__name__,
', '.join([ '%s: %s' % (x[0], `getattr(self, x[0])`)
for x in fields ]))
@@ -213,9 +252,6 @@ class FLAC__StreamMetadata_VorbisComment(Structure):
VorbisComments(x.asstring() for x in
self.getarray('comments'))

def __repr__(self):
return Structure.__repr__(self, self._material_)

class FLAC__StreamMetadata_CueSheet_Index(Structure):
_fields_ = [ ('offset', c_uint64),
('number', c_ubyte),
@@ -233,9 +269,6 @@ class FLAC__StreamMetadata_CueSheet_Track(Structure):
_material_ = (('offset', ), ('number', ), ('isrc', ), ('type', ),
('pre_emphasis', ), ('indices_array', ))

def __repr__(self):
return Structure.__repr__(self, self._material_)

class FLAC__StreamMetadata_CueSheet(Structure):
_fields_ = [ ('media_catalog_number', c_char * 129), # string + nul
('lead_in', c_uint64),
@@ -246,13 +279,34 @@ class FLAC__StreamMetadata_CueSheet(Structure):
_material_ = (('media_catalog_number', ), ('lead_in', ), ('is_cd', ),
('tracks_array', ))

def __repr__(self):
return Structure.__repr__(self, self._material_)
class FLAC__StreamMetadata_Picture(Structure):
_fields_ = [ ('type', c_int),
('mime_type', c_char_p),

# description is listed as FLAC__byte_p, but
# documented as NUL terminated UTF-8 string
('description', c_char_p),
('width', c_uint32),
('height', c_uint32),
('depth', c_uint32),
('colors', c_uint32),
('data_length', c_uint32),
('data', FLAC__byte_p),
]

_material_ = (('type', ), ('mime_type', ), ('width', ), ('height', ), ('depth', ), ('colors', ))

def asobj(self):
return (self.type, self.mime_type,
self.description.decode('utf-8'), self.width, self.height,
self.depth, self.colors,
''.join(chr(x) for x in self.data[:self.data_length]))

class FLAC__StreamMetadataData(Union):
_fields_ = [ ('stream_info', FLAC__StreamMetadata_StreamInfo),
('vorbis_comment', FLAC__StreamMetadata_VorbisComment),
('cue_sheet', FLAC__StreamMetadata_CueSheet),
('picture', FLAC__StreamMetadata_Picture),
]

class FLAC__StreamMetadata(Structure):
@@ -472,6 +526,7 @@ class FLACDec(object):
tags = property(lambda x: x._tags)
vorbis = property(lambda x: x._vorbis)
cuesheet = property(lambda x: x._cuesheet)
pictures = property(lambda x: x._pictures)

def __len__(self):
return self._total_samps
@@ -497,10 +552,10 @@ class FLACDec(object):

flaclib.FLAC__stream_decoder_set_md5_checking(self.flacdec,
True)
flaclib.FLAC__stream_decoder_set_metadata_respond(self.flacdec,
FLAC__METADATA_TYPE_VORBIS_COMMENT)
flaclib.FLAC__stream_decoder_set_metadata_respond(self.flacdec,
FLAC__METADATA_TYPE_CUESHEET)
for i in (FLAC__METADATA_TYPE_VORBIS_COMMENT,
FLAC__METADATA_TYPE_CUESHEET, FLAC__METADATA_TYPE_PICTURE):
flaclib.FLAC__stream_decoder_set_metadata_respond(
self.flacdec, i)

status = flaclib.FLAC__stream_decoder_init_file(self.flacdec,
file, self.write_wrap, self.metadata_wrap,
@@ -512,6 +567,7 @@ class FLACDec(object):
self._tags = {}
self._vorbis = None
self._cuesheet = None
self._pictures = {}

flaclib.FLAC__stream_decoder_process_until_end_of_metadata(
self.flacdec)
@@ -595,6 +651,13 @@ class FLACDec(object):
self._cuesheet = md.data.cue_sheet.asobj()
#print 'cs:', `md.data.cue_sheet`
#print 'c:', `self.cuesheet`
elif md.type == FLAC__METADATA_TYPE_PICTURE:
pict = md.data.picture
#print 'p:', `md.data.picture`
#print 'po:', `pict.asobj()`
self._pictures.setdefault(pictnamemap[pict.type],
[]).append(pict.asobj())
#print 'pd:', `self._pictures`
else:
print 'unknown metatype:', md.type

@@ -695,6 +758,7 @@ if __name__ == '__main__':
print 'channels:', d.channels
print 'rate:', d.samplerate
print 'bps:', d.bitspersample
print 'pict types:', d.pictures.keys()
print `d.read(10)`
print 'going'
d.goto(d.totalsamples - 1000*1000)


Loading…
Cancel
Save