blob: 3cf97f7d417b7a1dabba61d520fe6920dd448a4d [file] [log] [blame]
Sjoerd Mullendered59d201993-01-06 13:36:38 +00001/**********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Sjoerd Mullendered59d201993-01-06 13:36:38 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Sjoerd Mullendered59d201993-01-06 13:36:38 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Sjoerd Mullendered59d201993-01-06 13:36:38 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Sjoerd Mullendered59d201993-01-06 13:36:38 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Sjoerd Mullendered59d201993-01-06 13:36:38 +000029
30******************************************************************/
31
32/* SV module -- interface to the Indigo video board */
33
34#include <sys/time.h>
35#include <svideo.h>
36#include "allobjects.h"
37#include "import.h"
38#include "modsupport.h"
39#include "compile.h"
40#include "ceval.h"
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +000041#include "yuv.h" /* for YUV conversion functions */
Sjoerd Mullendered59d201993-01-06 13:36:38 +000042
43typedef struct {
44 OB_HEAD
45 SV_nodeP ob_svideo;
46 svCaptureInfo ob_info;
47} svobject;
48
49typedef struct {
50 OB_HEAD
51 void *ob_capture;
52 int ob_mustunlock;
53 svCaptureInfo ob_info;
54 svobject *ob_svideo;
55} captureobject;
56
57static object *SvError; /* exception sv.error */
58
59static object *newcaptureobject PROTO((svobject *, void *, int));
60
61/* Set a SV-specific error from svideo_errno and return NULL */
62static object *
63sv_error()
64{
65 err_setstr(SvError, svStrerror(svideo_errno));
66 return NULL;
67}
68
69static object *
70svc_conversion(self, args, function, factor)
71 captureobject *self;
72 object *args;
73 void (*function)();
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +000074 float factor;
Sjoerd Mullendered59d201993-01-06 13:36:38 +000075{
76 object *output;
77 int invert;
78
79 if (!getargs(args, "i", &invert))
80 return NULL;
81
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +000082 output = newsizedstringobject(NULL, (int) (self->ob_info.width * self->ob_info.height * factor));
Sjoerd Mullendered59d201993-01-06 13:36:38 +000083 if (output == NULL)
84 return NULL;
85
86 (*function)((boolean) invert, self->ob_capture, getstringvalue(output),
87 self->ob_info.width, self->ob_info.height);
88
89 return output;
90}
91
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +000092/*
93 * 3 functions to convert from Starter Video YUV 4:1:1 format to
94 * Compression Library 4:2:2 Duplicate Chroma format.
95 */
96static object *
97svc_YUVtoYUV422DC(self, args)
98 captureobject *self;
99 object *args;
100{
101 if (self->ob_info.format != SV_YUV411_FRAMES) {
102 err_setstr(SvError, "data has bad format");
103 return NULL;
104 }
105 return svc_conversion(self, args, yuv_sv411_to_cl422dc, 2.0);
106}
107
108static object *
109svc_YUVtoYUV422DC_quarter(self, args)
110 captureobject *self;
111 object *args;
112{
113 if (self->ob_info.format != SV_YUV411_FRAMES) {
114 err_setstr(SvError, "data has bad format");
115 return NULL;
116 }
117 return svc_conversion(self, args, yuv_sv411_to_cl422dc_quartersize, 0.5);
118}
119
120static object *
121svc_YUVtoYUV422DC_sixteenth(self, args)
122 captureobject *self;
123 object *args;
124{
125 if (self->ob_info.format != SV_YUV411_FRAMES) {
126 err_setstr(SvError, "data has bad format");
127 return NULL;
128 }
129 return svc_conversion(self, args, yuv_sv411_to_cl422dc_sixteenthsize, 0.125);
130}
131
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000132static object *
133svc_YUVtoRGB(self, args)
134 captureobject *self;
135 object *args;
136{
137 switch (self->ob_info.format) {
138 case SV_YUV411_FRAMES:
139 case SV_YUV411_FRAMES_AND_BLANKING_BUFFER:
140 break;
141 default:
142 err_setstr(SvError, "data had bad format");
143 return NULL;
144 }
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +0000145 return svc_conversion(self, args, svYUVtoRGB, (float) sizeof(long));
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000146}
147
148static object *
149svc_RGB8toRGB32(self, args)
150 captureobject *self;
151 object *args;
152{
153 if (self->ob_info.format != SV_RGB8_FRAMES) {
154 err_setstr(SvError, "data has bad format");
155 return NULL;
156 }
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +0000157 return svc_conversion(self, args, svRGB8toRGB32, (float) sizeof(long));
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000158}
159
160static object *
161svc_InterleaveFields(self, args)
162 captureobject *self;
163 object *args;
164{
165 if (self->ob_info.format != SV_RGB8_FRAMES) {
166 err_setstr(SvError, "data has bad format");
167 return NULL;
168 }
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +0000169 return svc_conversion(self, args, svInterleaveFields, 1.0);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000170}
171
172static object *
173svc_GetFields(self, args)
174 captureobject *self;
175 object *args;
176{
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000177 object *f1, *f2, *ret;
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000178 int fieldsize;
179
180 if (self->ob_info.format != SV_RGB8_FRAMES) {
181 err_setstr(SvError, "data has bad format");
182 return NULL;
183 }
184
185 fieldsize = self->ob_info.width * self->ob_info.height / 2;
186 f1 = newsizedstringobject((char *) self->ob_capture, fieldsize);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000187 f2 = newsizedstringobject((char *) self->ob_capture + fieldsize, fieldsize);
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000188 ret = mkvalue("(OO)", f1, f2);
189 XDECREF(f1);
190 XDECREF(f2);
191 return ret;
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000192}
193
194static object *
195svc_UnlockCaptureData(self, args)
196 captureobject *self;
197 object *args;
198{
199 if (!getnoarg(args))
200 return NULL;
201
202 if (!self->ob_mustunlock) {
203 err_setstr(SvError, "buffer should not be unlocked");
204 return NULL;
205 }
206
207 if (svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture))
208 return sv_error();
209
210 self->ob_mustunlock = 0;
211
212 INCREF(None);
213 return None;
214}
215
216#ifdef USE_GL
217#include <gl.h>
218
219static object *
220svc_lrectwrite(self, args)
221 captureobject *self;
222 object *args;
223{
224 Screencoord x1, x2, y1, y2;
225
226 if (!getargs(args, "(hhhh)", &x1, &x2, &y1, &y2))
227 return NULL;
228
229 lrectwrite(x1, x2, y1, y2, (unsigned long *) self->ob_capture);
230
231 INCREF(None);
232 return None;
233}
234#endif
235
236static object *
Guido van Rossumb6775db1994-08-01 11:34:53 +0000237svc_writefile(self, args)
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000238 captureobject *self;
239 object *args;
240{
241 object *file;
242 int size;
243
244 if (!getargs(args, "O", &file))
245 return NULL;
246
247 if (!is_fileobject(file)) {
248 err_setstr(SvError, "not a file object");
249 return NULL;
250 }
251
252 size = self->ob_info.width * self->ob_info.height;
253
254 if (fwrite(self->ob_capture, sizeof(long), size, getfilefile(file)) != size) {
255 err_setstr(SvError, "writing failed");
256 return NULL;
257 }
258
259 INCREF(None);
260 return None;
261}
262
263static object *
264svc_FindVisibleRegion(self, args)
265 captureobject *self;
266 object *args;
267{
268 void *visible;
269 int width;
270
271 if (!getnoarg(args))
272 return NULL;
273
274 if (svFindVisibleRegion(self->ob_svideo->ob_svideo, self->ob_capture, &visible, self->ob_info.width))
275 return sv_error();
276
277 if (visible == NULL) {
278 err_setstr(SvError, "data in wrong format");
279 return NULL;
280 }
281
282 return newcaptureobject(self->ob_svideo, visible, 0);
283}
284
285static struct methodlist capture_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000286 {"YUVtoRGB", (method)svc_YUVtoRGB},
287 {"RGB8toRGB32", (method)svc_RGB8toRGB32},
288 {"InterleaveFields", (method)svc_InterleaveFields},
289 {"UnlockCaptureData", (method)svc_UnlockCaptureData},
290 {"FindVisibleRegion", (method)svc_FindVisibleRegion},
291 {"GetFields", (method)svc_GetFields},
292 {"YUVtoYUV422DC", (method)svc_YUVtoYUV422DC},
293 {"YUVtoYUV422DC_quarter",(method)svc_YUVtoYUV422DC_quarter},
294 {"YUVtoYUV422DC_sixteenth",(method)svc_YUVtoYUV422DC_sixteenth},
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000295#ifdef USE_GL
Guido van Rossumb6775db1994-08-01 11:34:53 +0000296 {"lrectwrite", (method)svc_lrectwrite},
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000297#endif
Guido van Rossumb6775db1994-08-01 11:34:53 +0000298 {"writefile", (method)svc_writefile},
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000299 {NULL, NULL} /* sentinel */
300};
301
302static void
303capture_dealloc(self)
304 captureobject *self;
305{
306 if (self->ob_capture != NULL) {
307 if (self->ob_mustunlock)
308 (void) svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture);
309 self->ob_capture = NULL;
310 DECREF(self->ob_svideo);
311 self->ob_svideo = NULL;
312 }
313 DEL(self);
314}
315
316static object *
317capture_getattr(self, name)
318 svobject *self;
319 char *name;
320{
321 return findmethod(capture_methods, (object *)self, name);
322}
323
324typeobject Capturetype = {
325 OB_HEAD_INIT(&Typetype)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000326 0, /*ob_size*/
327 "capture", /*tp_name*/
328 sizeof(captureobject), /*tp_size*/
329 0, /*tp_itemsize*/
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000330 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000331 (destructor)capture_dealloc, /*tp_dealloc*/
332 0, /*tp_print*/
333 (getattrfunc)capture_getattr, /*tp_getattr*/
334 0, /*tp_setattr*/
335 0, /*tp_compare*/
336 0, /*tp_repr*/
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000337};
338
339static object *
340newcaptureobject(self, ptr, mustunlock)
341 svobject *self;
342 void *ptr;
343 int mustunlock;
344{
345 captureobject *p;
346
347 p = NEWOBJ(captureobject, &Capturetype);
348 if (p == NULL)
349 return NULL;
350 p->ob_svideo = self;
351 INCREF(self);
352 p->ob_capture = ptr;
353 p->ob_mustunlock = mustunlock;
354 p->ob_info = self->ob_info;
355 return (object *) p;
356}
357
358static object *
359sv_GetCaptureData(self, args)
360 svobject *self;
361 object *args;
362{
363 void *ptr;
364 long fieldID;
365 object *res, *c;
366
367 if (!getnoarg(args))
368 return NULL;
369
370 if (svGetCaptureData(self->ob_svideo, &ptr, &fieldID))
371 return sv_error();
372
373 if (ptr == NULL) {
374 err_setstr(SvError, "no data available");
375 return NULL;
376 }
377
378 c = newcaptureobject(self, ptr, 1);
379 if (c == NULL)
380 return NULL;
381 res = mkvalue("(Oi)", c, fieldID);
382 DECREF(c);
383 return res;
384}
385
386static object *
387sv_BindGLWindow(self, args)
388 svobject *self;
389 object *args;
390{
391 long wid;
392 int mode;
393
394 if (!getargs(args, "(ii)", &wid, &mode))
395 return NULL;
396
397 if (svBindGLWindow(self->ob_svideo, wid, mode))
398 return sv_error();
399
400 INCREF(None);
401 return None;
402}
403
404static object *
405sv_EndContinuousCapture(self, args)
406 svobject *self;
407 object *args;
408{
409
410 if (!getnoarg(args))
411 return NULL;
412
413 if (svEndContinuousCapture(self->ob_svideo))
414 return sv_error();
415
416 INCREF(None);
417 return None;
418}
419
420static object *
421sv_IsVideoDisplayed(self, args)
422 svobject *self;
423 object *args;
424{
425 int v;
426
427 if (!getnoarg(args))
428 return NULL;
429
430 v = svIsVideoDisplayed(self->ob_svideo);
431 if (v == -1)
432 return sv_error();
433
434 return newintobject((long) v);
435}
436
437static object *
438sv_OutputOffset(self, args)
439 svobject *self;
440 object *args;
441{
442 int x_offset;
443 int y_offset;
444
445 if (!getargs(args, "(ii)", &x_offset, &y_offset))
446 return NULL;
447
448 if (svOutputOffset(self->ob_svideo, x_offset, y_offset))
449 return sv_error();
450
451 INCREF(None);
452 return None;
453}
454
455static object *
456sv_PutFrame(self, args)
457 svobject *self;
458 object *args;
459{
460 char *buffer;
461
462 if (!getargs(args, "s", &buffer))
463 return NULL;
464
465 if (svPutFrame(self->ob_svideo, buffer))
466 return sv_error();
467
468 INCREF(None);
469 return None;
470}
471
472static object *
473sv_QuerySize(self, args)
474 svobject *self;
475 object *args;
476{
477 int w;
478 int h;
479 int rw;
480 int rh;
481
482 if (!getargs(args, "(ii)", &w, &h))
483 return NULL;
484
485 if (svQuerySize(self->ob_svideo, w, h, &rw, &rh))
486 return sv_error();
487
488 return mkvalue("(ii)", (long) rw, (long) rh);
489}
490
491static object *
492sv_SetSize(self, args)
493 svobject *self;
494 object *args;
495{
496 int w;
497 int h;
498
499 if (!getargs(args, "(ii)", &w, &h))
500 return NULL;
501
502 if (svSetSize(self->ob_svideo, w, h))
503 return sv_error();
504
505 INCREF(None);
506 return None;
507}
508
509static object *
510sv_SetStdDefaults(self, args)
511 svobject *self;
512 object *args;
513{
514
515 if (!getnoarg(args))
516 return NULL;
517
518 if (svSetStdDefaults(self->ob_svideo))
519 return sv_error();
520
521 INCREF(None);
522 return None;
523}
524
525static object *
526sv_UseExclusive(self, args)
527 svobject *self;
528 object *args;
529{
530 boolean onoff;
531 int mode;
532
533 if (!getargs(args, "(ii)", &onoff, &mode))
534 return NULL;
535
536 if (svUseExclusive(self->ob_svideo, onoff, mode))
537 return sv_error();
538
539 INCREF(None);
540 return None;
541}
542
543static object *
544sv_WindowOffset(self, args)
545 svobject *self;
546 object *args;
547{
548 int x_offset;
549 int y_offset;
550
551 if (!getargs(args, "(ii)", &x_offset, &y_offset))
552 return NULL;
553
554 if (svWindowOffset(self->ob_svideo, x_offset, y_offset))
555 return sv_error();
556
557 INCREF(None);
558 return None;
559}
560
561static object *
562sv_CaptureBurst(self, args)
563 svobject *self;
564 object *args;
565{
566 int bytes, i;
567 svCaptureInfo info;
568 void *bitvector = NULL;
569 object *videodata, *bitvecobj, *res;
570 static object *evenitem, *odditem;
571
572 if (!getargs(args, "(iiiii)", &info.format, &info.width, &info.height,
573 &info.size, &info.samplingrate))
574 return NULL;
575
576 switch (info.format) {
577 case SV_RGB8_FRAMES:
578 bitvector = malloc(SV_BITVEC_SIZE(info.size));
579 break;
580 case SV_YUV411_FRAMES_AND_BLANKING_BUFFER:
581 break;
582 default:
583 err_setstr(SvError, "illegal format specified");
584 return NULL;
585 }
586
587 if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) {
588 if (bitvector)
589 free(bitvector);
590 return sv_error();
591 }
592
593 videodata = newsizedstringobject(NULL, bytes);
594 if (videodata == NULL) {
595 if (bitvector)
596 free(bitvector);
597 return NULL;
598 }
599
600 /* XXX -- need to do something about the bitvector */
601 if (svCaptureBurst(self->ob_svideo, &info, getstringvalue(videodata),
602 bitvector)) {
603 if (bitvector)
604 free(bitvector);
605 DECREF(videodata);
606 return sv_error();
607 }
608
609 if (bitvector) {
610 if (evenitem == NULL) {
611 evenitem = newintobject(0);
612 if (evenitem == NULL) {
613 free(bitvector);
614 DECREF(videodata);
615 return NULL;
616 }
617 }
618 if (odditem == NULL) {
619 odditem = newintobject(1);
620 if (odditem == NULL) {
621 free(bitvector);
622 DECREF(videodata);
623 return NULL;
624 }
625 }
626 bitvecobj = newtupleobject(2 * info.size);
627 if (bitvecobj == NULL) {
628 free(bitvecobj);
629 DECREF(videodata);
630 return NULL;
631 }
632 for (i = 0; i < 2 * info.size; i++) {
633 if (SV_GET_FIELD(bitvector, i) == SV_EVEN_FIELD) {
634 INCREF(evenitem);
635 settupleitem(bitvecobj, i, evenitem);
636 } else {
637 INCREF(odditem);
638 settupleitem(bitvecobj, i, odditem);
639 }
640 }
641 free(bitvector);
642 } else {
643 bitvecobj = None;
644 INCREF(None);
645 }
646
647 res = mkvalue("((iiiii)OO)", info.format, info.width, info.height,
648 info.size, info.samplingrate, videodata, bitvecobj);
649 DECREF(videodata);
650 DECREF(bitvecobj);
651 return res;
652}
653
654static object *
655sv_CaptureOneFrame(self, args)
656 svobject *self;
657 object *args;
658{
659 svCaptureInfo info;
660 int format, width, height;
661 int bytes;
662 object *videodata, *res;
663
664 if (!getargs(args, "(iii)", &format, &width, &height))
665 return NULL;
666 info.format = format;
667 info.width = width;
668 info.height = height;
669 info.size = 0;
670 info.samplingrate = 0;
671 if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes))
672 return sv_error();
673 videodata = newsizedstringobject(NULL, bytes);
674 if (videodata == NULL)
675 return NULL;
676 if (svCaptureOneFrame(self->ob_svideo, format, &width, &height,
677 getstringvalue(videodata))) {
678 DECREF(videodata);
679 return sv_error();
680 }
681
682 res = mkvalue("(iiO)", width, height, videodata);
683 DECREF(videodata);
684 return res;
685}
686
687static object *
688sv_InitContinuousCapture(self, args)
689 svobject *self;
690 object *args;
691{
692 svCaptureInfo info;
693
694 if (!getargs(args, "(iiiii)", &info.format, &info.width, &info.height,
695 &info.size, &info.samplingrate))
696 return NULL;
697
698 if (svInitContinuousCapture(self->ob_svideo, &info))
699 return sv_error();
700
701 self->ob_info = info;
702
703 return mkvalue("(iiiii)", info.format, info.width, info.height,
704 info.size, info.samplingrate);
705}
706
707static object *
708sv_LoadMap(self, args)
709 svobject *self;
710 object *args;
711{
712 object *rgb, *v, *cell;
713 rgb_tuple *mapp;
714 int maptype;
715 int i, j; /* indices */
716
717 if (!getargs(args, "(iO)", &maptype, &rgb))
718 return NULL;
719 if (!is_listobject(rgb) || getlistsize(rgb) != 256) {
720 err_badarg();
721 return NULL;
722 }
723 mapp = NEW(rgb_tuple, 256);
724 if (mapp == NULL)
725 return err_nomem();
726 for (i = 0; i < 256; i++) {
727 v = getlistitem(rgb, i);
728 if (!is_tupleobject(v) || gettuplesize(v) != 3) {
729 DEL(mapp);
730 err_badarg();
731 return NULL;
732 }
733 for (j = 0; j < 3; j++) {
734 cell = gettupleitem(v, j);
735 if (!is_intobject(cell)) {
736 DEL(mapp);
737 err_badarg();
738 return NULL;
739 }
740 switch (j) {
741 case 0: mapp[i].red = getintvalue(cell); break;
742 case 1: mapp[i].blue = getintvalue(cell); break;
743 case 2: mapp[i].green = getintvalue(cell); break;
744 }
745 }
746 }
747
748 if (svLoadMap(self->ob_svideo, maptype, mapp)) {
749 DEL(mapp);
750 return sv_error();
751 }
752
753 DEL(mapp);
754
755 INCREF(None);
756 return None;
757}
758
759static object *
760sv_CloseVideo(self, args)
761 svobject *self;
762 object *args;
763{
764 if (!getnoarg(args))
765 return NULL;
766
767 if (svCloseVideo(self->ob_svideo))
768 return sv_error();
769 self->ob_svideo = NULL;
770
771 INCREF(None);
772 return None;
773}
774
775static object *
776doParams(self, args, func, modified)
777 svobject *self;
778 object *args;
779 int (*func)(SV_nodeP, long *, int);
780 int modified;
781{
782 object *list, *v;
783 long *PVbuffer;
784 long length;
785 int i;
786
787 if (!getargs(args, "O", &list))
788 return NULL;
789 if (!is_listobject(list)) {
790 err_badarg();
791 return NULL;
792 }
793 length = getlistsize(list);
794 PVbuffer = NEW(long, length);
795 if (PVbuffer == NULL)
796 return err_nomem();
797 for (i = 0; i < length; i++) {
798 v = getlistitem(list, i);
799 if (!is_intobject(v)) {
800 DEL(PVbuffer);
801 err_badarg();
802 return NULL;
803 }
804 PVbuffer[i] = getintvalue(v);
805 }
806
807 if ((*func)(self->ob_svideo, PVbuffer, length)) {
808 DEL(PVbuffer);
809 return sv_error();
810 }
811
812 if (modified) {
813 for (i = 0; i < length; i++)
814 setlistitem(list, i, newintobject(PVbuffer[i]));
815 }
816
817 DEL(PVbuffer);
818
819 INCREF(None);
820 return None;
821}
822
823static object *
824sv_GetParam(self, args)
825 object *self, *args;
826{
827 return doParams(self, args, svGetParam, 1);
828}
829
830static object *
831sv_GetParamRange(self, args)
832 object *self, *args;
833{
834 return doParams(self, args, svGetParamRange, 1);
835}
836
837static object *
838sv_SetParam(self, args)
839 object *self, *args;
840{
841 return doParams(self, args, svSetParam, 0);
842}
843
844static struct methodlist svideo_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000845 {"BindGLWindow", (method)sv_BindGLWindow},
846 {"EndContinuousCapture",(method)sv_EndContinuousCapture},
847 {"IsVideoDisplayed", (method)sv_IsVideoDisplayed},
848 {"OutputOffset", (method)sv_OutputOffset},
849 {"PutFrame", (method)sv_PutFrame},
850 {"QuerySize", (method)sv_QuerySize},
851 {"SetSize", (method)sv_SetSize},
852 {"SetStdDefaults", (method)sv_SetStdDefaults},
853 {"UseExclusive", (method)sv_UseExclusive},
854 {"WindowOffset", (method)sv_WindowOffset},
855 {"InitContinuousCapture",(method)sv_InitContinuousCapture},
856 {"CaptureBurst", (method)sv_CaptureBurst},
857 {"CaptureOneFrame", (method)sv_CaptureOneFrame},
858 {"GetCaptureData", (method)sv_GetCaptureData},
859 {"CloseVideo", (method)sv_CloseVideo},
860 {"LoadMap", (method)sv_LoadMap},
861 {"GetParam", (method)sv_GetParam},
862 {"GetParamRange", (method)sv_GetParamRange},
863 {"SetParam", (method)sv_SetParam},
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000864 {NULL, NULL} /* sentinel */
865};
866
867static object *
868sv_conversion(self, args, function, inputfactor, factor)
869 object *self, *args;
870 void (*function)();
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +0000871 int inputfactor;
872 float factor;
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000873{
874 int invert, width, height, inputlength;
875 char *input;
876 object *output;
877
878 if (!getargs(args, "(is#ii)", &invert, &input, &inputlength, &width, &height))
879 return NULL;
880
881 if (width * height * inputfactor > inputlength) {
882 err_setstr(SvError, "input buffer not long enough");
883 return NULL;
884 }
885
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +0000886 output = newsizedstringobject(NULL, (int) (width * height * factor));
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000887 if (output == NULL)
888 return NULL;
889
890 (*function)(invert, input, getstringvalue(output), width, height);
891
892 return output;
893}
894
895static object *
896sv_InterleaveFields(self, args)
897 object *self, *args;
898{
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +0000899 return sv_conversion(self, args, svInterleaveFields, 1, 1.0);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000900}
901
902static object *
903sv_RGB8toRGB32(self, args)
904 object *self, *args;
905{
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +0000906 return sv_conversion(self, args, svRGB8toRGB32, 1, (float) sizeof(long));
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000907}
908
909static object *
910sv_YUVtoRGB(self, args)
911 object *self, *args;
912{
Sjoerd Mullender6b517fd1993-03-16 12:25:30 +0000913 return sv_conversion(self, args, svYUVtoRGB, 2, (float) sizeof(long));
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000914}
915
916static void
917svideo_dealloc(self)
918 svobject *self;
919{
920 if (self->ob_svideo != NULL)
921 (void) svCloseVideo(self->ob_svideo);
922 DEL(self);
923}
924
925static object *
926svideo_getattr(self, name)
927 svobject *self;
928 char *name;
929{
930 return findmethod(svideo_methods, (object *)self, name);
931}
932
933typeobject Svtype = {
934 OB_HEAD_INIT(&Typetype)
935 0, /*ob_size*/
936 "sv", /*tp_name*/
937 sizeof(svobject), /*tp_size*/
938 0, /*tp_itemsize*/
939 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000940 (destructor)svideo_dealloc, /*tp_dealloc*/
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000941 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000942 (getattrfunc)svideo_getattr, /*tp_getattr*/
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000943 0, /*tp_setattr*/
944 0, /*tp_compare*/
945 0, /*tp_repr*/
946};
947
948static object *
949newsvobject(svp)
950 SV_nodeP svp;
951{
952 svobject *p;
953
954 p = NEWOBJ(svobject, &Svtype);
955 if (p == NULL)
956 return NULL;
957 p->ob_svideo = svp;
958 p->ob_info.format = 0;
959 p->ob_info.size = 0;
960 p->ob_info.width = 0;
961 p->ob_info.height = 0;
962 p->ob_info.samplingrate = 0;
963 return (object *) p;
964}
965
966static object *
967sv_OpenVideo(self, args)
968 object *self, *args;
969{
970 SV_nodeP svp;
971
972 if (!getnoarg(args))
973 return NULL;
974
975 svp = svOpenVideo();
976 if (svp == NULL)
977 return sv_error();
978
979 return newsvobject(svp);
980}
981
982static struct methodlist sv_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000983 {"InterleaveFields", (method)sv_InterleaveFields},
984 {"RGB8toRGB32", (method)sv_RGB8toRGB32},
985 {"YUVtoRGB", (method)sv_YUVtoRGB},
986 {"OpenVideo", (method)sv_OpenVideo},
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000987 {NULL, NULL} /* Sentinel */
988};
989
990void
991initsv()
992{
993 object *m, *d;
994
995 m = initmodule("sv", sv_methods);
996 d = getmoduledict(m);
997
998 SvError = newstringobject("sv.error");
999 if (SvError == NULL || dictinsert(d, "error", SvError) != 0)
1000 fatal("can't define sv.error");
1001}