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