# Parsers/generators for QuickTime media descriptions
import struct

Error = 'MediaDescr.Error'

class _MediaDescriptionCodec:
	def __init__(self, trunc, size, names, fmt):
		self.trunc = trunc
		self.size = size
		self.names = names
		self.fmt = fmt
		
	def decode(self, data):
		if self.trunc:
			data = data[:self.size]
		values = struct.unpack(self.fmt, data)
		if len(values) != len(self.names):
			raise Error, ('Format length does not match number of names', descr)
		rv = {}
		for i in range(len(values)):
			name = self.names[i]
			value = values[i]
			if type(name) == type(()):
				name, cod, dec = name
				value = dec(value)
			rv[name] = value
		return rv
		
	def encode(dict):
		list = [self.fmt]
		for name in self.names:
			if type(name) == type(()):
				name, cod, dec = name
			else:
				cod = dec = None
			value = dict[name]
			if cod:
				value = cod(value)
			list.append(value)
		rv = apply(struct.pack, tuple(list))
		return rv
		
# Helper functions
def _tofixed(float):
	hi = int(float)
	lo = int(float*0x10000) & 0xffff
	return (hi<<16)|lo
	
def _fromfixed(fixed):
	hi = (fixed >> 16) & 0xffff
	lo = (fixed & 0xffff)
	return hi + (lo / float(0x10000))
	
def _tostr31(str):
	return chr(len(str)) + str + '\0'*(31-len(str))
	
def _fromstr31(str31):
	return str31[1:1+ord(str31[0])]

SampleDescription = _MediaDescriptionCodec(
	1,	# May be longer, truncate
	16,	# size
	('descSize', 'dataFormat', 'resvd1', 'resvd2', 'dataRefIndex'),	# Attributes
	"l4slhh"	# Format
)

SoundDescription = _MediaDescriptionCodec(
	1,
	36,
	('descSize', 'dataFormat', 'resvd1', 'resvd2', 'dataRefIndex',
	'version', 'revlevel', 'vendor', 'numChannels', 'sampleSize',
	'compressionID', 'packetSize', ('sampleRate', _tofixed, _fromfixed)),
	"l4slhhhh4shhhhl"	# Format
)

SoundDescriptionV1 = _MediaDescriptionCodec(
	1,
	52,
	('descSize', 'dataFormat', 'resvd1', 'resvd2', 'dataRefIndex',
	'version', 'revlevel', 'vendor', 'numChannels', 'sampleSize',
	'compressionID', 'packetSize', ('sampleRate', _tofixed, _fromfixed), 'samplesPerPacket',
	'bytesPerPacket', 'bytesPerFrame', 'bytesPerSample'),
	"l4slhhhh4shhhhlllll"	# Format
)

ImageDescription = _MediaDescriptionCodec(
	1,	# May be longer, truncate
	86,	# size
	('idSize', 'cType', 'resvd1', 'resvd2', 'dataRefIndex', 'version',
	 'revisionLevel', 'vendor', 'temporalQuality', 'spatialQuality',
	 'width', 'height', ('hRes', _tofixed, _fromfixed), ('vRes', _tofixed, _fromfixed), 
	'dataSize', 'frameCount', ('name', _tostr31, _fromstr31),
	 'depth', 'clutID'),
	'l4slhhhh4sllhhlllh32shh',
)

# XXXX Others, like TextDescription and such, remain to be done.
