1 # intercom -- use mike and headset to *talk* to a person on another host.
2 # For SGI 4D/35 or Indigo running IRIX 4.0.
3 # Uses 16 bit sampling at 16000 samples/sec, or 32000 bytes/sec,
4 # tranmitted in 32 1000-byte UDP packets. (In each direction!)
7 # intercom hostname - start talking to person on other host
8 # intercom -r hostname - called remotely to do the setup
11 import sys
, time
, posix
, gl
, fl
, FL
, al
, AL
, getopt
, rand
14 # UDP port numbers used (one for each direction!)
18 # Figure out the user name
20 user
= posix
.environ
['LOGNAME']
22 user
= posix
.environ
['USER']
24 # Debug flags (Implemented as a list; non-empty means debugging is on)
29 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'rd')
31 if opt
== '-r': remote
= 1
32 elif opt
== '-d': debug
.append(opt
)
34 msg
= 'usage: intercom [-d] [-r] hostname'
35 msg
= msg
+ ' (-r is for internal use only!)\n'
44 print 'client starting'
45 cmd
= 'rsh ' + hostname
+ ' "cd ' + AUDIODIR
46 cmd
= cmd
+ '; DISPLAY=:0; export DISPLAY'
47 cmd
= cmd
+ '; ' + PYTHON
+ ' intercom.py -r '
48 for flag
in debug
: cmd
= cmd
+ flag
+ ' '
49 cmd
= cmd
+ gethostname()
52 pipe
= posix
.popen(cmd
, 'r')
56 line
= pipe
.readline()
58 sys
.stdout
.write('remote: ' + line
)
66 print 'Remote user doesn\'t want to talk to you.'
69 print 'No acknowledgement (remote side crashed?).'
74 s
= socket(AF_INET
, SOCK_DGRAM
)
77 otheraddr
= gethostbyname(hostname
), PORT1
81 except KeyboardInterrupt:
82 log('client got intr')
84 log('client got error')
86 s
.sendto('', otheraddr
)
87 log('client finished sending empty packet to server')
93 print 'server starting'
96 if not remotedialog():
102 s
= socket(AF_INET
, SOCK_DGRAM
)
105 # Close std{in,out,err} so rsh will exit; reopen them as dummies
108 sys
.stdin
= open('/dev/null', 'r')
110 sys
.stdout
= open('/dev/null', 'w')
113 sys
.stderr
= open('/tmp/intercom.err', 'a')
115 sys
.stderr
= open('/dev/null', 'w')
117 ioloop(s
, (gethostbyname(hostname
), PORT2
))
124 m1
= user
+ ' wants to talk to you over the audio channel.'
125 m2
= 'If it\'s OK, put on your headset and click Yes.'
126 m3
= 'If you\'re too busy, click No.'
127 return fl
.show_question(m1
, m2
, m3
)
129 def ioloop(s
, otheraddr
):
131 dev
= AL
.DEFAULT_DEVICE
132 params
= al
.queryparams(dev
)
133 al
.getparams(dev
, params
)
135 saveparams
= params
[:]
136 for i
in range(0, len(params
), 2):
137 if params
[i
] in (AL
.INPUT_RATE
, AL
.OUTPUT_RATE
):
138 params
[i
+1] = AL
.RATE_16000
139 elif params
[i
] == AL
.INPUT_SOURCE
:
140 params
[i
+1] = AL
.INPUT_MIC
142 al
.setparams(dev
, params
)
143 ioloop1(s
, otheraddr
)
145 al
.setparams(dev
, saveparams
)
147 def ioloop1(s
, otheraddr
):
149 # Watch out! data is in bytes, but the port counts in samples,
150 # which are two bytes each (for 16-bit samples).
151 # Luckily, we use mono, else it would be worse (2 samples/frame...)
154 BYTESPERSAMP
= 2 # AL.SAMPLE_16
155 BUFSIZE
= BYTESPERSAMP
*SAMPSPERBUF
156 QSIZE
= 4*SAMPSPERBUF
158 config
= al
.newconfig()
159 config
.setqueuesize(QSIZE
)
160 config
.setwidth(AL
.SAMPLE_16
)
161 config
.setchannels(AL
.MONO
)
165 # Parent -- speaker/headphones handler
166 log('parent started')
167 spkr
= al
.openport('spkr', 'w', config
)
169 data
= s
.recv(BUFSIZE
)
172 log('parent got empty packet; killing child')
175 # Discard whole packet if we are too much behind
176 if spkr
.getfillable() > len(data
) / BYTESPERSAMP
:
178 log('parent Q full; dropping packet')
179 spkr
.writesamps(data
)
181 # Child -- microphone handler
185 mike
= al
.openport('mike', 'r', config
)
186 # Sleep a while to let the other side get started
188 # Drain the queue before starting to read
189 data
= mike
.readsamps(mike
.getfilled())
190 # Loop, sending packets from the mike to the net
192 data
= mike
.readsamps(SAMPSPERBUF
)
193 s
.sendto(data
, otheraddr
)
194 except KeyboardInterrupt:
195 log('child got interrupt; exiting')
198 log('child got error; exiting')
201 log('child got unexpected error; leaving w/ traceback')
205 if type(msg
) <> type(''):
208 f
= open('/tmp/intercom.log', 'a')
209 f
.write(`sys
.argv`
+ ' ' + `posix
.getpid()`
+ ': ' + msg
+ '\n')