0
0
mirror of https://github.com/python/cpython.git synced 2024-12-01 03:01:36 +01:00
cpython/Modules/svmodule.c
Sjoerd Mullender ed59d205a9 Various changes.
* Makefile: svmodule.c.proto and svgen.py are gone, svmodule.c came in
	their stead.  Also, pass -DUSE_DL flag to thread.c and give
	the user a possibility to add the -DDEBUG to just thread.c.
* ceval.c: init_save_thread() can be called more than once now.
* svgen.py, svmodule.c.proto, svmodule.c: Removed prototype file and
	replaced it by the generated file.
* thread.c: Added some more checks; added call to DL library when it
	is also used to tell it where the shared arena is so that DL
	can use some other area.
* threadmodule.c: Call init_save_thread from another place.  Also,
	added new function getlocklock() which does to lock objects
	what getfilefile does to file objects.
1993-01-06 13:36:38 +00:00

953 lines
18 KiB
C

/**********************************************************
Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
/* SV module -- interface to the Indigo video board */
#include <sys/time.h>
#include <svideo.h>
#include "allobjects.h"
#include "import.h"
#include "modsupport.h"
#include "compile.h"
#include "ceval.h"
typedef struct {
OB_HEAD
SV_nodeP ob_svideo;
svCaptureInfo ob_info;
} svobject;
typedef struct {
OB_HEAD
void *ob_capture;
int ob_mustunlock;
svCaptureInfo ob_info;
svobject *ob_svideo;
} captureobject;
static object *SvError; /* exception sv.error */
static object *newcaptureobject PROTO((svobject *, void *, int));
/* Set a SV-specific error from svideo_errno and return NULL */
static object *
sv_error()
{
err_setstr(SvError, svStrerror(svideo_errno));
return NULL;
}
static object *
svc_conversion(self, args, function, factor)
captureobject *self;
object *args;
void (*function)();
int factor;
{
object *output;
int invert;
if (!getargs(args, "i", &invert))
return NULL;
output = newsizedstringobject(NULL, self->ob_info.width * self->ob_info.height * factor);
if (output == NULL)
return NULL;
(*function)((boolean) invert, self->ob_capture, getstringvalue(output),
self->ob_info.width, self->ob_info.height);
return output;
}
static object *
svc_YUVtoRGB(self, args)
captureobject *self;
object *args;
{
switch (self->ob_info.format) {
case SV_YUV411_FRAMES:
case SV_YUV411_FRAMES_AND_BLANKING_BUFFER:
break;
default:
err_setstr(SvError, "data had bad format");
return NULL;
}
return svc_conversion(self, args, svYUVtoRGB, sizeof(long));
}
static object *
svc_RGB8toRGB32(self, args)
captureobject *self;
object *args;
{
if (self->ob_info.format != SV_RGB8_FRAMES) {
err_setstr(SvError, "data has bad format");
return NULL;
}
return svc_conversion(self, args, svRGB8toRGB32, sizeof(long));
}
static object *
svc_InterleaveFields(self, args)
captureobject *self;
object *args;
{
if (self->ob_info.format != SV_RGB8_FRAMES) {
err_setstr(SvError, "data has bad format");
return NULL;
}
return svc_conversion(self, args, svInterleaveFields, 1);
}
static object *
svc_GetFields(self, args)
captureobject *self;
object *args;
{
object *f1, *f2;
int fieldsize;
if (self->ob_info.format != SV_RGB8_FRAMES) {
err_setstr(SvError, "data has bad format");
return NULL;
}
fieldsize = self->ob_info.width * self->ob_info.height / 2;
f1 = newsizedstringobject((char *) self->ob_capture, fieldsize);
if (f1 == NULL)
return NULL;
f2 = newsizedstringobject((char *) self->ob_capture + fieldsize, fieldsize);
if (f2 == NULL) {
DECREF(f1);
return NULL;
}
return mkvalue("(OO)", f1, f2);
}
static object *
svc_UnlockCaptureData(self, args)
captureobject *self;
object *args;
{
if (!getnoarg(args))
return NULL;
if (!self->ob_mustunlock) {
err_setstr(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;
INCREF(None);
return None;
}
#ifdef USE_GL
#include <gl.h>
static object *
svc_lrectwrite(self, args)
captureobject *self;
object *args;
{
Screencoord x1, x2, y1, y2;
if (!getargs(args, "(hhhh)", &x1, &x2, &y1, &y2))
return NULL;
lrectwrite(x1, x2, y1, y2, (unsigned long *) self->ob_capture);
INCREF(None);
return None;
}
#endif
static object *
writefile(self, args)
captureobject *self;
object *args;
{
object *file;
int size;
if (!getargs(args, "O", &file))
return NULL;
if (!is_fileobject(file)) {
err_setstr(SvError, "not a file object");
return NULL;
}
size = self->ob_info.width * self->ob_info.height;
if (fwrite(self->ob_capture, sizeof(long), size, getfilefile(file)) != size) {
err_setstr(SvError, "writing failed");
return NULL;
}
INCREF(None);
return None;
}
static object *
svc_FindVisibleRegion(self, args)
captureobject *self;
object *args;
{
void *visible;
int width;
if (!getnoarg(args))
return NULL;
if (svFindVisibleRegion(self->ob_svideo->ob_svideo, self->ob_capture, &visible, self->ob_info.width))
return sv_error();
if (visible == NULL) {
err_setstr(SvError, "data in wrong format");
return NULL;
}
return newcaptureobject(self->ob_svideo, visible, 0);
}
static struct methodlist capture_methods[] = {
{"YUVtoRGB", svc_YUVtoRGB},
{"RGB8toRGB32", svc_RGB8toRGB32},
{"InterleaveFields", svc_InterleaveFields},
{"UnlockCaptureData", svc_UnlockCaptureData},
{"FindVisibleRegion", svc_FindVisibleRegion},
{"GetFields", svc_GetFields},
#ifdef USE_GL
{"lrectwrite", svc_lrectwrite},
#endif
{"writefile", writefile},
{NULL, NULL} /* sentinel */
};
static void
capture_dealloc(self)
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;
DECREF(self->ob_svideo);
self->ob_svideo = NULL;
}
DEL(self);
}
static object *
capture_getattr(self, name)
svobject *self;
char *name;
{
return findmethod(capture_methods, (object *)self, name);
}
typeobject Capturetype = {
OB_HEAD_INIT(&Typetype)
0, /*ob_size*/
"capture", /*tp_name*/
sizeof(captureobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
capture_dealloc, /*tp_dealloc*/
0, /*tp_print*/
capture_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
};
static object *
newcaptureobject(self, ptr, mustunlock)
svobject *self;
void *ptr;
int mustunlock;
{
captureobject *p;
p = NEWOBJ(captureobject, &Capturetype);
if (p == NULL)
return NULL;
p->ob_svideo = self;
INCREF(self);
p->ob_capture = ptr;
p->ob_mustunlock = mustunlock;
p->ob_info = self->ob_info;
return (object *) p;
}
static object *
sv_GetCaptureData(self, args)
svobject *self;
object *args;
{
void *ptr;
long fieldID;
object *res, *c;
if (!getnoarg(args))
return NULL;
if (svGetCaptureData(self->ob_svideo, &ptr, &fieldID))
return sv_error();
if (ptr == NULL) {
err_setstr(SvError, "no data available");
return NULL;
}
c = newcaptureobject(self, ptr, 1);
if (c == NULL)
return NULL;
res = mkvalue("(Oi)", c, fieldID);
DECREF(c);
return res;
}
static object *
sv_BindGLWindow(self, args)
svobject *self;
object *args;
{
long wid;
int mode;
if (!getargs(args, "(ii)", &wid, &mode))
return NULL;
if (svBindGLWindow(self->ob_svideo, wid, mode))
return sv_error();
INCREF(None);
return None;
}
static object *
sv_EndContinuousCapture(self, args)
svobject *self;
object *args;
{
if (!getnoarg(args))
return NULL;
if (svEndContinuousCapture(self->ob_svideo))
return sv_error();
INCREF(None);
return None;
}
static object *
sv_IsVideoDisplayed(self, args)
svobject *self;
object *args;
{
int v;
if (!getnoarg(args))
return NULL;
v = svIsVideoDisplayed(self->ob_svideo);
if (v == -1)
return sv_error();
return newintobject((long) v);
}
static object *
sv_OutputOffset(self, args)
svobject *self;
object *args;
{
int x_offset;
int y_offset;
if (!getargs(args, "(ii)", &x_offset, &y_offset))
return NULL;
if (svOutputOffset(self->ob_svideo, x_offset, y_offset))
return sv_error();
INCREF(None);
return None;
}
static object *
sv_PutFrame(self, args)
svobject *self;
object *args;
{
char *buffer;
if (!getargs(args, "s", &buffer))
return NULL;
if (svPutFrame(self->ob_svideo, buffer))
return sv_error();
INCREF(None);
return None;
}
static object *
sv_QuerySize(self, args)
svobject *self;
object *args;
{
int w;
int h;
int rw;
int rh;
if (!getargs(args, "(ii)", &w, &h))
return NULL;
if (svQuerySize(self->ob_svideo, w, h, &rw, &rh))
return sv_error();
return mkvalue("(ii)", (long) rw, (long) rh);
}
static object *
sv_SetSize(self, args)
svobject *self;
object *args;
{
int w;
int h;
if (!getargs(args, "(ii)", &w, &h))
return NULL;
if (svSetSize(self->ob_svideo, w, h))
return sv_error();
INCREF(None);
return None;
}
static object *
sv_SetStdDefaults(self, args)
svobject *self;
object *args;
{
if (!getnoarg(args))
return NULL;
if (svSetStdDefaults(self->ob_svideo))
return sv_error();
INCREF(None);
return None;
}
static object *
sv_UseExclusive(self, args)
svobject *self;
object *args;
{
boolean onoff;
int mode;
if (!getargs(args, "(ii)", &onoff, &mode))
return NULL;
if (svUseExclusive(self->ob_svideo, onoff, mode))
return sv_error();
INCREF(None);
return None;
}
static object *
sv_WindowOffset(self, args)
svobject *self;
object *args;
{
int x_offset;
int y_offset;
if (!getargs(args, "(ii)", &x_offset, &y_offset))
return NULL;
if (svWindowOffset(self->ob_svideo, x_offset, y_offset))
return sv_error();
INCREF(None);
return None;
}
static object *
sv_CaptureBurst(self, args)
svobject *self;
object *args;
{
int bytes, i;
svCaptureInfo info;
void *bitvector = NULL;
object *videodata, *bitvecobj, *res;
static object *evenitem, *odditem;
if (!getargs(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:
err_setstr(SvError, "illegal format specified");
return NULL;
}
if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) {
if (bitvector)
free(bitvector);
return sv_error();
}
videodata = newsizedstringobject(NULL, bytes);
if (videodata == NULL) {
if (bitvector)
free(bitvector);
return NULL;
}
/* XXX -- need to do something about the bitvector */
if (svCaptureBurst(self->ob_svideo, &info, getstringvalue(videodata),
bitvector)) {
if (bitvector)
free(bitvector);
DECREF(videodata);
return sv_error();
}
if (bitvector) {
if (evenitem == NULL) {
evenitem = newintobject(0);
if (evenitem == NULL) {
free(bitvector);
DECREF(videodata);
return NULL;
}
}
if (odditem == NULL) {
odditem = newintobject(1);
if (odditem == NULL) {
free(bitvector);
DECREF(videodata);
return NULL;
}
}
bitvecobj = newtupleobject(2 * info.size);
if (bitvecobj == NULL) {
free(bitvecobj);
DECREF(videodata);
return NULL;
}
for (i = 0; i < 2 * info.size; i++) {
if (SV_GET_FIELD(bitvector, i) == SV_EVEN_FIELD) {
INCREF(evenitem);
settupleitem(bitvecobj, i, evenitem);
} else {
INCREF(odditem);
settupleitem(bitvecobj, i, odditem);
}
}
free(bitvector);
} else {
bitvecobj = None;
INCREF(None);
}
res = mkvalue("((iiiii)OO)", info.format, info.width, info.height,
info.size, info.samplingrate, videodata, bitvecobj);
DECREF(videodata);
DECREF(bitvecobj);
return res;
}
static object *
sv_CaptureOneFrame(self, args)
svobject *self;
object *args;
{
svCaptureInfo info;
int format, width, height;
int bytes;
object *videodata, *res;
if (!getargs(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();
videodata = newsizedstringobject(NULL, bytes);
if (videodata == NULL)
return NULL;
if (svCaptureOneFrame(self->ob_svideo, format, &width, &height,
getstringvalue(videodata))) {
DECREF(videodata);
return sv_error();
}
res = mkvalue("(iiO)", width, height, videodata);
DECREF(videodata);
return res;
}
static object *
sv_InitContinuousCapture(self, args)
svobject *self;
object *args;
{
svCaptureInfo info;
if (!getargs(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 mkvalue("(iiiii)", info.format, info.width, info.height,
info.size, info.samplingrate);
}
static object *
sv_LoadMap(self, args)
svobject *self;
object *args;
{
object *rgb, *v, *cell;
rgb_tuple *mapp;
int maptype;
int i, j; /* indices */
if (!getargs(args, "(iO)", &maptype, &rgb))
return NULL;
if (!is_listobject(rgb) || getlistsize(rgb) != 256) {
err_badarg();
return NULL;
}
mapp = NEW(rgb_tuple, 256);
if (mapp == NULL)
return err_nomem();
for (i = 0; i < 256; i++) {
v = getlistitem(rgb, i);
if (!is_tupleobject(v) || gettuplesize(v) != 3) {
DEL(mapp);
err_badarg();
return NULL;
}
for (j = 0; j < 3; j++) {
cell = gettupleitem(v, j);
if (!is_intobject(cell)) {
DEL(mapp);
err_badarg();
return NULL;
}
switch (j) {
case 0: mapp[i].red = getintvalue(cell); break;
case 1: mapp[i].blue = getintvalue(cell); break;
case 2: mapp[i].green = getintvalue(cell); break;
}
}
}
if (svLoadMap(self->ob_svideo, maptype, mapp)) {
DEL(mapp);
return sv_error();
}
DEL(mapp);
INCREF(None);
return None;
}
static object *
sv_CloseVideo(self, args)
svobject *self;
object *args;
{
if (!getnoarg(args))
return NULL;
if (svCloseVideo(self->ob_svideo))
return sv_error();
self->ob_svideo = NULL;
INCREF(None);
return None;
}
static object *
doParams(self, args, func, modified)
svobject *self;
object *args;
int (*func)(SV_nodeP, long *, int);
int modified;
{
object *list, *v;
long *PVbuffer;
long length;
int i;
if (!getargs(args, "O", &list))
return NULL;
if (!is_listobject(list)) {
err_badarg();
return NULL;
}
length = getlistsize(list);
PVbuffer = NEW(long, length);
if (PVbuffer == NULL)
return err_nomem();
for (i = 0; i < length; i++) {
v = getlistitem(list, i);
if (!is_intobject(v)) {
DEL(PVbuffer);
err_badarg();
return NULL;
}
PVbuffer[i] = getintvalue(v);
}
if ((*func)(self->ob_svideo, PVbuffer, length)) {
DEL(PVbuffer);
return sv_error();
}
if (modified) {
for (i = 0; i < length; i++)
setlistitem(list, i, newintobject(PVbuffer[i]));
}
DEL(PVbuffer);
INCREF(None);
return None;
}
static object *
sv_GetParam(self, args)
object *self, *args;
{
return doParams(self, args, svGetParam, 1);
}
static object *
sv_GetParamRange(self, args)
object *self, *args;
{
return doParams(self, args, svGetParamRange, 1);
}
static object *
sv_SetParam(self, args)
object *self, *args;
{
return doParams(self, args, svSetParam, 0);
}
static struct methodlist svideo_methods[] = {
{"BindGLWindow", sv_BindGLWindow},
{"EndContinuousCapture",sv_EndContinuousCapture},
{"IsVideoDisplayed", sv_IsVideoDisplayed},
{"OutputOffset", sv_OutputOffset},
{"PutFrame", sv_PutFrame},
{"QuerySize", sv_QuerySize},
{"SetSize", sv_SetSize},
{"SetStdDefaults", sv_SetStdDefaults},
{"UseExclusive", sv_UseExclusive},
{"WindowOffset", sv_WindowOffset},
{"InitContinuousCapture",sv_InitContinuousCapture},
{"CaptureBurst", sv_CaptureBurst},
{"CaptureOneFrame", sv_CaptureOneFrame},
{"GetCaptureData", sv_GetCaptureData},
{"CloseVideo", sv_CloseVideo},
{"LoadMap", sv_LoadMap},
{"GetParam", sv_GetParam},
{"GetParamRange", sv_GetParamRange},
{"SetParam", sv_SetParam},
{NULL, NULL} /* sentinel */
};
static object *
sv_conversion(self, args, function, inputfactor, factor)
object *self, *args;
void (*function)();
int inputfactor, factor;
{
int invert, width, height, inputlength;
char *input;
object *output;
if (!getargs(args, "(is#ii)", &invert, &input, &inputlength, &width, &height))
return NULL;
if (width * height * inputfactor > inputlength) {
err_setstr(SvError, "input buffer not long enough");
return NULL;
}
output = newsizedstringobject(NULL, width * height * factor);
if (output == NULL)
return NULL;
(*function)(invert, input, getstringvalue(output), width, height);
return output;
}
static object *
sv_InterleaveFields(self, args)
object *self, *args;
{
return sv_conversion(self, args, svInterleaveFields, 1, 1);
}
static object *
sv_RGB8toRGB32(self, args)
object *self, *args;
{
return sv_conversion(self, args, svRGB8toRGB32, 1, sizeof(long));
}
static object *
sv_YUVtoRGB(self, args)
object *self, *args;
{
return sv_conversion(self, args, svYUVtoRGB, 2, sizeof(long));
}
static void
svideo_dealloc(self)
svobject *self;
{
if (self->ob_svideo != NULL)
(void) svCloseVideo(self->ob_svideo);
DEL(self);
}
static object *
svideo_getattr(self, name)
svobject *self;
char *name;
{
return findmethod(svideo_methods, (object *)self, name);
}
typeobject Svtype = {
OB_HEAD_INIT(&Typetype)
0, /*ob_size*/
"sv", /*tp_name*/
sizeof(svobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
svideo_dealloc, /*tp_dealloc*/
0, /*tp_print*/
svideo_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
};
static object *
newsvobject(svp)
SV_nodeP svp;
{
svobject *p;
p = NEWOBJ(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 (object *) p;
}
static object *
sv_OpenVideo(self, args)
object *self, *args;
{
SV_nodeP svp;
if (!getnoarg(args))
return NULL;
svp = svOpenVideo();
if (svp == NULL)
return sv_error();
return newsvobject(svp);
}
static struct methodlist sv_methods[] = {
{"InterleaveFields", sv_InterleaveFields},
{"RGB8toRGB32", sv_RGB8toRGB32},
{"YUVtoRGB", sv_YUVtoRGB},
{"OpenVideo", sv_OpenVideo},
{NULL, NULL} /* Sentinel */
};
void
initsv()
{
object *m, *d;
m = initmodule("sv", sv_methods);
d = getmoduledict(m);
SvError = newstringobject("sv.error");
if (SvError == NULL || dictinsert(d, "error", SvError) != 0)
fatal("can't define sv.error");
}