Initial revision
diff --git a/Demo/sgi/cd/sendcd.py b/Demo/sgi/cd/sendcd.py
new file mode 100755
index 0000000..10b0faf
--- /dev/null
+++ b/Demo/sgi/cd/sendcd.py
@@ -0,0 +1,143 @@
+# Read CD audio data from the SCSI CD player and send it as UDP
+# packets to "readcd.py" on another host.
+# Option:
+# "-l" lists track info and quits.
+# "-s" displays status and quits.
+
+import cd
+import sys
+from socket import *
+import getopt
+
+HOST = 'voorn.cwi.nl' # The host where readcd.py is run
+PORT = 50505 # Must match the port in readcd.py
+
+def main():
+	try:
+		optlist, args = getopt.getopt(sys.argv[1:], 'ls')
+	except getopt.error, msg:
+		sys.stderr.write(msg + '\n')
+		sys.exit(2)
+
+	player = cd.open()
+	prstatus(player)
+	size = player.bestreadsize()
+
+	if optlist:
+		for opt, arg in optlist:
+			if opt == '-l':
+				prtrackinfo(player)
+			elif opt == '-s':
+				prstatus(player)
+		return
+
+	sys.stdout.write('waiting for socket... ')
+	sys.stdout.flush()
+	port = socket(AF_INET, SOCK_DGRAM)
+	port.connect(HOST, PORT)
+	print 'socket connected'
+
+	parser = cd.createparser()
+	parser.setcallback(0, audiocallback, port)
+	parser.setcallback(1, pnumcallback, player)
+	parser.setcallback(2, indexcallback, None)
+	## 3 = ptime: too many calls
+	## 4 = atime: too many calls
+	parser.setcallback(5, catalogcallback, None)
+	parser.setcallback(6, identcallback, None)
+	parser.setcallback(7, controlcallback, None)
+
+	if len(args) >= 2:
+		if len(args) >= 3:
+			[min, sec, frame] = args[:3]
+		else:
+			[min, sec] = args
+			frame = 0
+		min, sec, frame = eval(min), eval(sec), eval(frame)
+		print 'Seek to', triple(min, sec, frame)
+		dummy = player.seek(min, sec, frame)
+	elif len(args) == 1:
+		track = eval(args[0])
+		print 'Seek to track', track
+		dummy = player.seektrack(track)
+	else:
+		min, sec, frame = player.getstatus()[5:8]
+		print 'Try to seek back to', triple(min, sec, frame)
+		try:
+			player.seek(min, sec, frame)
+		except RuntimeError:
+			print 'Seek failed'
+
+	try:
+		while 1:
+			frames = player.readda(size)
+			if frames == '':
+				print 'END OF CD'
+				break
+			parser.parseframe(frames)
+	except KeyboardInterrupt:
+		print '[Interrupted]'
+		pass
+
+def prtrackinfo(player):
+	info = []
+	while 1:
+		try:
+			info.append(player.gettrackinfo(len(info) + 1))
+		except RuntimeError:
+			break
+	for i in range(len(info)):
+		start_min, start_sec, start_frame, \
+			total_min, total_sec, total_frame = info[i]
+		print 'Track', zfill(i+1), \
+			triple(start_min, start_sec, start_frame), \
+			triple(total_min, total_sec, total_frame)
+
+def audiocallback(port, type, data):
+##	sys.stdout.write('#')
+##	sys.stdout.flush()
+	port.send(data)
+
+def pnumcallback(player, type, data):
+	print 'pnum =', `data`
+	prstatus(player)
+
+def indexcallback(arg, type, data):
+	print 'index =', `data`
+
+def catalogcallback(arg, type, data):
+	print 'catalog =', `data`
+
+def identcallback(arg, type, data):
+	print 'ident =', `data`
+
+def controlcallback(arg, type, data):
+	print 'control =', `data`
+
+statedict = ['ERROR', 'NODISK', 'READY', 'PLAYING', 'PAUSED', 'STILL']
+
+def prstatus(player):
+	state, track, min, sec, frame, abs_min, abs_sec, abs_frame, \
+		total_min, total_sec, total_frame, first, last, scsi_audio, \
+		cur_block, dum1, dum2, dum3 = player.getstatus()
+	print 'Status:',
+	if 0 <= state < len(statedict):
+		print statedict[state]
+	else:
+		print state
+	print 'Track: ', track
+	print 'Time:  ', triple(min, sec, frame)
+	print 'Abs:   ', triple(abs_min, abs_sec, abs_frame)
+	print 'Total: ', triple(total_min, total_sec, total_frame)
+	print 'First: ', first
+	print 'Last:  ', last
+	print 'SCSI:  ', scsi_audio
+	print 'Block: ', cur_block
+	print 'Future:', (dum1, dum2, dum3)
+
+def triple(a, b, c):
+	return zfill(a) + ':' + zfill(b) + ':' + zfill(c)
+
+def zfill(n):
+	s = `n`
+	return '0' * (2 - len(s)) + s