| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | # intercom -- use mike and headset to *talk* to a person on another host. | 
					
						
							|  |  |  | # For SGI 4D/35 or Indigo running IRIX 4.0. | 
					
						
							|  |  |  | # Uses 16 bit sampling at 16000 samples/sec, or 32000 bytes/sec, | 
					
						
							|  |  |  | # tranmitted in 32 1000-byte UDP packets.  (In each direction!) | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # usage: | 
					
						
							|  |  |  | #	intercom hostname	- start talking to person on other host | 
					
						
							|  |  |  | #	intercom -r hostname	- called remotely to do the setup | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1991-09-15 21:26:44 +00:00
										 |  |  | from names import * | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | import sys, time, posix, gl, fl, FL, al, AL, getopt, rand | 
					
						
							|  |  |  | from socket import * | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # UDP port numbers used (one for each direction!) | 
					
						
							|  |  |  | PORT1 = 51042 | 
					
						
							|  |  |  | PORT2 = PORT1+1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Figure out the user name | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  | 	user = posix.environ['LOGNAME'] | 
					
						
							|  |  |  | except: | 
					
						
							|  |  |  | 	user = posix.environ['USER'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Debug flags (Implemented as a list; non-empty means debugging is on) | 
					
						
							|  |  |  | debug = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  | 	remote = 0 | 
					
						
							|  |  |  | 	opts, args = getopt.getopt(sys.argv[1:], 'rd') | 
					
						
							|  |  |  | 	for opt, arg in opts: | 
					
						
							| 
									
										
										
										
											1992-03-30 13:30:03 +00:00
										 |  |  | 		if opt == '-r': remote = 1 | 
					
						
							|  |  |  | 		elif opt == '-d': debug.append(opt) | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 	if len(args) <> 1: | 
					
						
							|  |  |  | 		msg = 'usage: intercom [-d] [-r] hostname' | 
					
						
							|  |  |  | 		msg = msg + ' (-r is for internal use only!)\n' | 
					
						
							|  |  |  | 		sys.stderr.write(msg) | 
					
						
							|  |  |  | 		sys.exit(2) | 
					
						
							|  |  |  | 	if remote: | 
					
						
							|  |  |  | 		server(args[0]) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		client(args[0]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def client(hostname): | 
					
						
							|  |  |  | 	print 'client starting' | 
					
						
							|  |  |  | 	cmd = 'rsh ' + hostname + ' "cd ' + AUDIODIR | 
					
						
							|  |  |  | 	cmd = cmd + '; DISPLAY=:0; export DISPLAY' | 
					
						
							| 
									
										
										
										
											1991-12-24 13:55:16 +00:00
										 |  |  | 	cmd = cmd + '; ' + PYTHON + ' intercom.py -r ' | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 	for flag in debug: cmd = cmd + flag + ' ' | 
					
						
							|  |  |  | 	cmd = cmd + gethostname() | 
					
						
							|  |  |  | 	cmd = cmd + '"' | 
					
						
							| 
									
										
										
										
											1991-12-24 13:55:16 +00:00
										 |  |  | 	if debug: print cmd | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 	pipe = posix.popen(cmd, 'r') | 
					
						
							|  |  |  | 	ack = 0 | 
					
						
							|  |  |  | 	nak = 0 | 
					
						
							|  |  |  | 	while 1: | 
					
						
							|  |  |  | 		line = pipe.readline() | 
					
						
							|  |  |  | 		if not line: break | 
					
						
							|  |  |  | 		sys.stdout.write('remote: ' + line) | 
					
						
							| 
									
										
										
										
											1992-03-30 13:30:03 +00:00
										 |  |  | 		if line == 'NAK\n': | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 			nak = 1 | 
					
						
							|  |  |  | 			break | 
					
						
							| 
									
										
										
										
											1992-03-30 13:30:03 +00:00
										 |  |  | 		elif line == 'ACK\n': | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 			ack = 1 | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 	if nak: | 
					
						
							|  |  |  | 		print 'Remote user doesn\'t want to talk to you.' | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	if not ack: | 
					
						
							|  |  |  | 		print 'No acknowledgement (remote side crashed?).' | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	print 'Ready...' | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	s = socket(AF_INET, SOCK_DGRAM) | 
					
						
							|  |  |  | 	s.bind('', PORT2) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	otheraddr = gethostbyname(hostname), PORT1 | 
					
						
							|  |  |  | 	try: | 
					
						
							| 
									
										
										
										
											1992-04-17 16:32:53 +00:00
										 |  |  | 		try: | 
					
						
							|  |  |  | 			ioloop(s, otheraddr) | 
					
						
							|  |  |  | 		except KeyboardInterrupt: | 
					
						
							|  |  |  | 			log('client got intr') | 
					
						
							|  |  |  | 		except error: | 
					
						
							|  |  |  | 			log('client got error') | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 	finally: | 
					
						
							|  |  |  | 		s.sendto('', otheraddr) | 
					
						
							|  |  |  | 		log('client finished sending empty packet to server') | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	log('client exit') | 
					
						
							|  |  |  | 	print 'Done.' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def server(hostname): | 
					
						
							|  |  |  | 	print 'server starting' | 
					
						
							|  |  |  | 	sys.stdout.flush() | 
					
						
							|  |  |  | 	#  | 
					
						
							|  |  |  | 	if not remotedialog(): | 
					
						
							|  |  |  | 		print 'NAK' | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	print 'ACK' | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	s = socket(AF_INET, SOCK_DGRAM) | 
					
						
							|  |  |  | 	s.bind('', PORT1) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	# Close std{in,out,err} so rsh will exit; reopen them as dummies | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	sys.stdin.close() | 
					
						
							|  |  |  | 	sys.stdin = open('/dev/null', 'r') | 
					
						
							|  |  |  | 	sys.stdout.close() | 
					
						
							|  |  |  | 	sys.stdout = open('/dev/null', 'w') | 
					
						
							|  |  |  | 	sys.stderr.close() | 
					
						
							|  |  |  | 	if debug: | 
					
						
							|  |  |  | 		sys.stderr = open('/tmp/intercom.err', 'a') | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		sys.stderr = open('/dev/null', 'w') | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	ioloop(s, (gethostbyname(hostname), PORT2)) | 
					
						
							|  |  |  | 	log('server exit') | 
					
						
							|  |  |  | 	sys.exit(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def remotedialog(): | 
					
						
							|  |  |  | 	gl.foreground() | 
					
						
							|  |  |  | 	gl.ringbell() | 
					
						
							|  |  |  | 	m1 = user + ' wants to talk to you over the audio channel.' | 
					
						
							|  |  |  | 	m2 = 'If it\'s OK, put on your headset and click Yes.' | 
					
						
							|  |  |  | 	m3 = 'If you\'re too busy, click No.' | 
					
						
							|  |  |  | 	return fl.show_question(m1, m2, m3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def ioloop(s, otheraddr): | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	dev = AL.DEFAULT_DEVICE | 
					
						
							|  |  |  | 	params = al.queryparams(dev) | 
					
						
							|  |  |  | 	al.getparams(dev, params) | 
					
						
							|  |  |  | 	time.sleep(1) | 
					
						
							|  |  |  | 	saveparams = params[:] | 
					
						
							|  |  |  | 	for i in range(0, len(params), 2): | 
					
						
							|  |  |  | 		if params[i] in (AL.INPUT_RATE, AL.OUTPUT_RATE): | 
					
						
							|  |  |  | 			params[i+1] = AL.RATE_16000 | 
					
						
							| 
									
										
										
										
											1992-03-30 13:30:03 +00:00
										 |  |  | 		elif params[i] == AL.INPUT_SOURCE: | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 			params[i+1] = AL.INPUT_MIC | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		al.setparams(dev, params) | 
					
						
							|  |  |  | 		ioloop1(s, otheraddr) | 
					
						
							|  |  |  | 	finally: | 
					
						
							|  |  |  | 		al.setparams(dev, saveparams) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def ioloop1(s, otheraddr): | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	# Watch out! data is in bytes, but the port counts in samples, | 
					
						
							|  |  |  | 	# which are two bytes each (for 16-bit samples). | 
					
						
							|  |  |  | 	# Luckily, we use mono, else it would be worse (2 samples/frame...) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	SAMPSPERBUF = 500 | 
					
						
							|  |  |  | 	BYTESPERSAMP = 2 # AL.SAMPLE_16 | 
					
						
							|  |  |  | 	BUFSIZE = BYTESPERSAMP*SAMPSPERBUF | 
					
						
							|  |  |  | 	QSIZE = 4*SAMPSPERBUF | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	config = al.newconfig() | 
					
						
							|  |  |  | 	config.setqueuesize(QSIZE) | 
					
						
							|  |  |  | 	config.setwidth(AL.SAMPLE_16) | 
					
						
							|  |  |  | 	config.setchannels(AL.MONO) | 
					
						
							|  |  |  | 	# | 
					
						
							|  |  |  | 	pid = posix.fork() | 
					
						
							|  |  |  | 	if pid: | 
					
						
							|  |  |  | 		# Parent -- speaker/headphones handler | 
					
						
							|  |  |  | 		log('parent started') | 
					
						
							|  |  |  | 		spkr = al.openport('spkr', 'w', config) | 
					
						
							|  |  |  | 		while 1: | 
					
						
							|  |  |  | 			data = s.recv(BUFSIZE) | 
					
						
							| 
									
										
										
										
											1992-03-30 13:30:03 +00:00
										 |  |  | 			if len(data) == 0: | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 				# EOF packet | 
					
						
							|  |  |  | 				log('parent got empty packet; killing child') | 
					
						
							|  |  |  | 				posix.kill(pid, 15) | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			# Discard whole packet if we are too much behind | 
					
						
							|  |  |  | 			if spkr.getfillable() > len(data) / BYTESPERSAMP: | 
					
						
							|  |  |  | 				if len(debug) >= 2: | 
					
						
							|  |  |  | 					log('parent Q full; dropping packet') | 
					
						
							|  |  |  | 				spkr.writesamps(data) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		# Child -- microphone handler | 
					
						
							|  |  |  | 		log('child started') | 
					
						
							|  |  |  | 		try: | 
					
						
							| 
									
										
										
										
											1992-12-14 15:05:16 +00:00
										 |  |  | 		    try: | 
					
						
							|  |  |  | 			    mike = al.openport('mike', 'r', config) | 
					
						
							|  |  |  | 			    # Sleep a while to let the other side get started | 
					
						
							|  |  |  | 			    time.sleep(1) | 
					
						
							|  |  |  | 			    # Drain the queue before starting to read | 
					
						
							|  |  |  | 			    data = mike.readsamps(mike.getfilled()) | 
					
						
							|  |  |  | 			    # Loop, sending packets from the mike to the net | 
					
						
							|  |  |  | 			    while 1: | 
					
						
							|  |  |  | 				    data = mike.readsamps(SAMPSPERBUF) | 
					
						
							|  |  |  | 				    s.sendto(data, otheraddr) | 
					
						
							|  |  |  | 		    except KeyboardInterrupt: | 
					
						
							|  |  |  | 			    log('child got interrupt; exiting') | 
					
						
							|  |  |  | 			    posix._exit(0) | 
					
						
							|  |  |  | 		    except error: | 
					
						
							|  |  |  | 			    log('child got error; exiting') | 
					
						
							|  |  |  | 			    posix._exit(1) | 
					
						
							| 
									
										
										
										
											1991-09-15 21:05:15 +00:00
										 |  |  | 		finally: | 
					
						
							|  |  |  | 			log('child got unexpected error; leaving w/ traceback') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def log(msg): | 
					
						
							|  |  |  | 	if not debug: return | 
					
						
							|  |  |  | 	if type(msg) <> type(''): | 
					
						
							|  |  |  | 		msg = `msg` | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	f = open('/tmp/intercom.log', 'a') | 
					
						
							|  |  |  | 	f.write(`sys.argv` + ' ' + `posix.getpid()` + ': ' + msg + '\n') | 
					
						
							|  |  |  | 	f.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | main() |