New modules LiveVideo{In,Out} (interfaces will change!).
New programs V{send,receive} to send/receive video over UDP.
Comment typo changed in Vaddcache.
diff --git a/Demo/sgi/video/LiveVideoIn.py b/Demo/sgi/video/LiveVideoIn.py
new file mode 100755
index 0000000..65e5317
--- /dev/null
+++ b/Demo/sgi/video/LiveVideoIn.py
@@ -0,0 +1,95 @@
+# Live video input class.
+# Note that importing this module attempts to initialize video.
+
+
+# Check if video is available.
+# There are three reasons for failure here:
+# (1) this version of Python may not have the sv or imageop modules;
+# (2) this machine may not have a video board;
+# (3) initializing the video board may fail for another reason.
+# The global variable have_video is set to true iff we reall do have video.
+
+try:
+	import sv
+	import SV
+	import imageop
+	try:
+		v = sv.OpenVideo()
+		have_video = 1
+	except sv.error:
+		have_video = 0
+except ImportError:
+	have_video = 0
+
+
+# The live video input class.
+# Only instantiate this if have_video is true!
+
+class LiveVideoIn:
+
+	# Initialize an instance.
+	# Parameters:
+	# - vw, vh specify the size of the video window.
+	# This initializes continuous capture.
+
+	def init(self, pktmax, vw, vh):
+		if not have_video:
+			raise RuntimeError, 'no video available'
+		realvw = vh*SV.PAL_XMAX/SV.PAL_YMAX
+		if realvw < vw:
+			print 'Funny, image too narrow...'
+		self.realwidth, self.realheight = v.QuerySize(realvw, vh)
+		##print 'Recording video in size', \
+		##	self.realwidth, self.realheight
+		self.width = vw
+		self.height = vh
+		self.x0 = (self.realwidth-self.width)/2
+		self.x1 = self.x0 + self.width - 1
+		self.y0 = (self.realheight-self.height)/2
+		self.y1 = self.y0 + self.height - 1
+		# Compute # full lines per packet
+		self.lpp = pktmax / self.width
+		self.pktsize = self.lpp*self.width
+		##print 'lpp =', self.lpp, '; pktsize =', self.pktsize
+		# Initialize capture
+		v.SetSize(self.realwidth, self.realheight)
+		dummy = v.InitContinuousCapture(SV.RGB8_FRAMES, \
+			  self.realwidth, self.realheight, 2, 5)
+		self.data = None
+		self.lpos = 0
+		return self
+
+	# Remove an instance.
+	# This turns off continuous capture.
+
+	def close(self):
+		v.EndContinuousCapture()
+
+	# Get the next video packet.
+	# This returns (lpos, data) where:
+	# - lpos is the line position
+	# - data is a piece of data
+	# The dimensions of data are:
+	# - pixel depth = 1 byte
+	# - scan line width = self.width (the vw argument to init())
+	# - number of scan lines = self.lpp (PKTMAX / vw)
+
+	def getnextpacket(self):
+		if not self.data:
+			try:
+				cd, id = v.GetCaptureData()
+			except sv.error:
+				return None
+			data = cd.InterleaveFields(1)
+			cd.UnlockCaptureData()
+			self.data = imageop.crop(data, 1, \
+				  self.realwidth, \
+				  self.realheight, \
+				  self.x0, self.y0, \
+				  self.x1, self.y1)
+			self.lpos = 0
+		data = self.data[:self.pktsize]
+		self.data = self.data[self.pktsize:]
+		lpos = self.lpos
+		self.lpos = self.lpos + self.lpp
+		return lpos, data
diff --git a/Demo/sgi/video/LiveVideoOut.py b/Demo/sgi/video/LiveVideoOut.py
new file mode 100755
index 0000000..d9c1138
--- /dev/null
+++ b/Demo/sgi/video/LiveVideoOut.py
@@ -0,0 +1,56 @@
+# Live video output (display video on the screen, presumably from the net)
+
+import gl
+from VFile import Displayer
+
+
+# Video output (displayer) class.
+
+class LiveVideoOut:
+
+	def init(self, wid, xywh, vw, vh):
+		##print 'Init', wid, xywh
+		##print 'video', vw, vw
+		self.vw = vw
+		self.vh = vh
+		self.disp = Displayer().init()
+		info = ('rgb8', vw, vh, 1, 8, 0, 0, 0, 0)
+		self.disp.setinfo(info)
+		self.wid = wid
+		oldwid = gl.winget()
+		gl.winset(wid)
+		self.disp.initcolormap()
+		self.resize(xywh)
+		gl.winset(oldwid)
+		return self
+
+	def resize(self, (x, y, w, h)):
+		oldwid = gl.winget()
+		gl.winset(self.wid)
+		##print 'Resize', x, y, w, h
+		gl.winposition(x, x+w-1, y, y+h-1)
+		gl.reshapeviewport()
+		if w < self.vw or h < self.vh:
+			self.toosmall = 1
+		else:
+			self.disp.xorigin = (w-self.vw)/2
+			self.disp.yorigin = (h-self.vh)/2
+			self.toosmall = 0
+			##print 'VIDEO OFFSET:', \
+			##	self.disp.xorigin, self.disp.yorigin
+		self.disp.clear()
+		gl.winset(oldwid)
+
+	def putnextpacket(self, pos, data):
+		if self.toosmall:
+			return
+		oldwid = gl.winget()
+		gl.winset(self.wid)
+		nline = len(data)/self.vw
+		if nline*self.vw <> len(data):
+			print 'Incorrect-sized video fragment'
+		self.disp.showpartframe(data, None, (0, pos, self.vw, nline))
+		gl.winset(oldwid)
+
+	def close(self):
+		print 'Done video out'
diff --git a/Demo/sgi/video/Vaddcache.py b/Demo/sgi/video/Vaddcache.py
index 191d6ea..d89a78a 100755
--- a/Demo/sgi/video/Vaddcache.py
+++ b/Demo/sgi/video/Vaddcache.py
@@ -10,7 +10,7 @@
 
 # Options:
 #
-# file ... : file(s) to inspect; default film.video
+# file ... : file(s) to modify; default film.video
 
 
 import sys
diff --git a/Demo/sgi/video/Vreceive.py b/Demo/sgi/video/Vreceive.py
new file mode 100755
index 0000000..8d7150e
--- /dev/null
+++ b/Demo/sgi/video/Vreceive.py
@@ -0,0 +1,74 @@
+#!/ufs/guido/bin/sgi/python-405
+
+# Receive live video UDP packets.
+# Usage: Vreceive [port]
+
+import sys
+import struct
+from socket import *
+import select
+import gl, GL, DEVICE
+sys.path.append('/ufs/guido/src/video')
+import LiveVideoOut
+
+PKTMAX = 16*1024
+WIDTH = 400
+HEIGHT = 300
+HOST = ''
+PORT = 5555
+
+def main():
+
+	port = PORT
+	if sys.argv[1:]:
+		port = eval(sys.argv[1])
+
+	width, height = WIDTH, HEIGHT
+
+	gl.foreground()
+	gl.prefsize(width, height)
+	wid = gl.winopen('Vreceive')
+	gl.qdevice(DEVICE.ESCKEY)
+	gl.qdevice(DEVICE.WINSHUT)
+	gl.qdevice(DEVICE.WINQUIT)
+
+	x, y = gl.getorigin()
+	lvo = LiveVideoOut.LiveVideoOut().init(wid, (x, y, width, height), \
+		width, height)
+
+	s = socket(AF_INET, SOCK_DGRAM)
+	s.bind(HOST, port)
+
+	ifdlist = [gl.qgetfd(), s.fileno()]
+	ofdlist = []
+	xfdlist = []
+	timeout = 1.0
+	selectargs = (ifdlist, ofdlist, xfdlist, timeout)
+
+	while 1:
+
+		if gl.qtest():
+			dev, val = gl.qread()
+			if dev in (DEVICE.ESCKEY, \
+				DEVICE.WINSHUT, DEVICE.WINQUIT):
+				break
+			if dev == DEVICE.REDRAW:
+				gl.clear()
+		elif s.avail():
+			data = s.recv(16*1024)
+			pos, w, h = struct.unpack('hhh', data[:6])
+			if (w, h) <> (width, height):
+				x, y = gl.getorigin()
+				y = y + height - h
+				width, height = w, h
+				lvo.close()
+				lvo = LiveVideoOut.LiveVideoOut() \
+				      .init(wid, (x, y, width, height), \
+				            width, height)
+			lvo.putnextpacket(pos, data[6:])
+		else:
+			x = select.select(selectargs)
+
+	lvo.close()
+
+main()
diff --git a/Demo/sgi/video/Vsend.py b/Demo/sgi/video/Vsend.py
new file mode 100755
index 0000000..32385f0
--- /dev/null
+++ b/Demo/sgi/video/Vsend.py
@@ -0,0 +1,94 @@
+#!/ufs/guido/bin/sgi/python-405
+
+# Send live video UDP packets.
+# Usage: Vsend [host [port]]
+
+import sys
+import time
+import struct
+from socket import *
+import gl, GL, DEVICE
+sys.path.append('/ufs/guido/src/video')
+import LiveVideoIn
+import LiveVideoOut
+
+PKTMAX_UCAST = 16*1024 - 6
+PKTMAX_BCAST = 1450
+WIDTH = 400
+HEIGHT = 300
+HOST = '<broadcast>'
+PORT = 5555
+
+def main():
+	if not LiveVideoIn.have_video:
+		print 'Sorry, no video (use python-405 on roos)'
+		sys.exit(1)
+
+	host = HOST
+	port = PORT
+	if sys.argv[1:]:
+		host = sys.argv[1]
+		if sys.argv[2:]:
+			port = eval(sys.argv[2])
+
+	if host == '<broadcast>':
+		pktmax = PKTMAX_BCAST
+	else:
+		pktmax = PKTMAX_UCAST
+
+	gl.foreground()
+	gl.prefsize(WIDTH, HEIGHT)
+	wid = gl.winopen('Vsend')
+	gl.keepaspect(WIDTH, HEIGHT)
+	gl.stepunit(8, 6)
+	gl.winconstraints()
+	gl.qdevice(DEVICE.ESCKEY)
+	gl.qdevice(DEVICE.WINSHUT)
+	gl.qdevice(DEVICE.WINQUIT)
+	width, height = gl.getsize()
+
+	x, y = gl.getorigin()
+	lvo = LiveVideoOut.LiveVideoOut().init(wid, (x, y, width, height), \
+		width, height)
+
+	lvi = LiveVideoIn.LiveVideoIn().init(pktmax, width, height)
+
+	s = socket(AF_INET, SOCK_DGRAM)
+	s.allowbroadcast(1)
+
+	while 1:
+
+		if gl.qtest():
+			dev, val = gl.qread()
+			if dev in (DEVICE.ESCKEY, \
+				DEVICE.WINSHUT, DEVICE.WINQUIT):
+				break
+			if dev == DEVICE.REDRAW:
+				w, h = gl.getsize()
+				x, y = gl.getorigin()
+				if (w, h) <> (width, height):
+					lvi.close()
+					width, height = w, h
+					lvi = LiveVideoIn.LiveVideoIn() \
+						.init(pktmax, width, height)
+					lvo.close()
+					lvo = LiveVideoOut.LiveVideoOut() \
+						.init(wid, \
+						      (x, y, width, height), \
+						      width, height)
+
+		rv = lvi.getnextpacket()
+		if not rv:
+			time.millisleep(10)
+			continue
+
+		pos, data = rv
+		lvo.putnextpacket(pos, data)
+
+		hdr = struct.pack('hhh', pos, width, height)
+		s.sendto(hdr + data, (host, port))
+
+	lvi.close()
+	lvo.close()
+
+main()