svmodule.c 20.6 KB
Newer Older
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1 2
/* SV module -- interface to the Indigo video board */

3 4 5 6 7
/* 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! */

Sjoerd Mullender's avatar
Sjoerd Mullender committed
8 9
#include <sys/time.h>
#include <svideo.h>
10
#include "Python.h"
Sjoerd Mullender's avatar
Sjoerd Mullender committed
11
#include "compile.h"
12
#include "yuv.h"		/* for YUV conversion functions */
Sjoerd Mullender's avatar
Sjoerd Mullender committed
13 14

typedef struct {
15
	PyObject_HEAD
Sjoerd Mullender's avatar
Sjoerd Mullender committed
16 17 18 19 20
	SV_nodeP ob_svideo;
	svCaptureInfo ob_info;
} svobject;

typedef struct {
21
	PyObject_HEAD
Sjoerd Mullender's avatar
Sjoerd Mullender committed
22 23 24 25 26 27
	void *ob_capture;
	int ob_mustunlock;
	svCaptureInfo ob_info;
	svobject *ob_svideo;
} captureobject;

28
static PyObject *SvError;		/* exception sv.error */
Sjoerd Mullender's avatar
Sjoerd Mullender committed
29

30
static PyObject *newcaptureobject(svobject *, void *, int);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
31 32

/* Set a SV-specific error from svideo_errno and return NULL */
33
static PyObject *
34
sv_error(void)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
35
{
36
	PyErr_SetString(SvError, svStrerror(svideo_errno));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
37 38 39
	return NULL;
}

40
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
41
svc_conversion(captureobject *self, PyObject *args, void (*function)(),	float factor)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
42
{
43
	PyObject *output;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
44
	int invert;
45
	char* outstr;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
46

47
	if (!PyArg_Parse(args, "i", &invert))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
48 49
		return NULL;

50
	if (!(output = PyString_FromStringAndSize(
51 52 53
		NULL,
		(int)(self->ob_info.width * self->ob_info.height * factor))))
	{
Sjoerd Mullender's avatar
Sjoerd Mullender committed
54
		return NULL;
55
	}
56
	if (!(outstr = PyString_AsString(output))) {
57 58 59
		Py_DECREF(output);
		return NULL;
	}
Sjoerd Mullender's avatar
Sjoerd Mullender committed
60

61 62
	(*function)((boolean)invert, self->ob_capture,
		    outstr,
Sjoerd Mullender's avatar
Sjoerd Mullender committed
63 64 65 66 67
		    self->ob_info.width, self->ob_info.height);

	return output;
}

68 69 70 71
/*
 * 3 functions to convert from Starter Video YUV 4:1:1 format to
 * Compression Library 4:2:2 Duplicate Chroma format.
 */
72
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
73
svc_YUVtoYUV422DC(captureobject *self, PyObject *args)
74 75
{
	if (self->ob_info.format != SV_YUV411_FRAMES) {
76
		PyErr_SetString(SvError, "data has bad format");
77 78 79 80 81
		return NULL;
	}
	return svc_conversion(self, args, yuv_sv411_to_cl422dc, 2.0);
}

82
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
83
svc_YUVtoYUV422DC_quarter(captureobject *self, PyObject *args)
84 85
{
	if (self->ob_info.format != SV_YUV411_FRAMES) {
86
		PyErr_SetString(SvError, "data has bad format");
87 88
		return NULL;
	}
89 90
	return svc_conversion(self, args,
			      yuv_sv411_to_cl422dc_quartersize, 0.5);
91 92
}

93
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
94
svc_YUVtoYUV422DC_sixteenth(captureobject *self, PyObject *args)
95 96
{
	if (self->ob_info.format != SV_YUV411_FRAMES) {
97
		PyErr_SetString(SvError, "data has bad format");
98 99
		return NULL;
	}
100 101
	return svc_conversion(self, args,
			      yuv_sv411_to_cl422dc_sixteenthsize, 0.125);
102 103
}

104
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
105
svc_YUVtoRGB(captureobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
106 107 108 109 110 111
{
	switch (self->ob_info.format) {
	case SV_YUV411_FRAMES:
	case SV_YUV411_FRAMES_AND_BLANKING_BUFFER:
		break;
	default:
112
		PyErr_SetString(SvError, "data had bad format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
113 114
		return NULL;
	}
115
	return svc_conversion(self, args, svYUVtoRGB, (float) sizeof(long));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
116 117
}

118
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
119
svc_RGB8toRGB32(captureobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
120 121
{
	if (self->ob_info.format != SV_RGB8_FRAMES) {
122
		PyErr_SetString(SvError, "data has bad format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
123 124
		return NULL;
	}
125
	return svc_conversion(self, args, svRGB8toRGB32, (float) sizeof(long));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
126 127
}

128
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
129
svc_InterleaveFields(captureobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
130 131
{
	if (self->ob_info.format != SV_RGB8_FRAMES) {
132
		PyErr_SetString(SvError, "data has bad format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
133 134
		return NULL;
	}
135
	return svc_conversion(self, args, svInterleaveFields, 1.0);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
136 137
}

138
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
139
svc_GetFields(captureobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
140
{
141 142 143
	PyObject *f1 = NULL;
	PyObject *f2 = NULL;
	PyObject *ret = NULL;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
144
	int fieldsize;
145
	char* obcapture;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
146 147

	if (self->ob_info.format != SV_RGB8_FRAMES) {
148
		PyErr_SetString(SvError, "data has bad format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
149 150 151 152
		return NULL;
	}

	fieldsize = self->ob_info.width * self->ob_info.height / 2;
153 154
	obcapture = (char*)self->ob_capture;
	
155
	if (!(f1 = PyString_FromStringAndSize(obcapture, fieldsize)))
156
		goto finally;
157
	if (!(f2 = PyString_FromStringAndSize(obcapture + fieldsize,
158 159
					      fieldsize)))
		goto finally;
160
	ret = PyTuple_Pack(2, f1, f2);
161 162 163 164

  finally:
	Py_XDECREF(f1);
	Py_XDECREF(f2);
165
	return ret;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
166 167
}
	
168
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
169
svc_UnlockCaptureData(captureobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
170
{
171
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
172 173 174
		return NULL;

	if (!self->ob_mustunlock) {
175
		PyErr_SetString(SvError, "buffer should not be unlocked");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
176 177 178 179 180 181 182 183
		return NULL;
	}

	if (svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture))
		return sv_error();

	self->ob_mustunlock = 0;

184 185
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
186 187 188 189 190
}

#ifdef USE_GL
#include <gl.h>

191
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
192
svc_lrectwrite(captureobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
193 194 195
{
	Screencoord x1, x2, y1, y2;

196
	if (!PyArg_Parse(args, "(hhhh)", &x1, &x2, &y1, &y2))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
197 198 199 200
		return NULL;

	lrectwrite(x1, x2, y1, y2, (unsigned long *) self->ob_capture);

201 202
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
203 204 205
}
#endif

206
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
207
svc_writefile(captureobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
208
{
209
	PyObject *file;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
210
	int size;
211
	FILE* fp;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
212

213
	if (!PyArg_Parse(args, "O", &file))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
214 215
		return NULL;

216 217
	if (!PyFile_Check(file)) {
		PyErr_SetString(SvError, "not a file object");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
218 219 220
		return NULL;
	}

221 222 223
	if (!(fp = PyFile_AsFile(file)))
		return NULL;

Sjoerd Mullender's avatar
Sjoerd Mullender committed
224 225
	size = self->ob_info.width * self->ob_info.height;

226 227
	if (fwrite(self->ob_capture, sizeof(long), size, fp) != size) {
		PyErr_SetString(SvError, "writing failed");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
228 229 230
		return NULL;
	}

231 232
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
233 234
}

235
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
236
svc_FindVisibleRegion(captureobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
237 238 239 240
{
	void *visible;
	int width;

241
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
242 243
		return NULL;

244 245 246
	if (svFindVisibleRegion(self->ob_svideo->ob_svideo,
				self->ob_capture, &visible,
				self->ob_info.width))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
247 248 249
		return sv_error();

	if (visible == NULL) {
250
		PyErr_SetString(SvError, "data in wrong format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
251 252 253 254 255 256
		return NULL;
	}

	return newcaptureobject(self->ob_svideo, visible, 0);
}

257
static PyMethodDef capture_methods[] = {
258 259 260 261 262 263 264 265 266
	{"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},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
267
#ifdef USE_GL
268
	{"lrectwrite",		(PyCFunction)svc_lrectwrite, METH_OLDARGS},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
269
#endif
270
	{"writefile",		(PyCFunction)svc_writefile, METH_OLDARGS},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
271 272 273 274
	{NULL,			NULL} 		/* sentinel */
};

static void
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
275
capture_dealloc(captureobject *self)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
276 277 278
{
	if (self->ob_capture != NULL) {
		if (self->ob_mustunlock)
279 280
			(void)svUnlockCaptureData(self->ob_svideo->ob_svideo,
						  self->ob_capture);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
281
		self->ob_capture = NULL;
282
		Py_DECREF(self->ob_svideo);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
283 284
		self->ob_svideo = NULL;
	}
285
	PyObject_Del(self);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
286 287
}

288
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
289
capture_getattr(svobject *self, char *name)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
290
{
291
	return Py_FindMethod(capture_methods, (PyObject *)self, name);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
292 293
}

294 295
PyTypeObject Capturetype = {
	PyObject_HEAD_INIT(&PyType_Type)
296
	0,				/*ob_size*/
297
	"sv.capture",			/*tp_name*/
298 299
	sizeof(captureobject),		/*tp_size*/
	0,				/*tp_itemsize*/
Sjoerd Mullender's avatar
Sjoerd Mullender committed
300
	/* methods */
301 302 303 304 305 306
	(destructor)capture_dealloc,	/*tp_dealloc*/
	0,				/*tp_print*/
	(getattrfunc)capture_getattr,	/*tp_getattr*/
	0,				/*tp_setattr*/
	0,				/*tp_compare*/
	0,				/*tp_repr*/
Sjoerd Mullender's avatar
Sjoerd Mullender committed
307 308
};

309
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
310
newcaptureobject(svobject *self, void *ptr, int mustunlock)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
311 312 313
{
	captureobject *p;

314
	p = PyObject_New(captureobject, &Capturetype);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
315 316 317
	if (p == NULL)
		return NULL;
	p->ob_svideo = self;
318
	Py_INCREF(self);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
319 320 321
	p->ob_capture = ptr;
	p->ob_mustunlock = mustunlock;
	p->ob_info = self->ob_info;
322
	return (PyObject *) p;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
323 324
}

325
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
326
sv_GetCaptureData(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
327 328 329
{
	void *ptr;
	long fieldID;
330
	PyObject *res, *c;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
331

332
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
333 334 335 336 337 338
		return NULL;

	if (svGetCaptureData(self->ob_svideo, &ptr, &fieldID))
		return sv_error();

	if (ptr == NULL) {
339
		PyErr_SetString(SvError, "no data available");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
340 341 342 343 344 345
		return NULL;
	}

	c = newcaptureobject(self, ptr, 1);
	if (c == NULL)
		return NULL;
346 347
	res = Py_BuildValue("(Oi)", c, fieldID);
	Py_DECREF(c);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
348 349 350
	return res;
}

351
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
352
sv_BindGLWindow(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
353 354 355 356
{
	long wid;
	int mode;

357
	if (!PyArg_Parse(args, "(ii)", &wid, &mode))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
358 359 360 361 362
		return NULL;

	if (svBindGLWindow(self->ob_svideo, wid, mode))
		return sv_error();

363 364
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
365 366
}

367
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
368
sv_EndContinuousCapture(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
369 370
{

371
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
372 373 374 375 376
		return NULL;

	if (svEndContinuousCapture(self->ob_svideo))
		return sv_error();

377 378
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
379 380
}

381
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
382
sv_IsVideoDisplayed(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
383 384 385
{
	int v;

386
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
387 388 389 390 391 392
		return NULL;

	v = svIsVideoDisplayed(self->ob_svideo);
	if (v == -1)
		return sv_error();

393
	return PyInt_FromLong((long) v);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
394 395
}

396
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
397
sv_OutputOffset(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
398 399 400 401
{
	int x_offset;
	int y_offset;

402
	if (!PyArg_Parse(args, "(ii)", &x_offset, &y_offset))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
403 404 405 406 407
		return NULL;

	if (svOutputOffset(self->ob_svideo, x_offset, y_offset))
		return sv_error();

408 409
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
410 411
}

412
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
413
sv_PutFrame(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
414 415 416
{
	char *buffer;

417
	if (!PyArg_Parse(args, "s", &buffer))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
418 419 420 421 422
		return NULL;

	if (svPutFrame(self->ob_svideo, buffer))
		return sv_error();

423 424
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
425 426
}

427
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
428
sv_QuerySize(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
429 430 431 432 433 434
{
	int w;
	int h;
	int rw;
	int rh;

435
	if (!PyArg_Parse(args, "(ii)", &w, &h))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
436 437 438 439 440
		return NULL;

	if (svQuerySize(self->ob_svideo, w, h, &rw, &rh))
		return sv_error();

441
	return Py_BuildValue("(ii)", (long) rw, (long) rh);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
442 443
}

444
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
445
sv_SetSize(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
446 447 448 449
{
	int w;
	int h;

450
	if (!PyArg_Parse(args, "(ii)", &w, &h))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
451 452 453 454 455
		return NULL;

	if (svSetSize(self->ob_svideo, w, h))
		return sv_error();

456 457
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
458 459
}

460
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
461
sv_SetStdDefaults(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
462 463
{

464
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
465 466 467 468 469
		return NULL;

	if (svSetStdDefaults(self->ob_svideo))
		return sv_error();

470 471
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
472 473
}

474
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
475
sv_UseExclusive(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
476 477 478 479
{
	boolean onoff;
	int mode;

480
	if (!PyArg_Parse(args, "(ii)", &onoff, &mode))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
481 482 483 484 485
		return NULL;

	if (svUseExclusive(self->ob_svideo, onoff, mode))
		return sv_error();

486 487
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
488 489
}

490
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
491
sv_WindowOffset(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
492 493 494 495
{
	int x_offset;
	int y_offset;

496
	if (!PyArg_Parse(args, "(ii)", &x_offset, &y_offset))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
497 498 499 500 501
		return NULL;

	if (svWindowOffset(self->ob_svideo, x_offset, y_offset))
		return sv_error();

502 503
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
504 505
}

506
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
507
sv_CaptureBurst(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
508 509 510 511
{
	int bytes, i;
	svCaptureInfo info;
	void *bitvector = NULL;
512 513
	PyObject *videodata = NULL;
	PyObject *bitvecobj = NULL;
514
	PyObject *res = NULL;
515 516 517 518 519
	static PyObject *evenitem, *odditem;

	if (!PyArg_Parse(args, "(iiiii)", &info.format,
			 &info.width, &info.height,
			 &info.size, &info.samplingrate))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
520 521 522 523 524 525 526 527 528
		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:
529
		PyErr_SetString(SvError, "illegal format specified");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
530 531 532 533
		return NULL;
	}

	if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) {
534 535
		res = sv_error();
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
536 537
	}

538
	if (!(videodata = PyString_FromStringAndSize(NULL, bytes)))
539
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
540 541

	/* XXX -- need to do something about the bitvector */
542
	{
543
		char* str = PyString_AsString(videodata);
544 545 546 547 548 549 550
		if (!str)
			goto finally;
		
		if (svCaptureBurst(self->ob_svideo, &info, str, bitvector)) {
			res = sv_error();
			goto finally;
		}
Sjoerd Mullender's avatar
Sjoerd Mullender committed
551 552 553 554
	}

	if (bitvector) {
		if (evenitem == NULL) {
555 556
			if (!(evenitem = PyInt_FromLong(0)))
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
557 558
		}
		if (odditem == NULL) {
559 560
			if (!(odditem = PyInt_FromLong(1)))
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
561
		}
562 563 564
		if (!(bitvecobj = PyTuple_New(2 * info.size)))
			goto finally;

Sjoerd Mullender's avatar
Sjoerd Mullender committed
565
		for (i = 0; i < 2 * info.size; i++) {
566 567
			int sts;

Sjoerd Mullender's avatar
Sjoerd Mullender committed
568
			if (SV_GET_FIELD(bitvector, i) == SV_EVEN_FIELD) {
569 570
				Py_INCREF(evenitem);
				sts = PyTuple_SetItem(bitvecobj, i, evenitem);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
571
			} else {
572 573
				Py_INCREF(odditem);
				sts = PyTuple_SetItem(bitvecobj, i, odditem);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
574
			}
575 576
			if (sts < 0)
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
577 578
		}
	} else {
579 580
		bitvecobj = Py_None;
		Py_INCREF(Py_None);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
581 582
	}

583 584 585 586 587 588 589 590 591 592 593
	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);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
594 595 596
	return res;
}

597
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
598
sv_CaptureOneFrame(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
599 600 601 602
{
	svCaptureInfo info;
	int format, width, height;
	int bytes;
603 604
	PyObject *videodata = NULL;
	PyObject *res = NULL;
605
	char *str;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
606
	
607
	if (!PyArg_Parse(args, "(iii)", &format, &width, &height))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
608
		return NULL;
609

Sjoerd Mullender's avatar
Sjoerd Mullender committed
610 611 612 613 614 615 616
	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();
617

618
	if (!(videodata = PyString_FromStringAndSize(NULL, bytes)))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
619
		return NULL;
620
	
621
	str = PyString_AsString(videodata);
622 623
	if (!str)
		goto finally;
624 625 626 627

	if (svCaptureOneFrame(self->ob_svideo, format, &width, &height, str)) {
		res = sv_error();
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
628 629
	}

630 631 632 633
	res = Py_BuildValue("(iiO)", width, height, videodata);

  finally:
	Py_XDECREF(videodata);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
634 635 636
	return res;
}

637
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
638
sv_InitContinuousCapture(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
639 640 641
{
	svCaptureInfo info;

642 643 644
	if (!PyArg_Parse(args, "(iiiii)", &info.format,
			 &info.width, &info.height,
			 &info.size, &info.samplingrate))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
645 646 647 648 649 650 651
		return NULL;

	if (svInitContinuousCapture(self->ob_svideo, &info))
		return sv_error();

	self->ob_info = info;

652 653
	return Py_BuildValue("(iiiii)", info.format, info.width, info.height,
			     info.size, info.samplingrate);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
654 655
}

656
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
657
sv_LoadMap(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
658
{
659 660 661
	PyObject *rgb;
	PyObject *res = NULL;
	rgb_tuple *mapp = NULL;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
662
	int maptype;
663
	int i, j;			     /* indices */
Sjoerd Mullender's avatar
Sjoerd Mullender committed
664

665
	if (!PyArg_Parse(args, "(iO)", &maptype, &rgb))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
666
		return NULL;
667 668 669

	if (!PyList_Check(rgb) || PyList_Size(rgb) != 256) {
		PyErr_BadArgument();
Sjoerd Mullender's avatar
Sjoerd Mullender committed
670 671
		return NULL;
	}
672 673 674 675

	if (!(mapp = PyMem_NEW(rgb_tuple, 256)))
		return PyErr_NoMemory();

Sjoerd Mullender's avatar
Sjoerd Mullender committed
676
	for (i = 0; i < 256; i++) {
677 678 679 680 681 682 683
		PyObject* v = PyList_GetItem(rgb, i);
		if (!v)
			goto finally;

		if (!PyTuple_Check(v) || PyTuple_Size(v) != 3) {
			PyErr_BadArgument();
			goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
684 685
		}
		for (j = 0; j < 3; j++) {
686 687 688 689 690 691 692
			PyObject* cell = PyTuple_GetItem(v, j);
			if (!cell)
				goto finally;

			if (!PyInt_Check(cell)) {
				PyErr_BadArgument();
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
693 694
			}
			switch (j) {
695 696 697
			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;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
698
			}
699 700
			if (PyErr_Occurred())
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
701 702 703 704
		}
	}

	if (svLoadMap(self->ob_svideo, maptype, mapp)) {
705 706
		res = sv_error();
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
707 708
	}

709 710
	Py_INCREF(Py_None);
	res = Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
711

712 713 714
  finally:
	PyMem_DEL(mapp);
	return res;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
715 716
}
		
717
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
718
sv_CloseVideo(svobject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
719
{
720
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
721 722 723 724 725
		return NULL;

	if (svCloseVideo(self->ob_svideo))
		return sv_error();

726 727 728
	self->ob_svideo = NULL;
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
729 730
}

731
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
732 733
doParams(svobject *self, PyObject *args,
         int (*func)(SV_nodeP, long *, int), int modified)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
734
{
735 736 737
	PyObject *list;
	PyObject *res = NULL;
	long *PVbuffer = NULL;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
738 739 740
	long length;
	int i;
	
741
	if (!PyArg_Parse(args, "O", &list))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
742
		return NULL;
743 744 745

	if (!PyList_Check(list)) {
		PyErr_BadArgument();
Sjoerd Mullender's avatar
Sjoerd Mullender committed
746 747
		return NULL;
	}
748 749 750 751 752

	if ((length = PyList_Size(list)) < 0)
		return NULL;

	PVbuffer = PyMem_NEW(long, length);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
753
	if (PVbuffer == NULL)
754 755
		return PyErr_NoMemory();

Sjoerd Mullender's avatar
Sjoerd Mullender committed
756
	for (i = 0; i < length; i++) {
757 758 759 760 761 762 763
		PyObject *v = PyList_GetItem(list, i);
		if (!v)
			goto finally;

		if (!PyInt_Check(v)) {
			PyErr_BadArgument();
			goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
764
		}
765 766 767 768 769 770
		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;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
771 772 773
	}

	if ((*func)(self->ob_svideo, PVbuffer, length)) {
774 775
		res = sv_error();
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
776 777 778
	}

	if (modified) {
779 780 781 782 783
		for (i = 0; i < length; i++) {
			PyObject* v = PyInt_FromLong(PVbuffer[i]);
			if (!v || PyList_SetItem(list, i, v) < 0)
				goto finally;
		}
Sjoerd Mullender's avatar
Sjoerd Mullender committed
784 785
	}

786 787
	Py_INCREF(Py_None);
	res = Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
788

789 790 791
  finally:
	PyMem_DEL(PVbuffer);
	return res;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
792 793
}

794
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
795
sv_GetParam(PyObject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
796 797 798 799
{
	return doParams(self, args, svGetParam, 1);
}

800
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
801
sv_GetParamRange(PyObject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
802 803 804 805
{
	return doParams(self, args, svGetParamRange, 1);
}

806
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
807
sv_SetParam(PyObject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
808 809 810 811
{
	return doParams(self, args, svSetParam, 0);
}

812
static PyMethodDef svideo_methods[] = {
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
	{"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},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
832 833 834
	{NULL,			NULL} 		/* sentinel */
};

835
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
836 837
sv_conversion(PyObject *self, PyObject *args, void (*function)(),
              int inputfactor, float factor)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
838 839
{
	int invert, width, height, inputlength;
840 841
	char *input, *str;
	PyObject *output;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
842

843 844
	if (!PyArg_Parse(args, "(is#ii)", &invert,
			 &input, &inputlength, &width, &height))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
845 846 847
		return NULL;

	if (width * height * inputfactor > inputlength) {
848
		PyErr_SetString(SvError, "input buffer not long enough");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
849 850 851
		return NULL;
	}

852
	if (!(output = PyString_FromStringAndSize(NULL,
853
					      (int)(width * height * factor))))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
854 855
		return NULL;

856
	str = PyString_AsString(output);
857 858 859 860 861
	if (!str) {
		Py_DECREF(output);
		return NULL;
	}
	(*function)(invert, input, str, width, height);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
862 863 864 865

	return output;
}

866
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
867
sv_InterleaveFields(PyObject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
868
{
869
	return sv_conversion(self, args, svInterleaveFields, 1, 1.0);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
870 871
}

872
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
873
sv_RGB8toRGB32(PyObject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
874
{
875
	return sv_conversion(self, args, svRGB8toRGB32, 1, (float) sizeof(long));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
876 877
}

878
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
879
sv_YUVtoRGB(PyObject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
880
{
881
	return sv_conversion(self, args, svYUVtoRGB, 2, (float) sizeof(long));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
882 883 884
}

static void
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
885
svideo_dealloc(svobject *self)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
886 887 888
{
	if (self->ob_svideo != NULL)
		(void) svCloseVideo(self->ob_svideo);
889
	PyObject_Del(self);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
890 891
}

892
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
893
svideo_getattr(svobject *self, char *name)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
894
{
895
	return Py_FindMethod(svideo_methods, (PyObject *)self, name);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
896 897
}

898 899
PyTypeObject Svtype = {
	PyObject_HEAD_INIT(&PyType_Type)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
900
	0,			/*ob_size*/
901
	"sv.sv",		/*tp_name*/
Sjoerd Mullender's avatar
Sjoerd Mullender committed
902 903 904
	sizeof(svobject),	/*tp_size*/
	0,			/*tp_itemsize*/
	/* methods */
905
	(destructor)svideo_dealloc, /*tp_dealloc*/
Sjoerd Mullender's avatar
Sjoerd Mullender committed
906
	0,			/*tp_print*/
907
	(getattrfunc)svideo_getattr, /*tp_getattr*/
Sjoerd Mullender's avatar
Sjoerd Mullender committed
908 909 910 911 912
	0,			/*tp_setattr*/
	0,			/*tp_compare*/
	0,			/*tp_repr*/
};

913
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
914
newsvobject(SV_nodeP svp)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
915 916 917
{
	svobject *p;

918
	p = PyObject_New(svobject, &Svtype);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
919 920 921 922 923 924 925 926
	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;
927
	return (PyObject *) p;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
928 929
}

930
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
931
sv_OpenVideo(PyObject *self, PyObject *args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
932 933 934
{
	SV_nodeP svp;

935
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
936 937 938 939 940 941 942 943 944
		return NULL;

	svp = svOpenVideo();
	if (svp == NULL)
		return sv_error();

	return newsvobject(svp);
}

945
static PyMethodDef sv_methods[] = {
946 947 948 949
	{"InterleaveFields",	(PyCFunction)sv_InterleaveFields, METH_OLDARGS},
	{"RGB8toRGB32",		(PyCFunction)sv_RGB8toRGB32, METH_OLDARGS},
	{"YUVtoRGB",		(PyCFunction)sv_YUVtoRGB, METH_OLDARGS},
	{"OpenVideo",		(PyCFunction)sv_OpenVideo, METH_OLDARGS},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
950 951 952 953
	{NULL,			NULL}	/* Sentinel */
};

void
954
initsv(void)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
955
{
956
	PyObject *m, *d;
957 958 959 960
	
	if (PyErr_WarnPy3k("the sv module has been removed in "
	                   "Python 3.0", 2) < 0)
	    return;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
961

962
	m = Py_InitModule("sv", sv_methods);
963 964
	if (m == NULL)
		return;
965
	d = PyModule_GetDict(m);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
966

967
	SvError = PyErr_NewException("sv.error", NULL, NULL);
968
	if (SvError == NULL || PyDict_SetItemString(d, "error", SvError) != 0)
969
		return;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
970
}