blob: ec59f22f5649d3142408387cf3d13d42e0ee0797 [file] [log] [blame]
Guido van Rossumf06ee5f1996-11-27 19:52:01 +00001#! /usr/bin/env python
Guido van Rossumb7e3cc11993-05-06 16:06:44 +00002
Guido van Rossum9f42f4f1993-05-10 15:07:20 +00003# Video bag of tricks: record video(+audio) in various formats and modes
Guido van Rossumb7e3cc11993-05-06 16:06:44 +00004
Guido van Rossumc5a14331993-05-07 11:20:07 +00005# XXX To do:
6# - audio
Guido van Rossumc5a14331993-05-07 11:20:07 +00007# - improve user interface
8# - help button?
9# - command line options to set initial settings
10# - save settings in a file
11# - ...?
Guido van Rossumbc6d3c31993-05-07 09:37:42 +000012
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000013import sys
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000014import time
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000015import getopt
16import string
17import os
Guido van Rossumc5a14331993-05-07 11:20:07 +000018sts = os.system('makemap') # Must be before "import fl" to work
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000019import sgi
20import gl
21import GL
22import DEVICE
23import fl
24import FL
25import flp
26import watchcursor
27import sv
28import SV
29import VFile
30import VGrabber
31import imageop
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000032sys.path.append('/ufs/jack/src/av/vcr')
Guido van Rossumf6d80321993-06-10 13:40:51 +000033import VCR
Jack Jansen78991fd1993-07-23 11:59:25 +000034try:
35 import cl
36 import CL
37except ImportError:
38 cl = None
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000039
40ARROW = 0
41WATCH = 1
42watchcursor.defwatch(WATCH)
43
44def main():
Guido van Rossumc5a14331993-05-07 11:20:07 +000045## fl.set_graphics_mode(0, 1)
Guido van Rossum21a3ff91993-12-17 15:11:41 +000046 vb = VideoBagOfTricks()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000047 while 1:
48 dummy = fl.do_forms()
49 [dummy]
50
51StopCapture = 'StopCapture'
52
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000053VideoFormatLabels = ['Video off', 'rgb8', 'grey8', 'grey4', 'grey2', \
Jack Jansen78991fd1993-07-23 11:59:25 +000054 'grey2 dith', 'mono dith', 'mono thresh', 'rgb24', 'rgb24-jpeg', \
55 'compress']
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000056VideoFormats = ['', 'rgb8', 'grey', 'grey4', 'grey2', \
Jack Jansen78991fd1993-07-23 11:59:25 +000057 'grey2', 'mono', 'mono', 'rgb', 'jpeg', 'compress']
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000058
59VideoModeLabels = ['Continuous', 'Burst', 'Single frame', 'VCR sync']
60[VM_CONT, VM_BURST, VM_SINGLE, VM_VCR] = range(1, 5)
61
62AudioFormatLabels = ['Audio off', \
63 '16 bit mono', '16 bit stereo', '8 bit mono', '8 bit stereo']
64[A_OFF, A_16_MONO, A_16_STEREO, A_8_MONO, A_8_STEREO] = range(1, 6)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000065
Jack Jansen672754a1993-06-08 12:52:41 +000066VcrSpeedLabels = ['normal', '1/3', '1/5', '1/10', '1/30', 'single-step']
67VcrSpeeds = [None, 5, 4, 3, 2, 1, 0]
68
69RgbSizeLabels = ['full', 'quarter', 'sixteenth']
70
Jack Jansen78991fd1993-07-23 11:59:25 +000071# init file stuff:
72if os.environ.has_key('HOME'):
73 HOME=os.environ['HOME']
74else:
75 HOME='.'
76VB_INIT_FILE=HOME + '/.Vb_init'
77
78VB_INIT_KEYS=['vfile', 'vmode', 'mono_thresh', 'vformat', 'comp_scheme', \
79 'rgb24_size', 'afile', 'aformat']
80
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000081class VideoBagOfTricks:
82
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000083 # Init/close stuff
84
Guido van Rossum21a3ff91993-12-17 15:11:41 +000085 def __init__(self):
Jack Jansen672754a1993-06-08 12:52:41 +000086 self.window = None
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000087 formdef = flp.parse_form('VbForm', 'form')
88 flp.create_full_form(self, formdef)
89 self.setdefaults()
Jack Jansen78991fd1993-07-23 11:59:25 +000090 if self.vmode <> VM_CONT:
91 self.g_cont.hide_object()
92 if self.vmode <> VM_BURST:
93 self.g_burst.hide_object()
94 if self.vmode <> VM_SINGLE:
95 self.g_single.hide_object()
96 if self.vmode <> VM_VCR:
97 self.g_vcr.hide_object()
98 if self.vformat <> 'compress':
99 self.g_compress.hide_object()
100
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000101 self.openvideo()
102 self.makewindow()
103 self.bindvideo()
Jack Jansen78991fd1993-07-23 11:59:25 +0000104 if self.use_24:
105 self.optfullsizewindow()
Guido van Rossumc5a14331993-05-07 11:20:07 +0000106 self.showform()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000107 fl.set_event_call_back(self.do_event)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000108
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000109 def close(self):
110 self.close_video()
111 self.close_audio()
Jack Jansen78991fd1993-07-23 11:59:25 +0000112 self.savedefaults()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000113 raise SystemExit, 0
114
Guido van Rossumc5a14331993-05-07 11:20:07 +0000115 def showform(self):
116 # Get position of video window
117 gl.winset(self.window)
118 x, y = gl.getorigin()
119 width, height = gl.getsize()
120 # Calculate position of form window
121 x1 = x + width + 10
122 x2 = x1 + int(self.form.w) - 1
123 y2 = y + height - 1
124 y1 = y2 - int(self.form.h) + 1
125 # Position and show form window
126 gl.prefposition(x1, x2, y1, y2)
Guido van Rossum43df8621993-06-11 15:48:39 +0000127 self.form.show_form(FL.PLACE_FREE, FL.TRUE, 'Vb Control')
Guido van Rossumc5a14331993-05-07 11:20:07 +0000128
Jack Jansen78991fd1993-07-23 11:59:25 +0000129 def getdefaultdefaults(self):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000130 # Video defaults
131 self.vfile = 'film.video'
132 self.vmode = VM_CONT
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000133 self.mono_thresh = 128
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000134 self.vformat = 'rgb8'
Jack Jansen78991fd1993-07-23 11:59:25 +0000135 self.comp_scheme = 'Uncompressed'
136 self.rgb24_size = 1
137 # Missing: drop, rate, maxmem, nframes, rate, vcrspeed
138 # Audio defaults:
139 self.afile = 'film.aiff'
140 self.aformat = A_OFF
141
142 def getdefaults(self):
143 self.getdefaultdefaults()
144 # XXXX Read defaults file and override.
145 try:
146 fp = open(VB_INIT_FILE, 'r')
147 except IOError:
148 print 'Vb: no init file'
149 self.initcont = {}
150 return
151 data = fp.read(1000000)
152 try:
153 self.initcont = eval(data)
154 except:
155 print 'Vb: Ill-formatted init file'
156 self.initcont = {}
157 for k in self.initcont.keys():
158 if hasattr(self, k):
159 setattr(self, k, self.initcont[k])
160
161 def savedefaults(self):
162 newdb = {}
163 for k in VB_INIT_KEYS:
164 newdb[k] = getattr(self, k)
165 if newdb <> self.initcont:
166 try:
167 fp = open(VB_INIT_FILE, 'w')
168 except IOError:
169 print 'Vb: Cannot create', VB_INIT_FILE
170 return
171 fp.write(`newdb`)
172 fp.close()
173
174 def setdefaults(self):
175 self.getdefaults()
176 self.vcr = None
177 self.vout = None
178 self.capturing = 0
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000179 self.c_vformat.clear_choice()
180 for label in VideoFormatLabels:
181 self.c_vformat.addto_choice(label)
182 self.c_vformat.set_choice(1 + VideoFormats.index(self.vformat))
183 self.c_vmode.clear_choice()
184 for label in VideoModeLabels:
185 self.c_vmode.addto_choice(label)
186 self.c_vmode.set_choice(self.vmode)
187 self.get_vformat()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000188 self.b_drop.set_button(1)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000189 self.in_rate.set_input('2')
190 self.in_maxmem.set_input('1.0')
191 self.in_nframes.set_input('0')
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000192 self.in_nframes_vcr.set_input('1')
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000193 self.in_rate_vcr.set_input('1')
Jack Jansen672754a1993-06-08 12:52:41 +0000194 self.c_vcrspeed.clear_choice()
195 for label in VcrSpeedLabels:
196 self.c_vcrspeed.addto_choice(label)
197 self.c_vcrspeed.set_choice(4)
198 self.c_rgb24_size.clear_choice()
199 for label in RgbSizeLabels:
200 self.c_rgb24_size.addto_choice(label)
Jack Jansen78991fd1993-07-23 11:59:25 +0000201 self.c_rgb24_size.set_choice(self.rgb24_size)
202 if cl:
203 algs = cl.QueryAlgorithms(CL.VIDEO)
204 self.all_comp_schemes = []
205 for i in range(0, len(algs), 2):
206 if algs[i+1] in (CL.COMPRESSOR, CL.CODEC):
207 self.all_comp_schemes.append(algs[i])
208 self.c_cformat.clear_choice()
209 for label in self.all_comp_schemes:
210 self.c_cformat.addto_choice(label)
211 i = self.all_comp_schemes.index(self.comp_scheme)
212 self.c_cformat.set_choice(i+1)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000213 # Audio defaults
214 self.aout = None
215 self.aport = None
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000216 self.c_aformat.clear_choice()
217 for label in AudioFormatLabels:
218 self.c_aformat.addto_choice(label)
219 self.c_aformat.set_choice(self.aformat)
220 self.get_aformat()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000221
222 def openvideo(self):
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000223 try:
224 self.video = sv.OpenVideo()
225 except sv.error, msg:
226 print 'Error opening video:', msg
227 self.video = None
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000228 param = [SV.BROADCAST, SV.PAL]
229 if self.video: self.video.GetParam(param)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000230 if param[1] == SV.PAL:
231 x = SV.PAL_XMAX
232 y = SV.PAL_YMAX
233 elif param[1] == SV.NTSC:
234 x = SV.NTSC_XMAX
235 y = SV.NTSC_YMAX
236 else:
237 print 'Unknown video standard:', param[1]
238 sys.exit(1)
239 self.maxx, self.maxy = x, y
Guido van Rossum43df8621993-06-11 15:48:39 +0000240 self.curx = 256
241 self.cury = 256*3/4
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000242
243 def makewindow(self):
244 x, y = self.maxx, self.maxy
245 gl.foreground()
246 gl.maxsize(x, y)
247 gl.keepaspect(x, y)
248 gl.stepunit(8, 6)
Guido van Rossum43df8621993-06-11 15:48:39 +0000249 width = self.curx
250 height = self.cury
251 if width and height:
252 # Place the window at (150, 150) from top left
253 # (the video board likes this location...)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000254 x1 = 150
Guido van Rossum43df8621993-06-11 15:48:39 +0000255 x2 = x1+width-1
256 SCRHEIGHT = 768
257 y2 = SCRHEIGHT-1-150
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000258 y1 = y2-height+1
259 gl.prefposition(x1, x2, y1, y2)
Guido van Rossum43df8621993-06-11 15:48:39 +0000260 self.window = gl.winopen('Vb video')
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000261 self.settitle()
262 if width:
263 gl.maxsize(x, y)
264 gl.keepaspect(x, y)
265 gl.stepunit(8, 6)
266 gl.winconstraints()
267 gl.qdevice(DEVICE.LEFTMOUSE)
268 gl.qdevice(DEVICE.WINQUIT)
269 gl.qdevice(DEVICE.WINSHUT)
270
Jack Jansen672754a1993-06-08 12:52:41 +0000271 def optfullsizewindow(self):
272 if not self.window:
273 return
274 gl.winset(self.window)
Guido van Rossum43df8621993-06-11 15:48:39 +0000275 if self.use_24:
276 x, y = self.maxx, self.maxy
277 else:
278 x, y = self.curx, self.cury
Guido van Rossum2055ee81993-06-11 14:13:13 +0000279 left, bottom = gl.getorigin()
280 width, height = gl.getsize()
281 bottom = bottom+height-y
282 gl.prefposition(left, left+x-1, bottom, bottom+y-1)
Jack Jansen672754a1993-06-08 12:52:41 +0000283 gl.winconstraints()
Guido van Rossum43df8621993-06-11 15:48:39 +0000284 if not self.use_24:
285 gl.keepaspect(x, y)
286 gl.stepunit(8, 6)
287 gl.maxsize(self.maxx, self.maxy)
288 gl.winconstraints()
Jack Jansen672754a1993-06-08 12:52:41 +0000289 self.bindvideo()
290
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000291 def bindvideo(self):
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000292 if not self.video: return
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000293 x, y = gl.getsize()
Guido van Rossum43df8621993-06-11 15:48:39 +0000294 if not self.use_24:
295 self.curx, self.cury = x, y
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000296 self.video.SetSize(x, y)
297 drop = self.b_drop.get_button()
298 if drop:
299 param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF]
300 else:
301 param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON]
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000302 if self.rgb:
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000303 param = param+[SV.COLOR, SV.DEFAULT_COLOR, \
304 SV.DITHER, 1, \
305 SV.INPUT_BYPASS, 0]
306 else:
307 param = param+[SV.COLOR, SV.MONO, SV.DITHER, 0, \
308 SV.INPUT_BYPASS, 1]
309 self.video.BindGLWindow(self.window, SV.IN_REPLACE)
310 self.video.SetParam(param)
311
312 def rebindvideo(self):
313 gl.winset(self.window)
314 self.bindvideo()
315
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000316 def reset(self):
317 self.close_video()
318 self.close_audio()
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000319 if self.vcr:
320 try:
321 ok = self.vcr.still()
322 except VCR.error:
323 pass
324 self.vcr = None
325 self.b_capture.set_button(0)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000326
327 # Event handler (catches resize of video window)
328
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000329 def do_event(self, dev, val):
330 #print 'Event:', dev, val
331 if dev in (DEVICE.WINSHUT, DEVICE.WINQUIT):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000332 self.close()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000333 if dev == DEVICE.REDRAW and val == self.window:
334 self.rebindvideo()
335 self.settitle()
336
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000337 # Video controls: format, mode, file
338
339 def cb_vformat(self, *args):
340 self.reset()
341 self.get_vformat()
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000342 if self.mono_use_thresh:
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000343 s = `self.mono_thresh`
344 s = fl.show_input('Please enter mono threshold', s)
345 if s:
346 try:
347 self.mono_thresh = string.atoi(s)
348 except string.atoi_error:
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000349 fl.show_message('Bad input, using', \
350 `self.mono_thresh`, '')
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000351 self.rebindvideo()
352
Jack Jansen78991fd1993-07-23 11:59:25 +0000353 def cb_cformat(self, *args):
354 i = self.c_cformat.get_choice()
355 self.comp_scheme = self.all_comp_schemes[i-1]
356
357
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000358 def cb_vmode(self, *args):
Guido van Rossumc17c84f1993-05-10 15:45:49 +0000359 if self.vcr:
360 self.vcr = None
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000361 self.vmode = self.c_vmode.get_choice()
362 self.form.freeze_form()
363 self.g_cont.hide_object()
364 self.g_burst.hide_object()
365 self.g_single.hide_object()
366 self.g_vcr.hide_object()
367 if self.vmode == VM_CONT:
368 self.g_cont.show_object()
369 elif self.vmode == VM_BURST:
370 self.g_burst.show_object()
371 elif self.vmode == VM_SINGLE:
372 self.g_single.show_object()
373 elif self.vmode == VM_VCR:
374 self.g_vcr.show_object()
375 self.form.unfreeze_form()
376
377 def cb_vfile(self, *args):
378 filename = self.vfile
379 hd, tl = os.path.split(filename)
380 filename = fl.file_selector('Video save file:', hd, '', tl)
381 if filename:
382 self.reset()
383 hd, tl = os.path.split(filename)
384 if hd == os.getcwd():
385 filename = tl
386 self.vfile = filename
387
388 # Video mode specific video controls
389
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000390 def cb_rate(self, *args):
391 pass
392
393 def cb_drop(self, *args):
394 self.rebindvideo()
395
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000396 def cb_maxmem(self, *args):
397 pass
398
399 def cb_nframes(self, *args):
400 pass
401
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000402 def cb_fps(self, *args):
403 pass
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000404
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000405 def cb_nframes_vcr(self, *args):
406 pass
407
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000408 def cb_rate_vcr(self, *args):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000409 pass
410
Jack Jansen672754a1993-06-08 12:52:41 +0000411 def cb_vcrspeed(self, *args):
412 pass
413
414 def cb_rgb24_size(self, *args):
415 i = self.c_rgb24_size.get_choice()
416 if i:
417 self.rgb24_size = i
418
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000419 # Audio controls: format, file
420
421 def cb_aformat(self, *args):
422 self.get_aformat()
423
424 def cb_afile(self, *args):
425 filename = self.afile
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000426 hd, tl = os.path.split(filename)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000427 filename = fl.file_selector('Audio save file:', hd, '', tl)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000428 if filename:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000429 self.reset()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000430 hd, tl = os.path.split(filename)
431 if hd == os.getcwd():
432 filename = tl
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000433 self.afile = filename
434
435 # General controls: capture, reset, play, quit
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000436
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000437 def cb_capture(self, *args):
Guido van Rossumc5a14331993-05-07 11:20:07 +0000438 if self.capturing:
439 raise StopCapture
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000440 if not self.b_capture.get_button():
441 return
442 if not self.video or not self.vformat:
443 gl.ringbell()
444 return
445 if self.vmode == VM_CONT:
446 self.cont_capture()
447 elif self.vmode == VM_BURST:
448 self.burst_capture()
449 elif self.vmode == VM_SINGLE:
Jack Jansen672754a1993-06-08 12:52:41 +0000450 self.single_capture(None, None)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000451 elif self.vmode == VM_VCR:
452 self.vcr_capture()
453
454 def cb_reset(self, *args):
455 self.reset()
Guido van Rossumc5a14331993-05-07 11:20:07 +0000456
457 def cb_play(self, *args):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000458 self.reset()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000459 sts = os.system('Vplay -q ' + self.vfile + ' &')
Guido van Rossumc5a14331993-05-07 11:20:07 +0000460
461 def cb_quit(self, *args):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000462 self.close()
463
464 # Capture routines
Guido van Rossumc5a14331993-05-07 11:20:07 +0000465
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000466 def burst_capture(self):
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000467 self.setwatch()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000468 gl.winset(self.window)
469 x, y = gl.getsize()
Jack Jansen672754a1993-06-08 12:52:41 +0000470 if self.use_24:
471 fl.show_message('Sorry, no 24 bit continuous capture yet', '', '')
472 return
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000473 vformat = SV.RGB8_FRAMES
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000474 nframes = self.getint(self.in_nframes, 0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000475 if nframes == 0:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000476 maxmem = self.getint(self.in_maxmem, 1.0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000477 memsize = int(maxmem * 1024 * 1024)
Guido van Rossum54618501993-10-26 10:23:14 +0000478 nframes = self.calcnframes(memsize)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000479 info = (vformat, x, y, nframes, 1)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000480 try:
481 info2, data, bitvec = self.video.CaptureBurst(info)
482 except sv.error, msg:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000483 self.b_capture.set_button(0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000484 self.setarrow()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000485 fl.show_message('Capture error:', str(msg), '')
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000486 return
Guido van Rossumc5a14331993-05-07 11:20:07 +0000487 if info <> info2: print info, '<>', info2
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000488 self.save_burst(info2, data, bitvec)
489 self.setarrow()
490
Guido van Rossum54618501993-10-26 10:23:14 +0000491 def calcnframes(self, memsize):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000492 gl.winset(self.window)
493 x, y = gl.getsize()
494 pixels = x*y
495 pixels = pixels/2 # XXX always assume fields
496 if self.mono or self.grey:
497 n = memsize/pixels
498 else:
499 n = memsize/(4*pixels)
500 return max(1, n)
501
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000502 def save_burst(self, info, data, bitvec):
503 (vformat, x, y, nframes, rate) = info
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000504 self.open_if_closed()
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000505 fieldsize = x*y/2
506 nskipped = 0
507 realframeno = 0
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000508 tpf = 1000 / 50.0 # XXX
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000509 for frameno in range(0, nframes*2):
510 if frameno <> 0 and \
511 bitvec[frameno] == bitvec[frameno-1]:
512 nskipped = nskipped + 1
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000513 continue
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000514 #
515 # Save field.
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000516 # XXX Works only for fields and top-to-bottom
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000517 #
518 start = frameno*fieldsize
519 field = data[start:start+fieldsize]
520 realframeno = realframeno + 1
521 fn = int(realframeno*tpf)
522 if not self.write_frame(fn, field):
523 break
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000524
525 def cont_capture(self):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000526 saved_label = self.b_capture.label
527 self.b_capture.label = 'Stop\n' + saved_label
528 self.open_if_closed()
529 self.init_cont()
530 fps = 59.64 # Fields per second
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000531 # XXX (fps of Indigo monitor, not of PAL or NTSC!)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000532 tpf = 1000.0 / fps # Time per field in msec
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000533 self.capturing = 1
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000534 self.start_audio()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000535 while 1:
536 try:
537 void = fl.check_forms()
538 except StopCapture:
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000539 break
540 try:
541 cd, id = self.video.GetCaptureData()
542 except sv.error:
543 sgi.nap(1)
544 continue
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000545 id = id + 2*self.rate
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000546 data = cd.InterleaveFields(1)
547 cd.UnlockCaptureData()
548 t = id*tpf
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000549 if not self.write_frame(t, data):
Guido van Rossume17c6c31993-05-06 16:27:25 +0000550 break
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000551 self.stop_audio()
Guido van Rossume17c6c31993-05-06 16:27:25 +0000552 self.capturing = 0
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000553 self.end_cont()
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000554 if self.aout:
555 # If recording audio, can't capture multiple sequences
556 self.reset()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000557 self.b_capture.label = saved_label
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000558
Jack Jansen672754a1993-06-08 12:52:41 +0000559 def single_capture(self, stepfunc, timecode):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000560 self.open_if_closed()
561 self.init_cont()
562 while 1:
563 try:
564 cd, id = self.video.GetCaptureData()
565 break
566 except sv.error:
567 pass
568 sgi.nap(1)
Jack Jansen672754a1993-06-08 12:52:41 +0000569 if stepfunc: # This might step the video
570 d=stepfunc() # to the next frame
571 if not self.use_24:
572 data = cd.InterleaveFields(1)
573 else:
574 x, y = self.vout.getsize()
Jack Jansen78991fd1993-07-23 11:59:25 +0000575 if self.use_compress:
576 if self.rgb24_size == 1:
577 data = cd.YUVtoYUV422DC(0)
578 elif self.rgb24_size == 2:
579 data = cd.YUVtoYUV422DC_quarter(1)
580 x = x/2
581 y = y/2
582 elif self.rgb24_size == 3:
583 data = cd.YUVtoYUV422DC_sixteenth(1)
584 x = x/4
585 y = y/4
Jack Jansen672754a1993-06-08 12:52:41 +0000586 else:
Jack Jansen78991fd1993-07-23 11:59:25 +0000587 data = cd.YUVtoRGB(1)
588 if self.maxx*self.maxy*4 <> len(data):
589 print 'maxx,maxy,exp,got=', self.maxx,
590 print self.maxy,self.maxx*self.maxy*4,
591 print len(data)
592 fl.showmessage('Wrong sized data')
593 return 0
594 if self.rgb24_size <> 1:
595 data = imageop.scale(data, 4, \
596 self.maxx, self.maxy, x, y)
Jack Jansen672754a1993-06-08 12:52:41 +0000597 if self.use_jpeg:
598 import jpeg
599 data = jpeg.compress(data, x, y, 4)
Jack Jansen78991fd1993-07-23 11:59:25 +0000600 if self.use_compress:
601 data = self.compressor.Compress(1, data)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000602 cd.UnlockCaptureData()
603 self.end_cont()
Jack Jansen672754a1993-06-08 12:52:41 +0000604 if timecode == None:
605 timecode = (self.nframes+1) * (1000/25)
606 return self.write_frame(timecode, data)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000607
608 def vcr_capture(self):
609 if not self.vcr:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000610 try:
Guido van Rossum2055ee81993-06-11 14:13:13 +0000611 print 'Connecting to VCR ...'
Guido van Rossum21a3ff91993-12-17 15:11:41 +0000612 self.vcr = VCR.VCR()
Guido van Rossum2055ee81993-06-11 14:13:13 +0000613 print 'Waiting for VCR to come online ...'
Jack Jansen78991fd1993-07-23 11:59:25 +0000614 self.vcr.initvcr()
Guido van Rossum2055ee81993-06-11 14:13:13 +0000615 print 'Preparing VCR ...'
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000616 if not (self.vcr.fmmode('dnr') and \
617 self.vcr.dmcontrol('digital slow')):
618 self.vcr_error('digital slow failed')
619 return
Guido van Rossum2055ee81993-06-11 14:13:13 +0000620 print 'VCR OK.'
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000621 except VCR.error, msg:
Guido van Rossumc17c84f1993-05-10 15:45:49 +0000622 self.vcr = None
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000623 self.vcr_error(msg)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000624 return
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000625 if not self.vcr.still():
626 self.vcr_error('still failed')
627 return
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000628 self.open_if_closed()
629 rate = self.getint(self.in_rate_vcr, 1)
630 rate = max(rate, 1)
Jack Jansen672754a1993-06-08 12:52:41 +0000631 vcrspeed = self.c_vcrspeed.get_choice()
632 vcrspeed = VcrSpeeds[vcrspeed]
633 if vcrspeed == 0:
634 stepfunc = self.vcr.step
635 else:
636 stepfunc = None
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000637 self.speed_factor = rate
Jack Jansen672754a1993-06-08 12:52:41 +0000638 addr = start_addr = self.vcr.sense()
639 if not self.single_capture(None, 0):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000640 return
641 print 'captured %02d:%02d:%02d:%02d' % self.vcr.addr2tc(addr)
642 count = self.getint(self.in_nframes_vcr, 1) - 1
643 if count <= 0:
644 while rate > 0:
645 if not self.vcr.step():
646 self.vcr_error('step failed')
647 here = self.vcr.sense()
648 if here > addr:
649 rate = rate - (here - addr)
650 addr = here
651 return
Guido van Rossum2055ee81993-06-11 14:13:13 +0000652 if not self.vcr.fwdshuttle(vcrspeed):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000653 self.vcr_error('fwd shuttle failed')
654 return
655 cycle = 0
656 while count > 0:
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000657 try:
658 here = self.vcr.sense()
659 except VCR.error, msg:
660 self.vcr_error(msg)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000661 break
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000662 if here <> addr:
663 if here <> addr+1:
664 print 'Missed', here-addr-1,
665 print 'frame' + 's'*(here-addr-1 <> 1)
666 cycle = (cycle+1) % rate
667 if cycle == 0:
Jack Jansen672754a1993-06-08 12:52:41 +0000668 tc = (here-start_addr)*40
669 if not self.single_capture(stepfunc, \
670 tc):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000671 break
672 print 'captured %02d:%02d:%02d:%02d' \
673 % self.vcr.addr2tc(here)
674 count = count -1
675 addr = here
676 if self.vcr and not self.vcr.still():
677 self.vcr_error('still failed')
678
679 def vcr_error(self, msg):
680 self.reset()
681 fl.show_message('VCR error:', str(msg), '')
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000682
683 # Init/end continuous capture mode
684
685 def init_cont(self):
686 qsize = 1
687 if self.vmode == VM_CONT:
688 self.rate = self.getint(self.in_rate, 2)
689 else:
690 self.rate = 2
691 x, y = self.vout.getsize()
Jack Jansen672754a1993-06-08 12:52:41 +0000692 if self.use_24:
693 info = (SV.YUV411_FRAMES, x, y, qsize, self.rate)
694 else:
695 info = (SV.RGB8_FRAMES, x, y, qsize, self.rate)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000696 info2 = self.video.InitContinuousCapture(info)
697 if info2 <> info:
698 # XXX This is really only debug info
699 print 'Info mismatch: requested', info, 'got', info2
700
701 def end_cont(self):
702 self.video.EndContinuousCapture()
703
704 # Misc stuff
705
706 def settitle(self):
707 gl.winset(self.window)
708 x, y = gl.getsize()
Guido van Rossum43df8621993-06-11 15:48:39 +0000709 title = 'Vb ' + self.vfile + ' (%dx%d)' % (x, y)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000710 gl.wintitle(title)
711
712 def get_vformat(self):
713 i = self.c_vformat.get_choice()
714 label = VideoFormatLabels[i-1]
715 format = VideoFormats[i-1]
Jack Jansen78991fd1993-07-23 11:59:25 +0000716 if format == 'compress' and cl == None:
717 fl.show_message('Sorry, no compression library support')
718 format = ''
719 label = 'Video off'
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000720 self.vformat = format
721 if self.vformat == '':
722 self.form.freeze_form()
723 self.g_video.hide_object()
724 self.g_cont.hide_object()
725 self.g_burst.hide_object()
726 self.g_single.hide_object()
727 self.form.unfreeze_form()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000728 else:
729 self.g_video.show_object()
730 if self.vmode == VM_CONT:
731 self.g_cont.show_object()
732 elif self.vmode == VM_BURST:
733 self.g_burst.show_object()
734 elif self.vmode == VM_SINGLE:
735 self.g_single.show_object()
Guido van Rossumc5a14331993-05-07 11:20:07 +0000736 #
Jack Jansen78991fd1993-07-23 11:59:25 +0000737 self.rgb = (format[:3] == 'rgb' or format == 'compress')
Guido van Rossumc5a14331993-05-07 11:20:07 +0000738 self.mono = (format == 'mono')
739 self.grey = (format[:4] == 'grey')
Jack Jansen78991fd1993-07-23 11:59:25 +0000740 self.use_24 = (format in ('rgb', 'jpeg', 'compress'))
741 if self.use_24:
Jack Jansen672754a1993-06-08 12:52:41 +0000742 self.g_rgb24.show_object()
743 else:
744 self.g_rgb24.hide_object()
745 self.use_jpeg = (format == 'jpeg')
Guido van Rossumc5a14331993-05-07 11:20:07 +0000746 self.mono_use_thresh = (label == 'mono thresh')
Jack Jansen78991fd1993-07-23 11:59:25 +0000747 self.use_compress = (format == 'compress')
748 if self.use_compress:
749 self.g_compress.show_object()
750 else:
751 self.g_compress.hide_object()
Guido van Rossumc5a14331993-05-07 11:20:07 +0000752 s = format[4:]
Jack Jansen78991fd1993-07-23 11:59:25 +0000753 if self.grey and s:
Guido van Rossumc5a14331993-05-07 11:20:07 +0000754 self.greybits = string.atoi(s)
755 else:
756 self.greybits = 8
757 if label == 'grey2 dith':
758 self.greybits = -2
759 #
760 convertor = None
761 if self.grey:
762 if self.greybits == 2:
763 convertor = imageop.grey2grey2
764 elif self.greybits == 4:
765 convertor = imageop.grey2grey4
766 elif self.greybits == -2:
767 convertor = imageop.dither2grey2
768 self.convertor = convertor
Jack Jansen672754a1993-06-08 12:52:41 +0000769 self.optfullsizewindow()
Guido van Rossumc5a14331993-05-07 11:20:07 +0000770
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000771 def get_aformat(self):
772 self.reset()
773 self.aformat = self.c_aformat.get_choice()
774 if self.aformat == A_OFF:
775 self.g_audio.hide_object()
776 else:
777 self.g_audio.show_object()
778
Jack Jansen78991fd1993-07-23 11:59:25 +0000779 def init_compressor(self, w, h):
780 self.compressor = None
781 scheme = cl.QuerySchemeFromName(CL.VIDEO, self.comp_scheme)
782 self.compressor = cl.OpenCompressor(scheme)
783 parambuf = [CL.IMAGE_WIDTH, w, \
784 CL.IMAGE_HEIGHT, h, \
785 CL.ORIGINAL_FORMAT, CL.YUV422DC]
786 self.compressor.SetParams(parambuf)
787 return self.compressor.Compress(0, '')
788
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000789 def open_if_closed(self):
790 if not self.vout:
791 self.open_video()
792 if not self.aout:
793 self.open_audio()
794
795 # File I/O handling
796
797 def open_video(self):
798 self.close_video()
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000799 gl.winset(self.window)
800 x, y = gl.getsize()
Jack Jansen672754a1993-06-08 12:52:41 +0000801 if self.use_24:
802 if self.rgb24_size == 2:
803 x, y = x/2, y/2
Jack Jansen78991fd1993-07-23 11:59:25 +0000804 elif self.rgb24_size == 3:
Jack Jansen672754a1993-06-08 12:52:41 +0000805 x, y = x/4, y/4
Guido van Rossum21a3ff91993-12-17 15:11:41 +0000806 vout = VFile.VoutFile(self.vfile)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000807 vout.setformat(self.vformat)
Jack Jansen78991fd1993-07-23 11:59:25 +0000808 if self.vformat == 'compress':
809 cheader = self.init_compressor(x, y)
810 vout.setcompressheader(cheader)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000811 vout.setsize(x, y)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000812 if self.vmode == VM_BURST:
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000813 vout.setpf((1, -2))
814 vout.writeheader()
815 self.vout = vout
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000816 self.nframes = 0
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000817 self.speed_factor = 1
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000818 self.t_nframes.label = `self.nframes`
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000819
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000820 def write_frame(self, t, data):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000821 t = t * self.speed_factor
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000822 if not self.vout:
823 gl.ringbell()
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000824 return 0
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000825 if self.convertor:
826 data = self.convertor(data, len(data), 1)
827 elif self.mono:
828 if self.mono_use_thresh:
829 data = imageop.grey2mono(data, \
830 len(data), 1,\
831 self.mono_thresh)
832 else:
833 data = imageop.dither2mono(data, \
834 len(data), 1)
835 try:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000836 self.vout.writeframe(int(t), data, None)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000837 except IOError, msg:
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000838 self.reset()
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000839 if msg == (0, 'Error 0'):
840 msg = 'disk full??'
841 fl.show_message('IOError', str(msg), '')
842 return 0
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000843 self.nframes = self.nframes + 1
844 self.t_nframes.label = `self.nframes`
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000845 return 1
846
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000847 def close_video(self):
848 if not self.vout:
849 return
850 self.nframes = 0
851 self.t_nframes.label = ''
Guido van Rossumc5a14331993-05-07 11:20:07 +0000852 try:
853 self.vout.close()
854 except IOError, msg:
855 if msg == (0, 'Error 0'):
856 msg = 'disk full??'
857 fl.show_message('IOError', str(msg), '')
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000858 self.vout = None
Jack Jansen78991fd1993-07-23 11:59:25 +0000859 self.compressor = None
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000860
861 # Watch cursor handling
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000862
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000863 def setwatch(self):
864 gl.winset(self.form.window)
865 gl.setcursor(WATCH, 0, 0)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000866 gl.winset(self.window)
867 gl.setcursor(WATCH, 0, 0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000868
869 def setarrow(self):
870 gl.winset(self.form.window)
871 gl.setcursor(ARROW, 0, 0)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000872 gl.winset(self.window)
873 gl.setcursor(ARROW, 0, 0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000874
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000875 # Numeric field handling
876
877 def getint(self, field, default):
878 try:
879 value = string.atoi(field.get_input())
880 except string.atoi_error:
881 value = default
882 field.set_input(`value`)
883 return value
884
885 def getfloat(self, field, default):
886 try:
887 value = float(eval(field.get_input()))
888 except:
889 value = float(default)
Guido van Rossumc17c84f1993-05-10 15:45:49 +0000890 field.set_input(`value`)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000891 return value
892
893 # Audio stuff
894
895 def open_audio(self):
896 if self.aformat == A_OFF:
897 return
898 import aifc
899 import al
900 import AL
901 import thread
902 self.close_audio()
903 params = [AL.INPUT_RATE, 0]
904 al.getparams(AL.DEFAULT_DEVICE, params)
905 rate = params[1]
906 self.aout = aifc.open(self.afile, 'w')
907 if self.aformat in (A_16_STEREO, A_8_STEREO):
908 nch = AL.STEREO
909 else:
910 nch = AL.MONO
911 if self.aformat in (A_16_STEREO, A_16_MONO):
912 width = AL.SAMPLE_16
913 else:
914 width = AL.SAMPLE_8
915 self.aout.setnchannels(nch)
916 self.aout.setsampwidth(width)
917 self.aout.setframerate(rate)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000918 c = al.newconfig()
919 c.setqueuesize(8000)
920 c.setchannels(nch)
921 c.setwidth(width)
922 self.aport = al.openport('Vb audio record', 'r', c)
923 self.audio_stop = 0
924 self.audio_ok = 0
925 self.audio_busy = 1
926 thread.start_new_thread(self.record_audio, ())
927
928 def start_audio(self):
929 if self.aformat == A_OFF:
930 return
931 self.audio_ok = 1
932
933 def record_audio(self, *args):
934 # This function runs in a separate thread
935 # Currently no semaphores are used
936 while not self.audio_stop:
937 data = self.aport.readsamps(4000)
938 if self.audio_ok:
Guido van Rossumf6d80321993-06-10 13:40:51 +0000939 self.aout.writeframes(data)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000940 data = None
941 self.audio_busy = 0
942
943 def stop_audio(self):
944 self.audio_ok = 0
945
946 def close_audio(self):
947 if self.aout:
948 self.audio_ok = 0
949 self.audio_stop = 1
950 while self.audio_busy:
951 time.sleep(0.1)
952 self.aout.close()
953 self.aout = None
954 if self.aport:
955 self.aport.closeport()
956 self.aport = None
957
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000958
959try:
960 main()
961except KeyboardInterrupt:
962 print '[Interrupt]'
963 sys.exit(1)