| /* SV module -- interface to the Indigo video board */ | 
 |  | 
 | /* WARNING! This module is for hardware that we don't have any more, | 
 |    so it hasn't been tested.  It has been converted to the new coding | 
 |    style, and it is possible that this conversion has broken something | 
 |    -- user beware! */ | 
 |  | 
 | #include <sys/time.h> | 
 | #include <svideo.h> | 
 | #include "Python.h" | 
 | #include "compile.h" | 
 | #include "yuv.h"                /* for YUV conversion functions */ | 
 |  | 
 | typedef struct { | 
 |     PyObject_HEAD | 
 |     SV_nodeP ob_svideo; | 
 |     svCaptureInfo ob_info; | 
 | } svobject; | 
 |  | 
 | typedef struct { | 
 |     PyObject_HEAD | 
 |     void *ob_capture; | 
 |     int ob_mustunlock; | 
 |     svCaptureInfo ob_info; | 
 |     svobject *ob_svideo; | 
 | } captureobject; | 
 |  | 
 | static PyObject *SvError;               /* exception sv.error */ | 
 |  | 
 | static PyObject *newcaptureobject(svobject *, void *, int); | 
 |  | 
 | /* Set a SV-specific error from svideo_errno and return NULL */ | 
 | static PyObject * | 
 | sv_error(void) | 
 | { | 
 |     PyErr_SetString(SvError, svStrerror(svideo_errno)); | 
 |     return NULL; | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_conversion(captureobject *self, PyObject *args, void (*function)(), float factor) | 
 | { | 
 |     PyObject *output; | 
 |     int invert; | 
 |     char* outstr; | 
 |  | 
 |     if (!PyArg_Parse(args, "i", &invert)) | 
 |         return NULL; | 
 |  | 
 |     if (!(output = PyString_FromStringAndSize( | 
 |         NULL, | 
 |         (int)(self->ob_info.width * self->ob_info.height * factor)))) | 
 |     { | 
 |         return NULL; | 
 |     } | 
 |     if (!(outstr = PyString_AsString(output))) { | 
 |         Py_DECREF(output); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     (*function)((boolean)invert, self->ob_capture, | 
 |                 outstr, | 
 |                 self->ob_info.width, self->ob_info.height); | 
 |  | 
 |     return output; | 
 | } | 
 |  | 
 | /* | 
 |  * 3 functions to convert from Starter Video YUV 4:1:1 format to | 
 |  * Compression Library 4:2:2 Duplicate Chroma format. | 
 |  */ | 
 | static PyObject * | 
 | svc_YUVtoYUV422DC(captureobject *self, PyObject *args) | 
 | { | 
 |     if (self->ob_info.format != SV_YUV411_FRAMES) { | 
 |         PyErr_SetString(SvError, "data has bad format"); | 
 |         return NULL; | 
 |     } | 
 |     return svc_conversion(self, args, yuv_sv411_to_cl422dc, 2.0); | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_YUVtoYUV422DC_quarter(captureobject *self, PyObject *args) | 
 | { | 
 |     if (self->ob_info.format != SV_YUV411_FRAMES) { | 
 |         PyErr_SetString(SvError, "data has bad format"); | 
 |         return NULL; | 
 |     } | 
 |     return svc_conversion(self, args, | 
 |                           yuv_sv411_to_cl422dc_quartersize, 0.5); | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_YUVtoYUV422DC_sixteenth(captureobject *self, PyObject *args) | 
 | { | 
 |     if (self->ob_info.format != SV_YUV411_FRAMES) { | 
 |         PyErr_SetString(SvError, "data has bad format"); | 
 |         return NULL; | 
 |     } | 
 |     return svc_conversion(self, args, | 
 |                           yuv_sv411_to_cl422dc_sixteenthsize, 0.125); | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_YUVtoRGB(captureobject *self, PyObject *args) | 
 | { | 
 |     switch (self->ob_info.format) { | 
 |     case SV_YUV411_FRAMES: | 
 |     case SV_YUV411_FRAMES_AND_BLANKING_BUFFER: | 
 |         break; | 
 |     default: | 
 |         PyErr_SetString(SvError, "data had bad format"); | 
 |         return NULL; | 
 |     } | 
 |     return svc_conversion(self, args, svYUVtoRGB, (float) sizeof(long)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_RGB8toRGB32(captureobject *self, PyObject *args) | 
 | { | 
 |     if (self->ob_info.format != SV_RGB8_FRAMES) { | 
 |         PyErr_SetString(SvError, "data has bad format"); | 
 |         return NULL; | 
 |     } | 
 |     return svc_conversion(self, args, svRGB8toRGB32, (float) sizeof(long)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_InterleaveFields(captureobject *self, PyObject *args) | 
 | { | 
 |     if (self->ob_info.format != SV_RGB8_FRAMES) { | 
 |         PyErr_SetString(SvError, "data has bad format"); | 
 |         return NULL; | 
 |     } | 
 |     return svc_conversion(self, args, svInterleaveFields, 1.0); | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_GetFields(captureobject *self, PyObject *args) | 
 | { | 
 |     PyObject *f1 = NULL; | 
 |     PyObject *f2 = NULL; | 
 |     PyObject *ret = NULL; | 
 |     int fieldsize; | 
 |     char* obcapture; | 
 |  | 
 |     if (self->ob_info.format != SV_RGB8_FRAMES) { | 
 |         PyErr_SetString(SvError, "data has bad format"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     fieldsize = self->ob_info.width * self->ob_info.height / 2; | 
 |     obcapture = (char*)self->ob_capture; | 
 |  | 
 |     if (!(f1 = PyString_FromStringAndSize(obcapture, fieldsize))) | 
 |         goto finally; | 
 |     if (!(f2 = PyString_FromStringAndSize(obcapture + fieldsize, | 
 |                                           fieldsize))) | 
 |         goto finally; | 
 |     ret = PyTuple_Pack(2, f1, f2); | 
 |  | 
 |   finally: | 
 |     Py_XDECREF(f1); | 
 |     Py_XDECREF(f2); | 
 |     return ret; | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_UnlockCaptureData(captureobject *self, PyObject *args) | 
 | { | 
 |     if (!PyArg_Parse(args, "")) | 
 |         return NULL; | 
 |  | 
 |     if (!self->ob_mustunlock) { | 
 |         PyErr_SetString(SvError, "buffer should not be unlocked"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture)) | 
 |         return sv_error(); | 
 |  | 
 |     self->ob_mustunlock = 0; | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | #ifdef USE_GL | 
 | #include <gl.h> | 
 |  | 
 | static PyObject * | 
 | svc_lrectwrite(captureobject *self, PyObject *args) | 
 | { | 
 |     Screencoord x1, x2, y1, y2; | 
 |  | 
 |     if (!PyArg_Parse(args, "(hhhh)", &x1, &x2, &y1, &y2)) | 
 |         return NULL; | 
 |  | 
 |     lrectwrite(x1, x2, y1, y2, (unsigned long *) self->ob_capture); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 | #endif | 
 |  | 
 | static PyObject * | 
 | svc_writefile(captureobject *self, PyObject *args) | 
 | { | 
 |     PyObject *file; | 
 |     int size; | 
 |     FILE* fp; | 
 |  | 
 |     if (!PyArg_Parse(args, "O", &file)) | 
 |         return NULL; | 
 |  | 
 |     if (!PyFile_Check(file)) { | 
 |         PyErr_SetString(SvError, "not a file object"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (!(fp = PyFile_AsFile(file))) | 
 |         return NULL; | 
 |  | 
 |     size = self->ob_info.width * self->ob_info.height; | 
 |  | 
 |     if (fwrite(self->ob_capture, sizeof(long), size, fp) != size) { | 
 |         PyErr_SetString(SvError, "writing failed"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | svc_FindVisibleRegion(captureobject *self, PyObject *args) | 
 | { | 
 |     void *visible; | 
 |     int width; | 
 |  | 
 |     if (!PyArg_Parse(args, "")) | 
 |         return NULL; | 
 |  | 
 |     if (svFindVisibleRegion(self->ob_svideo->ob_svideo, | 
 |                             self->ob_capture, &visible, | 
 |                             self->ob_info.width)) | 
 |         return sv_error(); | 
 |  | 
 |     if (visible == NULL) { | 
 |         PyErr_SetString(SvError, "data in wrong format"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     return newcaptureobject(self->ob_svideo, visible, 0); | 
 | } | 
 |  | 
 | static PyMethodDef capture_methods[] = { | 
 |     {"YUVtoRGB",                (PyCFunction)svc_YUVtoRGB, METH_OLDARGS}, | 
 |     {"RGB8toRGB32",             (PyCFunction)svc_RGB8toRGB32, METH_OLDARGS}, | 
 |     {"InterleaveFields",        (PyCFunction)svc_InterleaveFields, METH_OLDARGS}, | 
 |     {"UnlockCaptureData",       (PyCFunction)svc_UnlockCaptureData, METH_OLDARGS}, | 
 |     {"FindVisibleRegion",       (PyCFunction)svc_FindVisibleRegion, METH_OLDARGS}, | 
 |     {"GetFields",               (PyCFunction)svc_GetFields, METH_OLDARGS}, | 
 |     {"YUVtoYUV422DC",           (PyCFunction)svc_YUVtoYUV422DC, METH_OLDARGS}, | 
 |     {"YUVtoYUV422DC_quarter",(PyCFunction)svc_YUVtoYUV422DC_quarter, METH_OLDARGS}, | 
 |     {"YUVtoYUV422DC_sixteenth",(PyCFunction)svc_YUVtoYUV422DC_sixteenth, METH_OLDARGS}, | 
 | #ifdef USE_GL | 
 |     {"lrectwrite",              (PyCFunction)svc_lrectwrite, METH_OLDARGS}, | 
 | #endif | 
 |     {"writefile",               (PyCFunction)svc_writefile, METH_OLDARGS}, | 
 |     {NULL,                      NULL}           /* sentinel */ | 
 | }; | 
 |  | 
 | static void | 
 | capture_dealloc(captureobject *self) | 
 | { | 
 |     if (self->ob_capture != NULL) { | 
 |         if (self->ob_mustunlock) | 
 |             (void)svUnlockCaptureData(self->ob_svideo->ob_svideo, | 
 |                                       self->ob_capture); | 
 |         self->ob_capture = NULL; | 
 |         Py_CLEAR(self->ob_svideo); | 
 |     } | 
 |     PyObject_Del(self); | 
 | } | 
 |  | 
 | static PyObject * | 
 | capture_getattr(svobject *self, char *name) | 
 | { | 
 |     return Py_FindMethod(capture_methods, (PyObject *)self, name); | 
 | } | 
 |  | 
 | PyTypeObject Capturetype = { | 
 |     PyObject_HEAD_INIT(&PyType_Type) | 
 |     0,                                  /*ob_size*/ | 
 |     "sv.capture",                       /*tp_name*/ | 
 |     sizeof(captureobject),              /*tp_size*/ | 
 |     0,                                  /*tp_itemsize*/ | 
 |     /* methods */ | 
 |     (destructor)capture_dealloc,        /*tp_dealloc*/ | 
 |     0,                                  /*tp_print*/ | 
 |     (getattrfunc)capture_getattr,       /*tp_getattr*/ | 
 |     0,                                  /*tp_setattr*/ | 
 |     0,                                  /*tp_compare*/ | 
 |     0,                                  /*tp_repr*/ | 
 | }; | 
 |  | 
 | static PyObject * | 
 | newcaptureobject(svobject *self, void *ptr, int mustunlock) | 
 | { | 
 |     captureobject *p; | 
 |  | 
 |     p = PyObject_New(captureobject, &Capturetype); | 
 |     if (p == NULL) | 
 |         return NULL; | 
 |     p->ob_svideo = self; | 
 |     Py_INCREF(self); | 
 |     p->ob_capture = ptr; | 
 |     p->ob_mustunlock = mustunlock; | 
 |     p->ob_info = self->ob_info; | 
 |     return (PyObject *) p; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_GetCaptureData(svobject *self, PyObject *args) | 
 | { | 
 |     void *ptr; | 
 |     long fieldID; | 
 |     PyObject *res, *c; | 
 |  | 
 |     if (!PyArg_Parse(args, "")) | 
 |         return NULL; | 
 |  | 
 |     if (svGetCaptureData(self->ob_svideo, &ptr, &fieldID)) | 
 |         return sv_error(); | 
 |  | 
 |     if (ptr == NULL) { | 
 |         PyErr_SetString(SvError, "no data available"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     c = newcaptureobject(self, ptr, 1); | 
 |     if (c == NULL) | 
 |         return NULL; | 
 |     res = Py_BuildValue("(Oi)", c, fieldID); | 
 |     Py_DECREF(c); | 
 |     return res; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_BindGLWindow(svobject *self, PyObject *args) | 
 | { | 
 |     long wid; | 
 |     int mode; | 
 |  | 
 |     if (!PyArg_Parse(args, "(ii)", &wid, &mode)) | 
 |         return NULL; | 
 |  | 
 |     if (svBindGLWindow(self->ob_svideo, wid, mode)) | 
 |         return sv_error(); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_EndContinuousCapture(svobject *self, PyObject *args) | 
 | { | 
 |  | 
 |     if (!PyArg_Parse(args, "")) | 
 |         return NULL; | 
 |  | 
 |     if (svEndContinuousCapture(self->ob_svideo)) | 
 |         return sv_error(); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_IsVideoDisplayed(svobject *self, PyObject *args) | 
 | { | 
 |     int v; | 
 |  | 
 |     if (!PyArg_Parse(args, "")) | 
 |         return NULL; | 
 |  | 
 |     v = svIsVideoDisplayed(self->ob_svideo); | 
 |     if (v == -1) | 
 |         return sv_error(); | 
 |  | 
 |     return PyInt_FromLong((long) v); | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_OutputOffset(svobject *self, PyObject *args) | 
 | { | 
 |     int x_offset; | 
 |     int y_offset; | 
 |  | 
 |     if (!PyArg_Parse(args, "(ii)", &x_offset, &y_offset)) | 
 |         return NULL; | 
 |  | 
 |     if (svOutputOffset(self->ob_svideo, x_offset, y_offset)) | 
 |         return sv_error(); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_PutFrame(svobject *self, PyObject *args) | 
 | { | 
 |     char *buffer; | 
 |  | 
 |     if (!PyArg_Parse(args, "s", &buffer)) | 
 |         return NULL; | 
 |  | 
 |     if (svPutFrame(self->ob_svideo, buffer)) | 
 |         return sv_error(); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_QuerySize(svobject *self, PyObject *args) | 
 | { | 
 |     int w; | 
 |     int h; | 
 |     int rw; | 
 |     int rh; | 
 |  | 
 |     if (!PyArg_Parse(args, "(ii)", &w, &h)) | 
 |         return NULL; | 
 |  | 
 |     if (svQuerySize(self->ob_svideo, w, h, &rw, &rh)) | 
 |         return sv_error(); | 
 |  | 
 |     return Py_BuildValue("(ii)", (long) rw, (long) rh); | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_SetSize(svobject *self, PyObject *args) | 
 | { | 
 |     int w; | 
 |     int h; | 
 |  | 
 |     if (!PyArg_Parse(args, "(ii)", &w, &h)) | 
 |         return NULL; | 
 |  | 
 |     if (svSetSize(self->ob_svideo, w, h)) | 
 |         return sv_error(); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_SetStdDefaults(svobject *self, PyObject *args) | 
 | { | 
 |  | 
 |     if (!PyArg_Parse(args, "")) | 
 |         return NULL; | 
 |  | 
 |     if (svSetStdDefaults(self->ob_svideo)) | 
 |         return sv_error(); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_UseExclusive(svobject *self, PyObject *args) | 
 | { | 
 |     boolean onoff; | 
 |     int mode; | 
 |  | 
 |     if (!PyArg_Parse(args, "(ii)", &onoff, &mode)) | 
 |         return NULL; | 
 |  | 
 |     if (svUseExclusive(self->ob_svideo, onoff, mode)) | 
 |         return sv_error(); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_WindowOffset(svobject *self, PyObject *args) | 
 | { | 
 |     int x_offset; | 
 |     int y_offset; | 
 |  | 
 |     if (!PyArg_Parse(args, "(ii)", &x_offset, &y_offset)) | 
 |         return NULL; | 
 |  | 
 |     if (svWindowOffset(self->ob_svideo, x_offset, y_offset)) | 
 |         return sv_error(); | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_CaptureBurst(svobject *self, PyObject *args) | 
 | { | 
 |     int bytes, i; | 
 |     svCaptureInfo info; | 
 |     void *bitvector = NULL; | 
 |     PyObject *videodata = NULL; | 
 |     PyObject *bitvecobj = NULL; | 
 |     PyObject *res = NULL; | 
 |     static PyObject *evenitem, *odditem; | 
 |  | 
 |     if (!PyArg_Parse(args, "(iiiii)", &info.format, | 
 |                      &info.width, &info.height, | 
 |                      &info.size, &info.samplingrate)) | 
 |         return NULL; | 
 |  | 
 |     switch (info.format) { | 
 |     case SV_RGB8_FRAMES: | 
 |         bitvector = malloc(SV_BITVEC_SIZE(info.size)); | 
 |         break; | 
 |     case SV_YUV411_FRAMES_AND_BLANKING_BUFFER: | 
 |         break; | 
 |     default: | 
 |         PyErr_SetString(SvError, "illegal format specified"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) { | 
 |         res = sv_error(); | 
 |         goto finally; | 
 |     } | 
 |  | 
 |     if (!(videodata = PyString_FromStringAndSize(NULL, bytes))) | 
 |         goto finally; | 
 |  | 
 |     /* XXX -- need to do something about the bitvector */ | 
 |     { | 
 |         char* str = PyString_AsString(videodata); | 
 |         if (!str) | 
 |             goto finally; | 
 |  | 
 |         if (svCaptureBurst(self->ob_svideo, &info, str, bitvector)) { | 
 |             res = sv_error(); | 
 |             goto finally; | 
 |         } | 
 |     } | 
 |  | 
 |     if (bitvector) { | 
 |         if (evenitem == NULL) { | 
 |             if (!(evenitem = PyInt_FromLong(0))) | 
 |                 goto finally; | 
 |         } | 
 |         if (odditem == NULL) { | 
 |             if (!(odditem = PyInt_FromLong(1))) | 
 |                 goto finally; | 
 |         } | 
 |         if (!(bitvecobj = PyTuple_New(2 * info.size))) | 
 |             goto finally; | 
 |  | 
 |         for (i = 0; i < 2 * info.size; i++) { | 
 |             int sts; | 
 |  | 
 |             if (SV_GET_FIELD(bitvector, i) == SV_EVEN_FIELD) { | 
 |                 Py_INCREF(evenitem); | 
 |                 sts = PyTuple_SetItem(bitvecobj, i, evenitem); | 
 |             } else { | 
 |                 Py_INCREF(odditem); | 
 |                 sts = PyTuple_SetItem(bitvecobj, i, odditem); | 
 |             } | 
 |             if (sts < 0) | 
 |                 goto finally; | 
 |         } | 
 |     } else { | 
 |         bitvecobj = Py_None; | 
 |         Py_INCREF(Py_None); | 
 |     } | 
 |  | 
 |     res = Py_BuildValue("((iiiii)OO)", info.format, | 
 |                         info.width, info.height, | 
 |                         info.size, info.samplingrate, | 
 |                         videodata, bitvecobj); | 
 |  | 
 |   finally: | 
 |     if (bitvector) | 
 |         free(bitvector); | 
 |  | 
 |     Py_XDECREF(videodata); | 
 |     Py_XDECREF(bitvecobj); | 
 |     return res; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_CaptureOneFrame(svobject *self, PyObject *args) | 
 | { | 
 |     svCaptureInfo info; | 
 |     int format, width, height; | 
 |     int bytes; | 
 |     PyObject *videodata = NULL; | 
 |     PyObject *res = NULL; | 
 |     char *str; | 
 |  | 
 |     if (!PyArg_Parse(args, "(iii)", &format, &width, &height)) | 
 |         return NULL; | 
 |  | 
 |     info.format = format; | 
 |     info.width = width; | 
 |     info.height = height; | 
 |     info.size = 0; | 
 |     info.samplingrate = 0; | 
 |     if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) | 
 |         return sv_error(); | 
 |  | 
 |     if (!(videodata = PyString_FromStringAndSize(NULL, bytes))) | 
 |         return NULL; | 
 |  | 
 |     str = PyString_AsString(videodata); | 
 |     if (!str) | 
 |         goto finally; | 
 |  | 
 |     if (svCaptureOneFrame(self->ob_svideo, format, &width, &height, str)) { | 
 |         res = sv_error(); | 
 |         goto finally; | 
 |     } | 
 |  | 
 |     res = Py_BuildValue("(iiO)", width, height, videodata); | 
 |  | 
 |   finally: | 
 |     Py_XDECREF(videodata); | 
 |     return res; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_InitContinuousCapture(svobject *self, PyObject *args) | 
 | { | 
 |     svCaptureInfo info; | 
 |  | 
 |     if (!PyArg_Parse(args, "(iiiii)", &info.format, | 
 |                      &info.width, &info.height, | 
 |                      &info.size, &info.samplingrate)) | 
 |         return NULL; | 
 |  | 
 |     if (svInitContinuousCapture(self->ob_svideo, &info)) | 
 |         return sv_error(); | 
 |  | 
 |     self->ob_info = info; | 
 |  | 
 |     return Py_BuildValue("(iiiii)", info.format, info.width, info.height, | 
 |                          info.size, info.samplingrate); | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_LoadMap(svobject *self, PyObject *args) | 
 | { | 
 |     PyObject *rgb; | 
 |     PyObject *res = NULL; | 
 |     rgb_tuple *mapp = NULL; | 
 |     int maptype; | 
 |     int i, j;                                /* indices */ | 
 |  | 
 |     if (!PyArg_Parse(args, "(iO)", &maptype, &rgb)) | 
 |         return NULL; | 
 |  | 
 |     if (!PyList_Check(rgb) || PyList_Size(rgb) != 256) { | 
 |         PyErr_BadArgument(); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (!(mapp = PyMem_NEW(rgb_tuple, 256))) | 
 |         return PyErr_NoMemory(); | 
 |  | 
 |     for (i = 0; i < 256; i++) { | 
 |         PyObject* v = PyList_GetItem(rgb, i); | 
 |         if (!v) | 
 |             goto finally; | 
 |  | 
 |         if (!PyTuple_Check(v) || PyTuple_Size(v) != 3) { | 
 |             PyErr_BadArgument(); | 
 |             goto finally; | 
 |         } | 
 |         for (j = 0; j < 3; j++) { | 
 |             PyObject* cell = PyTuple_GetItem(v, j); | 
 |             if (!cell) | 
 |                 goto finally; | 
 |  | 
 |             if (!PyInt_Check(cell)) { | 
 |                 PyErr_BadArgument(); | 
 |                 goto finally; | 
 |             } | 
 |             switch (j) { | 
 |             case 0: mapp[i].red = PyInt_AsLong(cell); break; | 
 |             case 1: mapp[i].blue = PyInt_AsLong(cell); break; | 
 |             case 2: mapp[i].green = PyInt_AsLong(cell); break; | 
 |             } | 
 |             if (PyErr_Occurred()) | 
 |                 goto finally; | 
 |         } | 
 |     } | 
 |  | 
 |     if (svLoadMap(self->ob_svideo, maptype, mapp)) { | 
 |         res = sv_error(); | 
 |         goto finally; | 
 |     } | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     res = Py_None; | 
 |  | 
 |   finally: | 
 |     PyMem_DEL(mapp); | 
 |     return res; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_CloseVideo(svobject *self, PyObject *args) | 
 | { | 
 |     if (!PyArg_Parse(args, "")) | 
 |         return NULL; | 
 |  | 
 |     if (svCloseVideo(self->ob_svideo)) | 
 |         return sv_error(); | 
 |  | 
 |     self->ob_svideo = NULL; | 
 |     Py_INCREF(Py_None); | 
 |     return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | doParams(svobject *self, PyObject *args, | 
 |          int (*func)(SV_nodeP, long *, int), int modified) | 
 | { | 
 |     PyObject *list; | 
 |     PyObject *res = NULL; | 
 |     long *PVbuffer = NULL; | 
 |     long length; | 
 |     int i; | 
 |  | 
 |     if (!PyArg_Parse(args, "O", &list)) | 
 |         return NULL; | 
 |  | 
 |     if (!PyList_Check(list)) { | 
 |         PyErr_BadArgument(); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if ((length = PyList_Size(list)) < 0) | 
 |         return NULL; | 
 |  | 
 |     PVbuffer = PyMem_NEW(long, length); | 
 |     if (PVbuffer == NULL) | 
 |         return PyErr_NoMemory(); | 
 |  | 
 |     for (i = 0; i < length; i++) { | 
 |         PyObject *v = PyList_GetItem(list, i); | 
 |         if (!v) | 
 |             goto finally; | 
 |  | 
 |         if (!PyInt_Check(v)) { | 
 |             PyErr_BadArgument(); | 
 |             goto finally; | 
 |         } | 
 |         PVbuffer[i] = PyInt_AsLong(v); | 
 |         /* can't just test the return value, because what if the | 
 |            value was -1?! | 
 |         */ | 
 |         if (PVbuffer[i] == -1 && PyErr_Occurred()) | 
 |             goto finally; | 
 |     } | 
 |  | 
 |     if ((*func)(self->ob_svideo, PVbuffer, length)) { | 
 |         res = sv_error(); | 
 |         goto finally; | 
 |     } | 
 |  | 
 |     if (modified) { | 
 |         for (i = 0; i < length; i++) { | 
 |             PyObject* v = PyInt_FromLong(PVbuffer[i]); | 
 |             if (!v || PyList_SetItem(list, i, v) < 0) | 
 |                 goto finally; | 
 |         } | 
 |     } | 
 |  | 
 |     Py_INCREF(Py_None); | 
 |     res = Py_None; | 
 |  | 
 |   finally: | 
 |     PyMem_DEL(PVbuffer); | 
 |     return res; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_GetParam(PyObject *self, PyObject *args) | 
 | { | 
 |     return doParams(self, args, svGetParam, 1); | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_GetParamRange(PyObject *self, PyObject *args) | 
 | { | 
 |     return doParams(self, args, svGetParamRange, 1); | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_SetParam(PyObject *self, PyObject *args) | 
 | { | 
 |     return doParams(self, args, svSetParam, 0); | 
 | } | 
 |  | 
 | static PyMethodDef svideo_methods[] = { | 
 |     {"BindGLWindow",            (PyCFunction)sv_BindGLWindow, METH_OLDARGS}, | 
 |     {"EndContinuousCapture",(PyCFunction)sv_EndContinuousCapture, METH_OLDARGS}, | 
 |     {"IsVideoDisplayed",        (PyCFunction)sv_IsVideoDisplayed, METH_OLDARGS}, | 
 |     {"OutputOffset",            (PyCFunction)sv_OutputOffset, METH_OLDARGS}, | 
 |     {"PutFrame",                (PyCFunction)sv_PutFrame, METH_OLDARGS}, | 
 |     {"QuerySize",               (PyCFunction)sv_QuerySize, METH_OLDARGS}, | 
 |     {"SetSize",                 (PyCFunction)sv_SetSize, METH_OLDARGS}, | 
 |     {"SetStdDefaults",          (PyCFunction)sv_SetStdDefaults, METH_OLDARGS}, | 
 |     {"UseExclusive",            (PyCFunction)sv_UseExclusive, METH_OLDARGS}, | 
 |     {"WindowOffset",            (PyCFunction)sv_WindowOffset, METH_OLDARGS}, | 
 |     {"InitContinuousCapture",(PyCFunction)sv_InitContinuousCapture, METH_OLDARGS}, | 
 |     {"CaptureBurst",            (PyCFunction)sv_CaptureBurst, METH_OLDARGS}, | 
 |     {"CaptureOneFrame",         (PyCFunction)sv_CaptureOneFrame, METH_OLDARGS}, | 
 |     {"GetCaptureData",          (PyCFunction)sv_GetCaptureData, METH_OLDARGS}, | 
 |     {"CloseVideo",              (PyCFunction)sv_CloseVideo, METH_OLDARGS}, | 
 |     {"LoadMap",                 (PyCFunction)sv_LoadMap, METH_OLDARGS}, | 
 |     {"GetParam",                (PyCFunction)sv_GetParam, METH_OLDARGS}, | 
 |     {"GetParamRange",           (PyCFunction)sv_GetParamRange, METH_OLDARGS}, | 
 |     {"SetParam",                (PyCFunction)sv_SetParam, METH_OLDARGS}, | 
 |     {NULL,                      NULL}           /* sentinel */ | 
 | }; | 
 |  | 
 | static PyObject * | 
 | sv_conversion(PyObject *self, PyObject *args, void (*function)(), | 
 |               int inputfactor, float factor) | 
 | { | 
 |     int invert, width, height, inputlength; | 
 |     char *input, *str; | 
 |     PyObject *output; | 
 |  | 
 |     if (!PyArg_Parse(args, "(is#ii)", &invert, | 
 |                      &input, &inputlength, &width, &height)) | 
 |         return NULL; | 
 |  | 
 |     if (width * height * inputfactor > inputlength) { | 
 |         PyErr_SetString(SvError, "input buffer not long enough"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (!(output = PyString_FromStringAndSize(NULL, | 
 |                                           (int)(width * height * factor)))) | 
 |         return NULL; | 
 |  | 
 |     str = PyString_AsString(output); | 
 |     if (!str) { | 
 |         Py_DECREF(output); | 
 |         return NULL; | 
 |     } | 
 |     (*function)(invert, input, str, width, height); | 
 |  | 
 |     return output; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_InterleaveFields(PyObject *self, PyObject *args) | 
 | { | 
 |     return sv_conversion(self, args, svInterleaveFields, 1, 1.0); | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_RGB8toRGB32(PyObject *self, PyObject *args) | 
 | { | 
 |     return sv_conversion(self, args, svRGB8toRGB32, 1, (float) sizeof(long)); | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_YUVtoRGB(PyObject *self, PyObject *args) | 
 | { | 
 |     return sv_conversion(self, args, svYUVtoRGB, 2, (float) sizeof(long)); | 
 | } | 
 |  | 
 | static void | 
 | svideo_dealloc(svobject *self) | 
 | { | 
 |     if (self->ob_svideo != NULL) | 
 |         (void) svCloseVideo(self->ob_svideo); | 
 |     PyObject_Del(self); | 
 | } | 
 |  | 
 | static PyObject * | 
 | svideo_getattr(svobject *self, char *name) | 
 | { | 
 |     return Py_FindMethod(svideo_methods, (PyObject *)self, name); | 
 | } | 
 |  | 
 | PyTypeObject Svtype = { | 
 |     PyObject_HEAD_INIT(&PyType_Type) | 
 |     0,                          /*ob_size*/ | 
 |     "sv.sv",                    /*tp_name*/ | 
 |     sizeof(svobject),           /*tp_size*/ | 
 |     0,                          /*tp_itemsize*/ | 
 |     /* methods */ | 
 |     (destructor)svideo_dealloc, /*tp_dealloc*/ | 
 |     0,                          /*tp_print*/ | 
 |     (getattrfunc)svideo_getattr, /*tp_getattr*/ | 
 |     0,                          /*tp_setattr*/ | 
 |     0,                          /*tp_compare*/ | 
 |     0,                          /*tp_repr*/ | 
 | }; | 
 |  | 
 | static PyObject * | 
 | newsvobject(SV_nodeP svp) | 
 | { | 
 |     svobject *p; | 
 |  | 
 |     p = PyObject_New(svobject, &Svtype); | 
 |     if (p == NULL) | 
 |         return NULL; | 
 |     p->ob_svideo = svp; | 
 |     p->ob_info.format = 0; | 
 |     p->ob_info.size = 0; | 
 |     p->ob_info.width = 0; | 
 |     p->ob_info.height = 0; | 
 |     p->ob_info.samplingrate = 0; | 
 |     return (PyObject *) p; | 
 | } | 
 |  | 
 | static PyObject * | 
 | sv_OpenVideo(PyObject *self, PyObject *args) | 
 | { | 
 |     SV_nodeP svp; | 
 |  | 
 |     if (!PyArg_Parse(args, "")) | 
 |         return NULL; | 
 |  | 
 |     svp = svOpenVideo(); | 
 |     if (svp == NULL) | 
 |         return sv_error(); | 
 |  | 
 |     return newsvobject(svp); | 
 | } | 
 |  | 
 | static PyMethodDef sv_methods[] = { | 
 |     {"InterleaveFields",        (PyCFunction)sv_InterleaveFields, METH_OLDARGS}, | 
 |     {"RGB8toRGB32",             (PyCFunction)sv_RGB8toRGB32, METH_OLDARGS}, | 
 |     {"YUVtoRGB",                (PyCFunction)sv_YUVtoRGB, METH_OLDARGS}, | 
 |     {"OpenVideo",               (PyCFunction)sv_OpenVideo, METH_OLDARGS}, | 
 |     {NULL,                      NULL}   /* Sentinel */ | 
 | }; | 
 |  | 
 | void | 
 | initsv(void) | 
 | { | 
 |     PyObject *m, *d; | 
 |  | 
 |     if (PyErr_WarnPy3k("the sv module has been removed in " | 
 |                        "Python 3.0", 2) < 0) | 
 |         return; | 
 |  | 
 |     m = Py_InitModule("sv", sv_methods); | 
 |     if (m == NULL) | 
 |         return; | 
 |     d = PyModule_GetDict(m); | 
 |  | 
 |     SvError = PyErr_NewException("sv.error", NULL, NULL); | 
 |     if (SvError == NULL || PyDict_SetItemString(d, "error", SvError) != 0) | 
 |         return; | 
 | } |