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