A module to parse/generate MediaDescription handles as used by QuickTime. Only
generic, video and audio implemented for now.
diff --git a/Mac/Lib/lib-toolbox/MediaDescr.py b/Mac/Lib/lib-toolbox/MediaDescr.py
new file mode 100644
index 0000000..3c73820
--- /dev/null
+++ b/Mac/Lib/lib-toolbox/MediaDescr.py
@@ -0,0 +1,97 @@
+# 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.