diff --git a/Demo/sgi/video/VFile.py b/Demo/sgi/video/VFile.py
index e43bd94..0f72306 100755
--- a/Demo/sgi/video/VFile.py
+++ b/Demo/sgi/video/VFile.py
@@ -1,91 +1,231 @@
-# VFile -- two classes for Video Files.
-# VinFile -- for video input.
-# VoutFile -- for video output.
+# Classes to read and write CMIF video files.
+# (For a description of the CMIF video format, see cmif-file.ms.)
+
+
+# Layers of functionality:
+#
+# VideoParams: maintain essential parameters of a video file
+# Displayer: display a frame in a window (with some extra parameters)
+# Grabber: grab a frame from a window
+# BasicVinFile: read a CMIF video file
+# BasicVoutFile: write a CMIF video file
+# VinFile: BasicVinFile + Displayer
+# VoutFile: BasicVoutFile + Displayer + Grabber
+
+
+# Imported modules
 
 import sys
 import gl
 import GL
 import colorsys
 
-Error = 'VFile.Error' # Exception
 
-# Missing from GL.py:
+# Exception raised for various occasions
+
+Error = 'VFile.Error'			# file format errors
+CallError = 'VFile.CallError'		# bad call
+
+
+# Constants returned by gl.getdisplaymode(), from <gl/get.h>
+
 DMRGB = 0
+DMSINGLE = 1
+DMDOUBLE = 2
+DMRGBDOUBLE = 5
+
+
+# Max nr. of colormap entries to use
 
 MAXMAP = 4096 - 256
 
-def conv_grey(l,x,y): return colorsys.yiq_to_rgb(l,0,0)
-def conv_yiq (y,i,q): return colorsys.yiq_to_rgb(y, (i-0.5)*1.2, q-0.5)
-def conv_hls (l,h,s): return colorsys.hls_to_rgb(h,l,s)
-def conv_hsv (v,h,s): return colorsys.hsv_to_rgb(h,s,v)
-def conv_rgb (r,g,b):
+
+# Parametrizations of colormap handling based on color system.
+# (These functions are used via eval with a constructed argument!)
+
+def conv_grey(l, x, y):
+	return colorsys.yiq_to_rgb(l, 0, 0)
+
+def conv_yiq(y, i, q):
+	return colorsys.yiq_to_rgb(y, (i-0.5)*1.2, q-0.5)
+
+def conv_hls(l, h, s):
+	return colorsys.hls_to_rgb(h, l, s)
+
+def conv_hsv(v, h, s):
+	return colorsys.hsv_to_rgb(h, s, v)
+
+def conv_rgb(r, g, b):
 	raise Error, 'Attempt to make RGB colormap'
-def conv_rgb8(rgb,d1,d2):
+
+def conv_rgb8(rgb, d1, d2):
 	rgb = int(rgb*255.0)
 	r = (rgb >> 5) & 0x07
 	g = (rgb     ) & 0x07
 	b = (rgb >> 3) & 0x03
 	return (r/7.0, g/7.0, b/3.0)
 
-# Class VinFile represents a video file used for input.
-#
-# It has the following methods:
-# init(filename)
-# initfp(fp, filename)
-# reopen()
-# rewind()
-# getnextframe()
-# skipnextframe()
-# (and many more)
-#
-# The following read-only data members provide public information:
-# version
-# filename
-# width, height
-# packfactor
-# c0bits, c1bits, c2bits, chrompack
-# offset
-# format
-#
-# These writable data members provide additional parametrization:
-# magnify
-# xorigin, yorigin
-# fallback
+
+# Choose one of the above based upon a color system name
+
+def choose_conversion(format):
+	try:
+		return eval('conv_' + format)
+	except:
+		raise Error, 'Unknown color system: ' + `format`
 
 
+# Routines to grab data, per color system (only a few really supported).
+# (These functions are used via eval with a constructed argument!)
 
-# XXX it's a total mess now -- VFile is a new base class
-# XXX to support common functionality (e.g. showframe)
+def grab_rgb(w, h, pf):
+	if gl.getdisplaymode() <> DMRGB:
+		raise Error, 'Sorry, can only grab rgb in single-buf rgbmode'
+	if pf <> 1 and pf <> 0:
+		raise Error, 'Sorry, only grab rgb with packfactor 1'
+	return gl.lrectread(0, 0, w-1, h-1), None
 
-class VFile:
+def grab_rgb8(w, h, pf):
+	if gl.getdisplaymode() <> DMRGB:
+		raise Error, 'Sorry, can only grab rgb8 in single-buf rgbmode'
+	if pf <> 1 and pf <> 0:
+		raise Error, 'Sorry, can only grab rgb8 with packfactor 1'
+	r = gl.getgdesc(GL.GD_BITS_NORM_SNG_RED)
+	g = gl.getgdesc(GL.GD_BITS_NORM_SNG_GREEN)
+	b = gl.getgdesc(GL.GD_BITS_NORM_SNG_BLUE)
+	if (r, g, b) <> (3, 3, 2):
+		raise Error, 'Sorry, can only grab rgb8 on 8-bit Indigo'
+	# XXX Dirty Dirty here.
+	# XXX Set buffer to cmap mode, grab image and set it back.
+	# XXX (Shouldn't be necessary???)
+	gl.cmode()
+	gl.gconfig()
+	gl.pixmode(GL.PM_SIZE, 8)
+	data = gl.lrectread(0, 0, w-1, h-1)
+	data = data[:w*h]	# BUG FIX for python lrectread
+	gl.RGBmode()
+	gl.gconfig()
+	gl.pixmode(GL.PM_SIZE, 32)
+	return data, None
 
-	#
-	# getinfo returns all info pertaining to a film. The returned tuple
-	# can be passed to VoutFile.setinfo()
-	#
+def grab_grey(w, h, pf):
+	raise Error, 'Sorry, grabbing grey not implemented'
+
+def grab_yiq(w, h, pf):
+	raise Error, 'Sorry, grabbing yiq not implemented'
+
+def grab_hls(w, h, pf):
+	raise Error, 'Sorry, grabbing hls not implemented'
+
+def grab_hsv(w, h, pf):
+	raise Error, 'Sorry, grabbing hsv not implemented'
+
+
+# Choose one of the above based upon a color system name
+
+def choose_grabber(format):
+	try:
+		return eval('grab_' + format)
+	except:
+		raise Error, 'Unknown color system: ' + `format`
+
+
+# Base class to manage video format parameters
+
+class VideoParams:
+
+	# Initialize an instance.
+	# Set all parameters to something decent
+	# (except width and height are set to zero)
+
+	def init(self):
+		# Essential parameters
+		self.format = 'grey'	# color system used
+		# Choose from: 'rgb', 'rgb8', 'hsv', 'yiq', 'hls'
+		self.width = 0		# width of frame
+		self.height = 0		# height of frame
+		self.packfactor = 1	# expansion using rectzoom
+		# if packfactor == 0, data is one 32-bit word/pixel;
+		# otherwise, data is one byte/pixel
+		self.c0bits = 8		# bits in first color dimension
+		self.c1bits = 0		# bits in second color dimension
+		self.c2bits = 0		# bits in third color dimension
+		self.offset = 0		# colormap index offset (XXX ???)
+		self.chrompack = 0	# set if separate chrominance data
+		return self
+
+	# Set the frame width and height (e.g. from gl.getsize())
+
+	def setsize(self, size):
+		self.width, self.height = size
+
+	# Retrieve the frame width and height (e.g. for gl.prefsize())
+
+	def getsize(self):
+		return (self.width, self.height)
+
+	# Set all parameters.
+	# This does limited validity checking;
+	# if the check fails no parameters are changed
+
+	def setinfo(self, values):
+		(self.format, self.width, self.height, self.packfactor,\
+			self.c0bits, self.c1bits, self.c2bits, self.offset, \
+			self.chrompack) = values
+
+	# Retrieve all parameters in a format suitable for a subsequent
+	# call to setinfo()
+
 	def getinfo(self):
 		return (self.format, self.width, self.height, self.packfactor,\
-			  self.c0bits, self.c1bits, self.c2bits, self.offset, \
-			  self.chrompack)
+			self.c0bits, self.c1bits, self.c2bits, self.offset, \
+			self.chrompack)
 
-	# reopen() raises Error if the header is bad (which can only
-	# happen if the file was written to since opened).
+	# Write the relevant bits to stdout
 
-	def reopen(self):
-		self.fp.seek(0)
-		x = self.initfp(self.fp, self.filename)
+	def printinfo(self):
+		print 'Format:  ', self.format
+		print 'Size:    ', self.width, 'x', self.height
+		print 'Pack:    ', self.packfactor, '; chrom:', self.chrompack
+		print 'Bits:    ', self.c0bits, self.c1bits, self.c2bits
+		print 'Offset:  ', self.offset
 
-	def setconvcolor(self):
-		try:
-			self.convcolor = eval('conv_'+self.format)
-		except:
-			raise Error, \
-			  self.filename + ': unknown colorsys ' + self.format
+
+# Class to display video frames in a window.
+# It is the caller's responsibility to ensure that the correct window
+# is current when using showframe(), initcolormap() and clear()
+
+class Displayer(VideoParams):
+
+	# Initialize an instance.
+	# This does not need a current window
+
+	def init(self):
+		self = VideoParams.init(self)
+		# User-settable parameters
+		self.magnify = 1.0	# frame magnification factor
+		self.xorigin = 0	# x frame offset
+		self.yorigin = 0	# y frame offset (from bottom)
+		self.quiet = 0		# if set, don't print messages
+		self.fallback = 1	# allow fallback to grey
+		# Internal flags
+		self.colormapinited = 0	# must initialize window
+		self.skipchrom = 0	# don't skip chrominance data
+		return self
+
+	# setinfo() must reset some internal flags
+
+	def setinfo(self, values):
+		VideoParams.setinfo(values)
+		self.colormapinited = 0
+		self.skipchrom = 0
+
+	# Show one frame, initializing the window if necessary
 
 	def showframe(self, data, chromdata):
-		w, h, pf = self.width, self.height, self.packfactor
 		if not self.colormapinited:
 			self.initcolormap()
+		w, h, pf = self.width, self.height, self.packfactor
 		factor = self.magnify
 		if pf: factor = factor * pf
 		if chromdata and not self.skipchrom:
@@ -102,50 +242,62 @@
 		if pf:
 			gl.writemask((1 << self.c0bits) - 1)
 			gl.pixmode(GL.PM_SIZE, 8)
-			gl.rectzoom(factor, factor)
 			w = w/pf
 			h = h/pf
+		gl.rectzoom(factor, factor)
 		gl.lrectwrite(self.xorigin, self.yorigin, \
 			self.xorigin + w - 1, self.yorigin + h - 1, data)
 
+	# Initialize the window: set RGB or colormap mode as required,
+	# fill in the colormap, and clear the window
+
 	def initcolormap(self):
-		self.colormapinited = 1
 		if self.format == 'rgb':
 			gl.RGBmode()
 			gl.gconfig()
-			gl.RGBcolor(200, 200, 200)
+			self.colormapinited = 1
+			gl.RGBcolor(200, 200, 200) # XXX rather light grey
 			gl.clear()
 			return
 		gl.cmode()
 		gl.gconfig()
 		self.skipchrom = 0
+		if self.offset == 0:
+			self.mask = 0x7ff
+		else:
+			self.mask = 0xfff
 		if not self.quiet:
 			sys.stderr.write('Initializing color map...')
-		self.initcmap()
+		self._initcmap()
+		self.colormapinited = 1
 		self.clear()
 		if not self.quiet:
 			sys.stderr.write(' Done.\n')
 
+	# Clear the window
+
 	def clear(self):
+		if not self.colormapinited: raise CallError
 		if self.offset == 0:
 			gl.color(0x800)
 			gl.clear()
-			self.mask = 0x7ff
 		else:
-			self.mask = 0xfff
 			gl.clear()
 
-	def initcmap(self):
+	# Do the hard work for initializing the colormap
+
+	def _initcmap(self):
+		convcolor = choose_conversion(self.format)
 		maxbits = gl.getgdesc(GL.GD_BITS_NORM_SNG_CMODE)
 		if maxbits > 11:
 			maxbits = 11
 		c0bits, c1bits, c2bits = self.c0bits, self.c1bits, self.c2bits
 		if c0bits+c1bits+c2bits > maxbits:
 			if self.fallback and c0bits < maxbits:
-				# Cannot display film in this mode, use mono
+				# Cannot display frames in this mode, use grey
 				self.skipchrom = 1
 				c1bits = c2bits = 0
-				self.convcolor = conv_grey
+				convcolor = choose_conversion('grey')
 			else:
 				raise Error, 'Sorry, '+`maxbits`+ \
 				  ' bits max on this machine'
@@ -158,9 +310,10 @@
 			offset = self.offset
 		if maxbits <> 11:
 			offset = offset & ((1<<maxbits)-1)
-		#for i in range(512, MAXMAP):
+		# XXX why is this here?
+		# for i in range(512, MAXMAP):
 		#	gl.mapcolor(i, 0, 0, 0)
-		#void = gl.qtest()    # Should be gl.gflush()
+		# gl.gflush()
 		for c0 in range(maxc0):
 			c0v = c0/float(maxc0-1)
 			for c1 in range(maxc1):
@@ -174,366 +327,420 @@
 					else:
 						c2v = c2/float(maxc2-1)
 					index = offset + c0 + (c1<<c0bits) + \
-						  (c2 << (c0bits+c1bits))
-					rv, gv, bv = self.convcolor( \
-						  c0v, c1v, c2v)
-					r, g, b = int(rv*255.0), \
-						  int(gv*255.0), int(bv*255.0)
+						(c2 << (c0bits+c1bits))
 					if index < MAXMAP:
+						rv, gv, bv = \
+						  convcolor(c0v, c1v, c2v)
+						r, g, b = int(rv*255.0), \
+							  int(gv*255.0), \
+							  int(bv*255.0)
 						gl.mapcolor(index, r, g, b)
-		void = gl.gflush()
+		gl.gflush() # send the colormap changes to the X server
 
-	
 
-class VinFile(VFile):
+# Class to grab frames from a window.
+# (This has fewer user-settable parameters than Displayer.)
+# It is the caller's responsibility to initialize the window and to
+# ensure that it is current when using grabframe()
 
-	# init() and initfp() raise Error if the header is bad.
-	# init() raises whatever open() raises if the file can't be opened.
+class Grabber(VideoParams):
 
-	def init(self, filename):
-		if filename == '-':
-			return self.initfp(sys.stdin, filename)
-		return self.initfp(open(filename, 'r'), filename)
+	# XXX The init() method of VideoParams is just fine, for now
 
-	def initfp(self, fp, filename):
-		self.colormapinited = 0
-		self.magnify = 1.0
-		self.xorigin = self.yorigin = 0
-		self.fallback = 1
-		self.skipchrom = 0
-		self.fp = fp
-		self.filename = filename
-		self.quiet = 0
-		#
-		line = self.fp.readline()
-		if line == 'CMIF video 1.0\n':
-			self.version = 1.0
-		elif line == 'CMIF video 2.0\n':
-			self.version = 2.0
-		elif line == 'CMIF video 3.0\n':
-			self.version = 3.0
-		else:
-			raise Error, self.filename + ': bad video format'
-		#
-		if self.version < 2.0:
-			self.c0bits, self.c1bits, self.c2bits = 8, 0, 0
-			self.chrompack = 0
-			self.offset = 0
-			self.format = 'grey'
-		elif self.version == 2.0:
-			line = self.fp.readline()
-			try:
-				self.c0bits, self.c1bits, self.c2bits, \
-					self.chrompack = eval(line[:-1])
-				if self.c1bits or self.c2bits:
-					self.format = 'yiq'
-				else:
-					self.format = 'grey'
-				self.offset = 0
-			except:
-				raise Error, \
-				  self.filename + ': bad 2.0 color info'
-		elif self.version == 3.0:
-			line = self.fp.readline()
-			try:
-				self.format, rest = eval(line[:-1])
-				if self.format == 'rgb':
-					self.offset = 0
-					self.c0bits = 0
-					self.c1bits = 0
-					self.c2bits = 0
-					self.chrompack = 0
-				elif self.format == 'grey':
-					self.offset = 0
-					self.c0bits = rest
-					self.c1bits = self.c2bits = \
-						self.chrompack = 0
-				else:
-					self.c0bits,self.c1bits,self.c2bits,\
-					  self.chrompack,self.offset = rest
-			except:
-				raise Error, \
-					self.filename + ': bad 3.0 color info'
-
-		self.setconvcolor()
-		#
-		line = self.fp.readline()
-		try:
-			x = eval(line[:-1])
-			if self.version > 1.0 or len(x) == 3:
-				self.width, self.height, self.packfactor = x
-				if self.packfactor == 0:
-					self.format = 'rgb'
-			else:
-				sef.width, self.height = x
-				self.packfactor = 2
-		except:
-			raise Error, self.filename + ': bad (w,h,pf) info'
-		self.frameno = 0
-		self.framecache = []
-		self.hascache = 0
-		#
-		return self
-
-	def warmcache(self):
-		if self.hascache: return
-		n = 0
-		try:
-			while 1:
-				void = self.skipnextframe()
-				n = n + 1
-		except EOFError:
-			pass
-		if not self.hascache:
-			raise Error, 'Cannot warm cache'
-
-	def close(self):
-		self.fp.close()
-		self.fp = None
-
-	def rewind(self):
-		if self.hascache:
-			self.frameno = 0
-		else:
-			self.reopen()
-
-	def position(self):
-		if self.frameno >= len(self.framecache):
-			raise EOFError
-		self.fp.seek(self.framecache[self.frameno][0])
-
-	# getnextframe() raises EOFError (built-in) if there is no next frame,
-	# or if the next frame is broken.
-	# So to getnextframeheader(), getnextframedata() and skipnextframe().
-
-	def getnextframe(self):
-		time, size, chromsize = self.getnextframeheader()
-		data, chromdata = self.getnextframedata(size, chromsize)
-		return time, data, chromdata
-
-	def getnextframedata(self, size, chromsize):
-		if self.hascache:
-			self.position()
-		self.frameno = self.frameno + 1
-		data = self.fp.read(size)
-		if len(data) <> size: raise EOFError
-		if chromsize:
-			chromdata = self.fp.read(chromsize)
-			if len(chromdata) <> chromsize: raise EOFError
-		else:
-			chromdata = None
-		#
-		return data, chromdata
-
-	def skipnextframe(self):
-		time, size, chromsize = self.getnextframeheader()
-		self.skipnextframedata(size, chromsize)
-		return time
-
-	def skipnextframedata(self, size, chromsize):
-		if self.hascache:
-			self.frameno = self.frameno + 1
-			return
-		# Note that this won't raise EOFError for a partial frame.
-		try:
-			self.fp.seek(size + chromsize, 1) # Relative seek
-		except:
-			# Assume it's a pipe -- read the data to discard it
-			dummy = self.fp.read(size + chromsize)
-
-	def getnextframeheader(self):
-		if self.hascache:
-			if self.frameno >= len(self.framecache):
-				raise EOFError
-			return self.framecache[self.frameno][1]
-		line = self.fp.readline()
-		if not line:
-			self.hascache = 1
-			raise EOFError
-		#
-		w, h, pf = self.width, self.height, self.packfactor
-		try:
-			x = eval(line[:-1])
-			if type(x) in (type(0), type(0.0)):
-				time = x
-				if pf == 0:
-					size = w * h * 4
-				else:
-					size = (w/pf) * (h/pf)
-			elif len(x) == 2:
-				time, size = x
-				cp = self.chrompack
-				if cp:
-					cw = (w + cp - 1) / cp
-					ch = (h + cp - 1) / cp
-					chromsize = 2 * cw * ch
-				else:
-					chromsize = 0
-			else:
-				time, size, chromsize = x
-		except:
-			raise Error, self.filename + ': bad frame header'
-		cdata = (self.fp.tell(), (time, size, chromsize))
-		self.framecache.append(cdata)
-		return time, size, chromsize
-
-	def shownextframe(self):
-		time, data, chromdata = self.getnextframe()
-		self.showframe(data, chromdata)
-		return time
-
-#
-# A set of routines to grab images from windows
-#
-def grab_rgb(w, h, pf):
-	if gl.getdisplaymode() <> DMRGB:
-		raise Error, 'Sorry, can only grab rgb in single-buf rgbmode'
-	if pf <> 1 and pf <> 0:
-		raise Error, 'Sorry, only grab with packfactor=1'
-	return gl.lrectread(0, 0, w-1, h-1), None
-	
-def grab_rgb8(w, h, pf):
-	if gl.getdisplaymode() <> DMRGB:
-		raise Error, 'Sorry, can only grab rgb in single-buf rgbmode'
-	if pf <> 1 and pf <> 0:
-		raise Error, 'Sorry, can only grab with packfactor=1'
-	r = gl.getgdesc(GL.GD_BITS_NORM_SNG_RED)
-	g = gl.getgdesc(GL.GD_BITS_NORM_SNG_GREEN)
-	b = gl.getgdesc(GL.GD_BITS_NORM_SNG_BLUE)
-	if (r,g,b) <> (3,3,2):
-		raise Error, 'Sorry, can only grab rgb8 on 8-bit Indigo'
-	# Dirty Dirty here. Set buffer to cmap mode, grab image and set it back
-	gl.cmode()
-	gl.gconfig()
-	gl.pixmode(GL.PM_SIZE, 8)
-	data = gl.lrectread(0, 0, w-1, h-1)
-	data = data[:w*h]	# BUG FIX for python lrectread
-	gl.RGBmode()
-	gl.gconfig()
-	gl.pixmode(GL.PM_SIZE, 32)
-	return data, None
-	
-def grab_grey(w, h, pf):
-	raise Error, 'Sorry, grabbing grey not implemented'
-
-def grab_yiq(w, h, pf):
-	raise Error, 'Sorry, grabbing yiq not implemented'
-
-def grab_hls(w, h, pf):
-	raise Error, 'Sorry, grabbing hls not implemented'
-
-def grab_hsv(w, h, pf):
-	raise Error, 'Sorry, grabbing hsv not implemented'
-
-#
-# The class VoutFile is not as well-designed (and tested) as VinFile.
-# Notably it will accept almost any garbage and write it to the video
-# output file
-#
-class VoutFile(VFile):
-	def init(self, filename):
-		if filename == '-':
-			return self.initfp(sys.stdout, filename)
-		else:
-			return self.initfp(open(filename,'w'), filename)
-			
-	def initfp(self, fp, filename):
-		self.fp = fp
-		self.format = 'grey'
-		self.width = self.height = 0
-		self.packfactor = 1
-		self.c0bits = 8
-		self.c1bits = self.c2bits = 0
-		self.offset = 0
-		self.chrompack = 0
-		self.headerwritten = 0
-		self.quiet = 0
-		self.magnify = 1
-		self.setconvcolor()
-		self.xorigin = self.yorigin = 0
-		return self
-
-	def close(self):
-		self.fp.close()
-		x = self.initfp(None, None)
-
-	def setinfo(self, values):
-		self.format, self.width, self.height, self.packfactor,\
-			  self.c0bits, self.c1bits, self.c2bits, self.offset, \
-			  self.chrompack = values
-		self.setconvcolor()
-
-	def writeheader(self):
-		self.headerwritten = 1
-		if self.format == 'rgb':
-			self.packfactor = 0
-		elif self.packfactor == 0:
-			self.packfactor = 1
-		self.fp.write('CMIF video 3.0\n')
-		if self.format == 'rgb':
-			data = ('rgb', 0)
-		elif self.format == 'grey':
-			data = ('grey', self.c0bits)
-		else:
-			data = (self.format, (self.c0bits, self.c1bits, \
-				  self.c2bits, self.chrompack, self.offset))
-		self.fp.write(`data`+'\n')
-		data = (self.width, self.height, self.packfactor)
-		self.fp.write(`data`+'\n')
-		try:
-			self._grabber = eval('grab_' + self.format)
-		except:
-			raise Error, 'unknown colorsys: ' + self.format
-
-	def writeframeheader(self, data):
-		if not self.headerwritten:
-			raise Error, 'Writing frame data before header'
-		# XXXX Should we sanity check here?
-		self.fp.write(`data`+'\n')
-
-	def writeframedata(self, data, chromdata):
-		# XXXX Check sizes here
-		self.fp.write(data)
-		if chromdata:
-			self.fp.write(chromdata)
-
-	def writeframe(self, time, data, chromdata):
-		if chromdata:
-			clen = len(chromdata)
-		else:
-			clen = 0
-		self.writeframeheader((time, len(data), clen))
-		self.writeframedata(data, chromdata)
+	# Grab a frame.
+	# Return (data, chromdata) just like getnextframe().
 
 	def grabframe(self):
-		return self._grabber(self.width, self.height, self.packfactor)
-		
+		grabber = choose_grabber(self.format)
+		return grabber(self.width, self.height, self.packfactor)
+
+
+# Read a CMIF video file header.
+# Return (version, values) where version is 0.0, 1.0, 2.0 or 3.0,
+# and values is ready for setinfo().
+# Raise Error if there is an error in the info
+
+def readfileheader(fp, filename):
+	#
+	# Get identifying header
+	#
+	line = fp.readline(20)
+	if   line == 'CMIF video 0.0\n':
+		version = 0.0
+	elif line == 'CMIF video 1.0\n':
+		version = 1.0
+	elif line == 'CMIF video 2.0\n':
+		version = 2.0
+	elif line == 'CMIF video 3.0\n':
+		version = 3.0
+	else:
+		# XXX Could be version 0.0 without identifying header
+		raise Error, \
+			filename + ': Unrecognized file header: ' + `line`[:20]
+	#
+	# Get color encoding info
+	#
+	if version <= 1.0:
+		format = 'grey'
+		c0bits, c1bits, c2bits = 8, 0, 0
+		chrompack = 0
+		offset = 0
+	elif version == 2.0:
+		line = fp.readline()
+		try:
+			c0bits, c1bits, c2bits, chrompack = eval(line[:-1])
+		except:
+			raise Error, filename + ': Bad 2.0 color info'
+		if c1bits or c2bits:
+			format = 'yiq'
+		else:
+			format = 'grey'
+		offset = 0
+	elif version == 3.0:
+		line = fp.readline()
+		try:
+			format, rest = eval(line[:-1])
+		except:
+			raise Error, filename + ': Bad 3.0 color info'
+		if format == 'rgb':
+			c0bits = c1bits = c2bits = 0
+			chrompack = 0
+			offset = 0
+		elif format == 'grey':
+			c0bits = rest
+			c1bits = c2bits = 0
+			chrompack = 0
+			offset = 0
+		else:
+			try:
+			    c0bits, c1bits, c2bits, chrompack, offset = rest
+			except:
+			    raise Error, filename + ': Bad 3.0 color info'
+	#
+	# Get frame geometry info
+	#
+	line = fp.readline()
+	try:
+		x = eval(line[:-1])
+	except:
+		raise Error, filename + ': Bad (w,h,pf) info'
+	if len(x) == 3:
+		width, height, packfactor = x
+		if packfactor == 0 and version < 3.0:
+			format = 'rgb'
+	elif len(x) == 2 and version <= 1.0:
+		width, height = x
+		packfactor = 2
+	else:
+		raise Error, filename + ': Bad (w,h,pf) info'
+	#
+	# Return (version, values)
+	#
+	values = (format, width, height, packfactor, \
+		  c0bits, c1bits, c2bits, offset, chrompack)
+	return (version, values)
+
+
+# Read a *frame* header -- separate functions per version.
+# Return (timecode, datasize, chromdatasize).
+# Raise EOFError if end of data is reached.
+# Raise Error if data is bad.
+
+def readv0frameheader(fp):
+	line = fp.readline()
+	if not line or line == '\n': raise EOFError
+	try:
+		t = eval(line[:-1])
+	except:
+		raise Error, 'Bad 0.0 frame header'
+	return (t, 0, 0)
+
+def readv1frameheader(fp):
+	line = fp.readline()
+	if not line or line == '\n': raise EOFError
+	try:
+		t, datasize = eval(line[:-1])
+	except:
+		raise Error, 'Bad 1.0 frame header'
+	return (t, datasize, 0)
+
+def readv2frameheader(fp):
+	line = fp.readline()
+	if not line or line == '\n': raise EOFError
+	try:
+		t, datasize = eval(line[:-1])
+	except:
+		raise Error, 'Bad 2.0 frame header'
+	return (t, datasize, 0)
+
+def readv3frameheader(fp):
+	line = fp.readline()
+	if not line or line == '\n': raise EOFError
+	try:
+		t, datasize, chromdatasize = x = eval(line[:-1])
+	except:
+		raise Error, 'Bad 3.0 frame header'
+	return x
+
+
+# Write a CMIF video file header (always version 3.0)
+
+def writefileheader(fp, values):
+	(format, width, height, packfactor, \
+		c0bits, c1bits, c2bits, offset, chrompack) = values
+	#
+	# Write identifying header
+	#
+	fp.write('CMIF video 3.0\n')
+	#
+	# Write color encoding info
+	#
+	if format == 'rgb':
+		data = ('rgb', 0)
+	elif format == 'grey':
+		data = ('grey', c0bits)
+	else:
+		data = (format, (c0bits, c1bits, c2bits, chrompack, offset))
+	fp.write(`data`+'\n')
+	#
+	# Write frame geometry info
+	#
+	if format == 'rgb':
+		packfactor = 0
+	elif packfactor == 0:
+		packfactor = 1
+	data = (width, height, packfactor)
+	fp.write(`data`+'\n')
+
+
+# Basic class for reading CMIF video files
+
+class BasicVinFile(VideoParams):
+
+	def init(self, filename):
+		if filename == '-':
+			fp = sys.stdin
+		else:
+			fp = open(filename, 'r')
+		return self.initfp(fp, filename)
+
+	def initfp(self, fp, filename):
+		self = VideoParams.init(self)
+		self.fp = fp
+		self.filename = filename
+		self.version, values = readfileheader(fp, filename)
+		VideoParams.setinfo(self, values)
+		if self.version == 0.0:
+			w, h, pf = self.width, self.height, self.packfactor
+			if pf == 0:
+				self._datasize = w*h*4
+			else:
+				self._datasize = (w/pf) * (h/pf)
+			self._readframeheader = self._readv0frameheader
+		elif self.version == 1.0:
+			self._readframeheader = readv1frameheader
+		elif self.version == 2.0:
+			self._readframeheader = readv2frameheader
+		elif self.version == 3.0:
+			self._readframeheader = readv3frameheader
+		else:
+			raise Error, \
+				filename + ': Bad version: ' + `self.version`
+		self.framecount = 0
+		self.atframeheader = 1
+		try:
+			self.startpos = self.fp.tell()
+			self.canseek = 1
+		except IOError:
+			self.startpos = -1
+			self.canseek = 0
+		return self
+
+	def _readv0frameheader(self, fp):
+		t, ds, cs = readv0frameheader(fp)
+		ds = self._datasize
+		return (t, ds, cs)
+
+	def close(self):
+		self.fp.close()
+		del self.fp
+		del self._readframeheader
+
+	def setinfo(self, values):
+		raise CallError # Can't change info of input file!
+
+	def setsize(self, size):
+		raise CallError # Can't change info of input file!
+
+	def rewind(self):
+		if not self.canseek:
+			raise Error, self.filename + ': can\'t seek'
+		self.fp.seek(self.startpos)
+		self.framecount = 0
+		self.atframeheader = 1
+
+	def warmcache(self):
+		pass
+
+	def printinfo(self):
+		print 'File:    ', self.filename
+		print 'Version: ', self.version
+		VideoParams.printinfo(self)
+
+	def getnextframe(self):
+		t, ds, cs = self.getnextframeheader()
+		data, cdata = self.getnextframedata(ds, cs)
+		return (t, data, cdata)
+
+	def skipnextframe(self):
+		t, ds, cs = self.getnextframeheader()
+		self.skipnextframedata(ds, cs)
+		return t
+
+	def getnextframeheader(self):
+		if not self.atframeheader: raise CallError
+		self.atframeheader = 0
+		try:
+			return self._readframeheader(self.fp)
+		except Error, msg:
+			# Patch up the error message
+			raise Error, self.filename + ': ' + msg
+
+	def getnextframedata(self, ds, cs):
+		if self.atframeheader: raise CallError
+		if ds:
+			data = self.fp.read(ds)
+			if len(data) < ds: raise EOFError
+		else:
+			data = ''
+		if cs:
+			cdata = self.fp.read(cs)
+			if len(cdata) < cs: raise EOFerror
+		else:
+			cdata = ''
+		self.atframeheader = 1
+		self.framecount = self.framecount + 1
+		return (data, cdata)
+
+	def skipnextframedata(self, ds, cs):
+		if self.atframeheader: raise CallError
+		# Note that this won't raise EOFError for a partial frame
+		# since there is no easy way to tell whether a seek
+		# ended up beyond the end of the file
+		if self.canseek:
+			self.fp.seek(ds + cs, 1) # Relative seek
+		else:
+			dummy = self.fp.read(ds + cs)
+			del dummy
+		self.atframeheader = 1
+		self.framecount = self.framecount + 1
+
+
+class BasicVoutFile(VideoParams):
+
+	def init(self, filename):
+		if filename == '-':
+			fp = sys.stdout
+		else:
+			fp = open(filename, 'w')
+		return self.initfp(fp, filename)
+
+	def initfp(self, fp, filename):
+		self = VideoParams.init(self)
+		self.fp = fp
+		self.filename = filename
+		self.version = 3.0 # In case anyone inquires
+		self.headerwritten = 0
+		return self
+
+	def flush(self):
+		self.fp.flush()
+
+	def close(self):
+		self.fp.close()
+		del self.fp
+
+	def setinfo(self, values):
+		if self.headerwritten: raise CallError
+		VideoParams.setinfo(self, values)
+
+	def writeheader(self):
+		if self.headerwritten: raise CallError
+		writefileheader(self.fp, self.getinfo())
+		self.headerwritten = 1
+		self.atheader = 1
+		self.framecount = 0
+
+	def rewind(self):
+		self.fp.seek(0)
+		self.headerwritten = 0
+		self.atheader = 1
+		self.framecount = 0
+
+	def printinfo(self):
+		print 'File:    ', self.filename
+		VideoParams.printinfo(self)
+
+	def writeframe(self, t, data, cdata):
+		if data: ds = len(data)
+		else: ds = 0
+		if cdata: cs = len(cdata)
+		else: cs = 0
+		self.writeframeheader(t, ds, cs)
+		self.writeframedata(data, cdata)
+
+	def writeframeheader(self, t, ds, cs):
+		if not self.headerwritten: self.writeheader()
+		if not self.atheader: raise CallError
+		self.fp.write(`(t, ds, cs)` + '\n')
+		self.atheader = 0
+
+	def writeframedata(self, data, cdata):
+		if not self.headerwritten or self.atheader: raise CallError
+		if data: self.fp.write(data)
+		if cdata: self.fp.write(cdata)
+		self.atheader = 1
+		self.framecount = self.framecount + 1
+
+
+# Classes that combine files with displayers and/or grabbers:
+
+class VinFile(BasicVinFile, Displayer):
+
+	def initfp(self, fp, filename):
+		self = Displayer.init(self)
+		return BasicVinFile.initfp(self, fp, filename)
+
+	def shownextframe(self):
+		t, data, cdata = self.getnextframe()
+		self.showframe(data, cdata)
+		return t
+
+
+class VoutFile(BasicVoutFile, Displayer, Grabber):
+
+	def initfp(self, fp, filename):
+		self = Displayer.init(self)
+##		self = Grabber.init(self) # XXX not needed
+		return BasicVoutFile.initfp(self, fp, filename)
+
+
+# Simple test program (VinFile only)
+
 def test():
-	import sys, time
-	filename = 'film.video'
+	import time
 	if sys.argv[1:]: filename = sys.argv[1]
+	else: filename = 'film.video'
 	vin = VinFile().init(filename)
-	print 'File:    ', filename
-	print 'Version: ', vin.version
-	print 'Size:    ', vin.width, 'x', vin.height
-	print 'Pack:    ', vin.packfactor, '; chrom:', vin.chrompack
-	print 'Bits:    ', vin.c0bits, vin.c1bits, vin.c2bits
-	print 'Format:  ', vin.format
-	print 'Offset:  ', vin.offset
+	vin.printinfo()
 	gl.foreground()
-	gl.prefsize(vin.width, vin.height)
+	gl.prefsize(vin.getsize())
 	wid = gl.winopen(filename)
 	vin.initcolormap()
 	t0 = time.millitimer()
 	while 1:
-		try:
-			t, data, chromdata = vin.getnextframe()
-		except EOFError:
-			break
-		dt = t + t0 - time.millitimer()
-		if dt > 0:
-			time.millisleep(dt)
-		vin.showframe(data, chromdata)
-	print 'Done.'
+		try: t = vin.shownextframe()
+		except EOFError: break
+		dt = t0 + t - time.millitimer()
+		if dt > 0: time.millisleep(dt)
 	time.sleep(2)
-
