blob: bbdbf33bbfe3c698390fa4b6132b2251cb56a6e2 [file] [log] [blame]
Sjoerd Mullendered59d201993-01-06 13:36:38 +00001/**********************************************************
Guido van Rossum34679b71993-01-26 13:33:44 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The 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"
34
35typedef struct {
36 OB_HEAD
37 SV_nodeP ob_svideo;
38 svCaptureInfo ob_info;
39} svobject;
40
41typedef struct {
42 OB_HEAD
43 void *ob_capture;
44 int ob_mustunlock;
45 svCaptureInfo ob_info;
46 svobject *ob_svideo;
47} captureobject;
48
49static object *SvError; /* exception sv.error */
50
51static object *newcaptureobject PROTO((svobject *, void *, int));
52
53/* Set a SV-specific error from svideo_errno and return NULL */
54static object *
55sv_error()
56{
57 err_setstr(SvError, svStrerror(svideo_errno));
58 return NULL;
59}
60
61static object *
62svc_conversion(self, args, function, factor)
63 captureobject *self;
64 object *args;
65 void (*function)();
66 int factor;
67{
68 object *output;
69 int invert;
70
71 if (!getargs(args, "i", &invert))
72 return NULL;
73
74 output = newsizedstringobject(NULL, self->ob_info.width * self->ob_info.height * factor);
75 if (output == NULL)
76 return NULL;
77
78 (*function)((boolean) invert, self->ob_capture, getstringvalue(output),
79 self->ob_info.width, self->ob_info.height);
80
81 return output;
82}
83
84static object *
85svc_YUVtoRGB(self, args)
86 captureobject *self;
87 object *args;
88{
89 switch (self->ob_info.format) {
90 case SV_YUV411_FRAMES:
91 case SV_YUV411_FRAMES_AND_BLANKING_BUFFER:
92 break;
93 default:
94 err_setstr(SvError, "data had bad format");
95 return NULL;
96 }
97 return svc_conversion(self, args, svYUVtoRGB, sizeof(long));
98}
99
100static object *
101svc_RGB8toRGB32(self, args)
102 captureobject *self;
103 object *args;
104{
105 if (self->ob_info.format != SV_RGB8_FRAMES) {
106 err_setstr(SvError, "data has bad format");
107 return NULL;
108 }
109 return svc_conversion(self, args, svRGB8toRGB32, sizeof(long));
110}
111
112static object *
113svc_InterleaveFields(self, args)
114 captureobject *self;
115 object *args;
116{
117 if (self->ob_info.format != SV_RGB8_FRAMES) {
118 err_setstr(SvError, "data has bad format");
119 return NULL;
120 }
121 return svc_conversion(self, args, svInterleaveFields, 1);
122}
123
124static object *
125svc_GetFields(self, args)
126 captureobject *self;
127 object *args;
128{
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000129 object *f1, *f2, *ret;
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000130 int fieldsize;
131
132 if (self->ob_info.format != SV_RGB8_FRAMES) {
133 err_setstr(SvError, "data has bad format");
134 return NULL;
135 }
136
137 fieldsize = self->ob_info.width * self->ob_info.height / 2;
138 f1 = newsizedstringobject((char *) self->ob_capture, fieldsize);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000139 f2 = newsizedstringobject((char *) self->ob_capture + fieldsize, fieldsize);
Guido van Rossum6f5afc91993-02-05 09:46:15 +0000140 ret = mkvalue("(OO)", f1, f2);
141 XDECREF(f1);
142 XDECREF(f2);
143 return ret;
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000144}
145
146static object *
147svc_UnlockCaptureData(self, args)
148 captureobject *self;
149 object *args;
150{
151 if (!getnoarg(args))
152 return NULL;
153
154 if (!self->ob_mustunlock) {
155 err_setstr(SvError, "buffer should not be unlocked");
156 return NULL;
157 }
158
159 if (svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture))
160 return sv_error();
161
162 self->ob_mustunlock = 0;
163
164 INCREF(None);
165 return None;
166}
167
168#ifdef USE_GL
169#include <gl.h>
170
171static object *
172svc_lrectwrite(self, args)
173 captureobject *self;
174 object *args;
175{
176 Screencoord x1, x2, y1, y2;
177
178 if (!getargs(args, "(hhhh)", &x1, &x2, &y1, &y2))
179 return NULL;
180
181 lrectwrite(x1, x2, y1, y2, (unsigned long *) self->ob_capture);
182
183 INCREF(None);
184 return None;
185}
186#endif
187
188static object *
189writefile(self, args)
190 captureobject *self;
191 object *args;
192{
193 object *file;
194 int size;
195
196 if (!getargs(args, "O", &file))
197 return NULL;
198
199 if (!is_fileobject(file)) {
200 err_setstr(SvError, "not a file object");
201 return NULL;
202 }
203
204 size = self->ob_info.width * self->ob_info.height;
205
206 if (fwrite(self->ob_capture, sizeof(long), size, getfilefile(file)) != size) {
207 err_setstr(SvError, "writing failed");
208 return NULL;
209 }
210
211 INCREF(None);
212 return None;
213}
214
215static object *
216svc_FindVisibleRegion(self, args)
217 captureobject *self;
218 object *args;
219{
220 void *visible;
221 int width;
222
223 if (!getnoarg(args))
224 return NULL;
225
226 if (svFindVisibleRegion(self->ob_svideo->ob_svideo, self->ob_capture, &visible, self->ob_info.width))
227 return sv_error();
228
229 if (visible == NULL) {
230 err_setstr(SvError, "data in wrong format");
231 return NULL;
232 }
233
234 return newcaptureobject(self->ob_svideo, visible, 0);
235}
236
237static struct methodlist capture_methods[] = {
238 {"YUVtoRGB", svc_YUVtoRGB},
239 {"RGB8toRGB32", svc_RGB8toRGB32},
240 {"InterleaveFields", svc_InterleaveFields},
241 {"UnlockCaptureData", svc_UnlockCaptureData},
242 {"FindVisibleRegion", svc_FindVisibleRegion},
243 {"GetFields", svc_GetFields},
244#ifdef USE_GL
245 {"lrectwrite", svc_lrectwrite},
246#endif
247 {"writefile", writefile},
248 {NULL, NULL} /* sentinel */
249};
250
251static void
252capture_dealloc(self)
253 captureobject *self;
254{
255 if (self->ob_capture != NULL) {
256 if (self->ob_mustunlock)
257 (void) svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture);
258 self->ob_capture = NULL;
259 DECREF(self->ob_svideo);
260 self->ob_svideo = NULL;
261 }
262 DEL(self);
263}
264
265static object *
266capture_getattr(self, name)
267 svobject *self;
268 char *name;
269{
270 return findmethod(capture_methods, (object *)self, name);
271}
272
273typeobject Capturetype = {
274 OB_HEAD_INIT(&Typetype)
275 0, /*ob_size*/
276 "capture", /*tp_name*/
277 sizeof(captureobject), /*tp_size*/
278 0, /*tp_itemsize*/
279 /* methods */
280 capture_dealloc, /*tp_dealloc*/
281 0, /*tp_print*/
282 capture_getattr, /*tp_getattr*/
283 0, /*tp_setattr*/
284 0, /*tp_compare*/
285 0, /*tp_repr*/
286};
287
288static object *
289newcaptureobject(self, ptr, mustunlock)
290 svobject *self;
291 void *ptr;
292 int mustunlock;
293{
294 captureobject *p;
295
296 p = NEWOBJ(captureobject, &Capturetype);
297 if (p == NULL)
298 return NULL;
299 p->ob_svideo = self;
300 INCREF(self);
301 p->ob_capture = ptr;
302 p->ob_mustunlock = mustunlock;
303 p->ob_info = self->ob_info;
304 return (object *) p;
305}
306
307static object *
308sv_GetCaptureData(self, args)
309 svobject *self;
310 object *args;
311{
312 void *ptr;
313 long fieldID;
314 object *res, *c;
315
316 if (!getnoarg(args))
317 return NULL;
318
319 if (svGetCaptureData(self->ob_svideo, &ptr, &fieldID))
320 return sv_error();
321
322 if (ptr == NULL) {
323 err_setstr(SvError, "no data available");
324 return NULL;
325 }
326
327 c = newcaptureobject(self, ptr, 1);
328 if (c == NULL)
329 return NULL;
330 res = mkvalue("(Oi)", c, fieldID);
331 DECREF(c);
332 return res;
333}
334
335static object *
336sv_BindGLWindow(self, args)
337 svobject *self;
338 object *args;
339{
340 long wid;
341 int mode;
342
343 if (!getargs(args, "(ii)", &wid, &mode))
344 return NULL;
345
346 if (svBindGLWindow(self->ob_svideo, wid, mode))
347 return sv_error();
348
349 INCREF(None);
350 return None;
351}
352
353static object *
354sv_EndContinuousCapture(self, args)
355 svobject *self;
356 object *args;
357{
358
359 if (!getnoarg(args))
360 return NULL;
361
362 if (svEndContinuousCapture(self->ob_svideo))
363 return sv_error();
364
365 INCREF(None);
366 return None;
367}
368
369static object *
370sv_IsVideoDisplayed(self, args)
371 svobject *self;
372 object *args;
373{
374 int v;
375
376 if (!getnoarg(args))
377 return NULL;
378
379 v = svIsVideoDisplayed(self->ob_svideo);
380 if (v == -1)
381 return sv_error();
382
383 return newintobject((long) v);
384}
385
386static object *
387sv_OutputOffset(self, args)
388 svobject *self;
389 object *args;
390{
391 int x_offset;
392 int y_offset;
393
394 if (!getargs(args, "(ii)", &x_offset, &y_offset))
395 return NULL;
396
397 if (svOutputOffset(self->ob_svideo, x_offset, y_offset))
398 return sv_error();
399
400 INCREF(None);
401 return None;
402}
403
404static object *
405sv_PutFrame(self, args)
406 svobject *self;
407 object *args;
408{
409 char *buffer;
410
411 if (!getargs(args, "s", &buffer))
412 return NULL;
413
414 if (svPutFrame(self->ob_svideo, buffer))
415 return sv_error();
416
417 INCREF(None);
418 return None;
419}
420
421static object *
422sv_QuerySize(self, args)
423 svobject *self;
424 object *args;
425{
426 int w;
427 int h;
428 int rw;
429 int rh;
430
431 if (!getargs(args, "(ii)", &w, &h))
432 return NULL;
433
434 if (svQuerySize(self->ob_svideo, w, h, &rw, &rh))
435 return sv_error();
436
437 return mkvalue("(ii)", (long) rw, (long) rh);
438}
439
440static object *
441sv_SetSize(self, args)
442 svobject *self;
443 object *args;
444{
445 int w;
446 int h;
447
448 if (!getargs(args, "(ii)", &w, &h))
449 return NULL;
450
451 if (svSetSize(self->ob_svideo, w, h))
452 return sv_error();
453
454 INCREF(None);
455 return None;
456}
457
458static object *
459sv_SetStdDefaults(self, args)
460 svobject *self;
461 object *args;
462{
463
464 if (!getnoarg(args))
465 return NULL;
466
467 if (svSetStdDefaults(self->ob_svideo))
468 return sv_error();
469
470 INCREF(None);
471 return None;
472}
473
474static object *
475sv_UseExclusive(self, args)
476 svobject *self;
477 object *args;
478{
479 boolean onoff;
480 int mode;
481
482 if (!getargs(args, "(ii)", &onoff, &mode))
483 return NULL;
484
485 if (svUseExclusive(self->ob_svideo, onoff, mode))
486 return sv_error();
487
488 INCREF(None);
489 return None;
490}
491
492static object *
493sv_WindowOffset(self, args)
494 svobject *self;
495 object *args;
496{
497 int x_offset;
498 int y_offset;
499
500 if (!getargs(args, "(ii)", &x_offset, &y_offset))
501 return NULL;
502
503 if (svWindowOffset(self->ob_svideo, x_offset, y_offset))
504 return sv_error();
505
506 INCREF(None);
507 return None;
508}
509
510static object *
511sv_CaptureBurst(self, args)
512 svobject *self;
513 object *args;
514{
515 int bytes, i;
516 svCaptureInfo info;
517 void *bitvector = NULL;
518 object *videodata, *bitvecobj, *res;
519 static object *evenitem, *odditem;
520
521 if (!getargs(args, "(iiiii)", &info.format, &info.width, &info.height,
522 &info.size, &info.samplingrate))
523 return NULL;
524
525 switch (info.format) {
526 case SV_RGB8_FRAMES:
527 bitvector = malloc(SV_BITVEC_SIZE(info.size));
528 break;
529 case SV_YUV411_FRAMES_AND_BLANKING_BUFFER:
530 break;
531 default:
532 err_setstr(SvError, "illegal format specified");
533 return NULL;
534 }
535
536 if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) {
537 if (bitvector)
538 free(bitvector);
539 return sv_error();
540 }
541
542 videodata = newsizedstringobject(NULL, bytes);
543 if (videodata == NULL) {
544 if (bitvector)
545 free(bitvector);
546 return NULL;
547 }
548
549 /* XXX -- need to do something about the bitvector */
550 if (svCaptureBurst(self->ob_svideo, &info, getstringvalue(videodata),
551 bitvector)) {
552 if (bitvector)
553 free(bitvector);
554 DECREF(videodata);
555 return sv_error();
556 }
557
558 if (bitvector) {
559 if (evenitem == NULL) {
560 evenitem = newintobject(0);
561 if (evenitem == NULL) {
562 free(bitvector);
563 DECREF(videodata);
564 return NULL;
565 }
566 }
567 if (odditem == NULL) {
568 odditem = newintobject(1);
569 if (odditem == NULL) {
570 free(bitvector);
571 DECREF(videodata);
572 return NULL;
573 }
574 }
575 bitvecobj = newtupleobject(2 * info.size);
576 if (bitvecobj == NULL) {
577 free(bitvecobj);
578 DECREF(videodata);
579 return NULL;
580 }
581 for (i = 0; i < 2 * info.size; i++) {
582 if (SV_GET_FIELD(bitvector, i) == SV_EVEN_FIELD) {
583 INCREF(evenitem);
584 settupleitem(bitvecobj, i, evenitem);
585 } else {
586 INCREF(odditem);
587 settupleitem(bitvecobj, i, odditem);
588 }
589 }
590 free(bitvector);
591 } else {
592 bitvecobj = None;
593 INCREF(None);
594 }
595
596 res = mkvalue("((iiiii)OO)", info.format, info.width, info.height,
597 info.size, info.samplingrate, videodata, bitvecobj);
598 DECREF(videodata);
599 DECREF(bitvecobj);
600 return res;
601}
602
603static object *
604sv_CaptureOneFrame(self, args)
605 svobject *self;
606 object *args;
607{
608 svCaptureInfo info;
609 int format, width, height;
610 int bytes;
611 object *videodata, *res;
612
613 if (!getargs(args, "(iii)", &format, &width, &height))
614 return NULL;
615 info.format = format;
616 info.width = width;
617 info.height = height;
618 info.size = 0;
619 info.samplingrate = 0;
620 if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes))
621 return sv_error();
622 videodata = newsizedstringobject(NULL, bytes);
623 if (videodata == NULL)
624 return NULL;
625 if (svCaptureOneFrame(self->ob_svideo, format, &width, &height,
626 getstringvalue(videodata))) {
627 DECREF(videodata);
628 return sv_error();
629 }
630
631 res = mkvalue("(iiO)", width, height, videodata);
632 DECREF(videodata);
633 return res;
634}
635
636static object *
637sv_InitContinuousCapture(self, args)
638 svobject *self;
639 object *args;
640{
641 svCaptureInfo info;
642
643 if (!getargs(args, "(iiiii)", &info.format, &info.width, &info.height,
644 &info.size, &info.samplingrate))
645 return NULL;
646
647 if (svInitContinuousCapture(self->ob_svideo, &info))
648 return sv_error();
649
650 self->ob_info = info;
651
652 return mkvalue("(iiiii)", info.format, info.width, info.height,
653 info.size, info.samplingrate);
654}
655
656static object *
657sv_LoadMap(self, args)
658 svobject *self;
659 object *args;
660{
661 object *rgb, *v, *cell;
662 rgb_tuple *mapp;
663 int maptype;
664 int i, j; /* indices */
665
666 if (!getargs(args, "(iO)", &maptype, &rgb))
667 return NULL;
668 if (!is_listobject(rgb) || getlistsize(rgb) != 256) {
669 err_badarg();
670 return NULL;
671 }
672 mapp = NEW(rgb_tuple, 256);
673 if (mapp == NULL)
674 return err_nomem();
675 for (i = 0; i < 256; i++) {
676 v = getlistitem(rgb, i);
677 if (!is_tupleobject(v) || gettuplesize(v) != 3) {
678 DEL(mapp);
679 err_badarg();
680 return NULL;
681 }
682 for (j = 0; j < 3; j++) {
683 cell = gettupleitem(v, j);
684 if (!is_intobject(cell)) {
685 DEL(mapp);
686 err_badarg();
687 return NULL;
688 }
689 switch (j) {
690 case 0: mapp[i].red = getintvalue(cell); break;
691 case 1: mapp[i].blue = getintvalue(cell); break;
692 case 2: mapp[i].green = getintvalue(cell); break;
693 }
694 }
695 }
696
697 if (svLoadMap(self->ob_svideo, maptype, mapp)) {
698 DEL(mapp);
699 return sv_error();
700 }
701
702 DEL(mapp);
703
704 INCREF(None);
705 return None;
706}
707
708static object *
709sv_CloseVideo(self, args)
710 svobject *self;
711 object *args;
712{
713 if (!getnoarg(args))
714 return NULL;
715
716 if (svCloseVideo(self->ob_svideo))
717 return sv_error();
718 self->ob_svideo = NULL;
719
720 INCREF(None);
721 return None;
722}
723
724static object *
725doParams(self, args, func, modified)
726 svobject *self;
727 object *args;
728 int (*func)(SV_nodeP, long *, int);
729 int modified;
730{
731 object *list, *v;
732 long *PVbuffer;
733 long length;
734 int i;
735
736 if (!getargs(args, "O", &list))
737 return NULL;
738 if (!is_listobject(list)) {
739 err_badarg();
740 return NULL;
741 }
742 length = getlistsize(list);
743 PVbuffer = NEW(long, length);
744 if (PVbuffer == NULL)
745 return err_nomem();
746 for (i = 0; i < length; i++) {
747 v = getlistitem(list, i);
748 if (!is_intobject(v)) {
749 DEL(PVbuffer);
750 err_badarg();
751 return NULL;
752 }
753 PVbuffer[i] = getintvalue(v);
754 }
755
756 if ((*func)(self->ob_svideo, PVbuffer, length)) {
757 DEL(PVbuffer);
758 return sv_error();
759 }
760
761 if (modified) {
762 for (i = 0; i < length; i++)
763 setlistitem(list, i, newintobject(PVbuffer[i]));
764 }
765
766 DEL(PVbuffer);
767
768 INCREF(None);
769 return None;
770}
771
772static object *
773sv_GetParam(self, args)
774 object *self, *args;
775{
776 return doParams(self, args, svGetParam, 1);
777}
778
779static object *
780sv_GetParamRange(self, args)
781 object *self, *args;
782{
783 return doParams(self, args, svGetParamRange, 1);
784}
785
786static object *
787sv_SetParam(self, args)
788 object *self, *args;
789{
790 return doParams(self, args, svSetParam, 0);
791}
792
793static struct methodlist svideo_methods[] = {
794 {"BindGLWindow", sv_BindGLWindow},
795 {"EndContinuousCapture",sv_EndContinuousCapture},
796 {"IsVideoDisplayed", sv_IsVideoDisplayed},
797 {"OutputOffset", sv_OutputOffset},
798 {"PutFrame", sv_PutFrame},
799 {"QuerySize", sv_QuerySize},
800 {"SetSize", sv_SetSize},
801 {"SetStdDefaults", sv_SetStdDefaults},
802 {"UseExclusive", sv_UseExclusive},
803 {"WindowOffset", sv_WindowOffset},
804 {"InitContinuousCapture",sv_InitContinuousCapture},
805 {"CaptureBurst", sv_CaptureBurst},
806 {"CaptureOneFrame", sv_CaptureOneFrame},
807 {"GetCaptureData", sv_GetCaptureData},
808 {"CloseVideo", sv_CloseVideo},
809 {"LoadMap", sv_LoadMap},
810 {"GetParam", sv_GetParam},
811 {"GetParamRange", sv_GetParamRange},
812 {"SetParam", sv_SetParam},
813 {NULL, NULL} /* sentinel */
814};
815
816static object *
817sv_conversion(self, args, function, inputfactor, factor)
818 object *self, *args;
819 void (*function)();
820 int inputfactor, factor;
821{
822 int invert, width, height, inputlength;
823 char *input;
824 object *output;
825
826 if (!getargs(args, "(is#ii)", &invert, &input, &inputlength, &width, &height))
827 return NULL;
828
829 if (width * height * inputfactor > inputlength) {
830 err_setstr(SvError, "input buffer not long enough");
831 return NULL;
832 }
833
834 output = newsizedstringobject(NULL, width * height * factor);
835 if (output == NULL)
836 return NULL;
837
838 (*function)(invert, input, getstringvalue(output), width, height);
839
840 return output;
841}
842
843static object *
844sv_InterleaveFields(self, args)
845 object *self, *args;
846{
847 return sv_conversion(self, args, svInterleaveFields, 1, 1);
848}
849
850static object *
851sv_RGB8toRGB32(self, args)
852 object *self, *args;
853{
854 return sv_conversion(self, args, svRGB8toRGB32, 1, sizeof(long));
855}
856
857static object *
858sv_YUVtoRGB(self, args)
859 object *self, *args;
860{
861 return sv_conversion(self, args, svYUVtoRGB, 2, sizeof(long));
862}
863
864static void
865svideo_dealloc(self)
866 svobject *self;
867{
868 if (self->ob_svideo != NULL)
869 (void) svCloseVideo(self->ob_svideo);
870 DEL(self);
871}
872
873static object *
874svideo_getattr(self, name)
875 svobject *self;
876 char *name;
877{
878 return findmethod(svideo_methods, (object *)self, name);
879}
880
881typeobject Svtype = {
882 OB_HEAD_INIT(&Typetype)
883 0, /*ob_size*/
884 "sv", /*tp_name*/
885 sizeof(svobject), /*tp_size*/
886 0, /*tp_itemsize*/
887 /* methods */
888 svideo_dealloc, /*tp_dealloc*/
889 0, /*tp_print*/
890 svideo_getattr, /*tp_getattr*/
891 0, /*tp_setattr*/
892 0, /*tp_compare*/
893 0, /*tp_repr*/
894};
895
896static object *
897newsvobject(svp)
898 SV_nodeP svp;
899{
900 svobject *p;
901
902 p = NEWOBJ(svobject, &Svtype);
903 if (p == NULL)
904 return NULL;
905 p->ob_svideo = svp;
906 p->ob_info.format = 0;
907 p->ob_info.size = 0;
908 p->ob_info.width = 0;
909 p->ob_info.height = 0;
910 p->ob_info.samplingrate = 0;
911 return (object *) p;
912}
913
914static object *
915sv_OpenVideo(self, args)
916 object *self, *args;
917{
918 SV_nodeP svp;
919
920 if (!getnoarg(args))
921 return NULL;
922
923 svp = svOpenVideo();
924 if (svp == NULL)
925 return sv_error();
926
927 return newsvobject(svp);
928}
929
930static struct methodlist sv_methods[] = {
931 {"InterleaveFields", sv_InterleaveFields},
932 {"RGB8toRGB32", sv_RGB8toRGB32},
933 {"YUVtoRGB", sv_YUVtoRGB},
934 {"OpenVideo", sv_OpenVideo},
935 {NULL, NULL} /* Sentinel */
936};
937
938void
939initsv()
940{
941 object *m, *d;
942
943 m = initmodule("sv", sv_methods);
944 d = getmoduledict(m);
945
946 SvError = newstringobject("sv.error");
947 if (SvError == NULL || dictinsert(d, "error", SvError) != 0)
948 fatal("can't define sv.error");
949}