svmodule.c 22 KB
Newer Older
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1
/**********************************************************
2 3
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
Sjoerd Mullender's avatar
Sjoerd Mullender committed
4 5 6

                        All Rights Reserved

7 8
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
Sjoerd Mullender's avatar
Sjoerd Mullender committed
9
provided that the above copyright notice appear in all copies and that
10
both that copyright notice and this permission notice appear in
Sjoerd Mullender's avatar
Sjoerd Mullender committed
11
supporting documentation, and that the names of Stichting Mathematisch
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Centrum or CWI or Corporation for National Research Initiatives or
CNRI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.

While CWI is the initial source for this software, a modified version
is made available by the Corporation for National Research Initiatives
(CNRI) at the Internet address ftp://ftp.python.org.

STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
CENTRUM OR CNRI 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.
Sjoerd Mullender's avatar
Sjoerd Mullender committed
29 30 31 32 33

******************************************************************/

/* SV module -- interface to the Indigo video board */

34 35 36 37 38
/* 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
39 40
#include <sys/time.h>
#include <svideo.h>
41
#include "Python.h"
Sjoerd Mullender's avatar
Sjoerd Mullender committed
42
#include "compile.h"
43
#include "yuv.h"		/* for YUV conversion functions */
Sjoerd Mullender's avatar
Sjoerd Mullender committed
44 45

typedef struct {
46
	PyObject_HEAD
Sjoerd Mullender's avatar
Sjoerd Mullender committed
47 48 49 50 51
	SV_nodeP ob_svideo;
	svCaptureInfo ob_info;
} svobject;

typedef struct {
52
	PyObject_HEAD
Sjoerd Mullender's avatar
Sjoerd Mullender committed
53 54 55 56 57 58
	void *ob_capture;
	int ob_mustunlock;
	svCaptureInfo ob_info;
	svobject *ob_svideo;
} captureobject;

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

61
static PyObject *newcaptureobject Py_PROTO((svobject *, void *, int));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
62 63

/* Set a SV-specific error from svideo_errno and return NULL */
64
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
65 66
sv_error()
{
67
	PyErr_SetString(SvError, svStrerror(svideo_errno));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
68 69 70
	return NULL;
}

71
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
72 73
svc_conversion(self, args, function, factor)
	captureobject *self;
74
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
75
	void (*function)();
76
	float factor;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
77
{
78
	PyObject *output;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
79
	int invert;
80
	char* outstr;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
81

82
	if (!PyArg_Parse(args, "i", &invert))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
83 84
		return NULL;

85 86 87 88
	if (!(output = PyString_FromStringAndSize(
		NULL,
		(int)(self->ob_info.width * self->ob_info.height * factor))))
	{
Sjoerd Mullender's avatar
Sjoerd Mullender committed
89
		return NULL;
90 91 92 93 94
	}
	if (!(outstr = PyString_AsString(output))) {
		Py_DECREF(output);
		return NULL;
	}
Sjoerd Mullender's avatar
Sjoerd Mullender committed
95

96 97
	(*function)((boolean)invert, self->ob_capture,
		    outstr,
Sjoerd Mullender's avatar
Sjoerd Mullender committed
98 99 100 101 102
		    self->ob_info.width, self->ob_info.height);

	return output;
}

103 104 105 106
/*
 * 3 functions to convert from Starter Video YUV 4:1:1 format to
 * Compression Library 4:2:2 Duplicate Chroma format.
 */
107
static PyObject *
108 109
svc_YUVtoYUV422DC(self, args)
	captureobject *self;
110
	PyObject *args;
111 112
{
	if (self->ob_info.format != SV_YUV411_FRAMES) {
113
		PyErr_SetString(SvError, "data has bad format");
114 115 116 117 118
		return NULL;
	}
	return svc_conversion(self, args, yuv_sv411_to_cl422dc, 2.0);
}

119
static PyObject *
120 121
svc_YUVtoYUV422DC_quarter(self, args)
	captureobject *self;
122
	PyObject *args;
123 124
{
	if (self->ob_info.format != SV_YUV411_FRAMES) {
125
		PyErr_SetString(SvError, "data has bad format");
126 127
		return NULL;
	}
128 129
	return svc_conversion(self, args,
			      yuv_sv411_to_cl422dc_quartersize, 0.5);
130 131
}

132
static PyObject *
133 134
svc_YUVtoYUV422DC_sixteenth(self, args)
	captureobject *self;
135
	PyObject *args;
136 137
{
	if (self->ob_info.format != SV_YUV411_FRAMES) {
138
		PyErr_SetString(SvError, "data has bad format");
139 140
		return NULL;
	}
141 142
	return svc_conversion(self, args,
			      yuv_sv411_to_cl422dc_sixteenthsize, 0.125);
143 144
}

145
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
146 147
svc_YUVtoRGB(self, args)
	captureobject *self;
148
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
149 150 151 152 153 154
{
	switch (self->ob_info.format) {
	case SV_YUV411_FRAMES:
	case SV_YUV411_FRAMES_AND_BLANKING_BUFFER:
		break;
	default:
155
		PyErr_SetString(SvError, "data had bad format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
156 157
		return NULL;
	}
158
	return svc_conversion(self, args, svYUVtoRGB, (float) sizeof(long));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
159 160
}

161
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
162 163
svc_RGB8toRGB32(self, args)
	captureobject *self;
164
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
165 166
{
	if (self->ob_info.format != SV_RGB8_FRAMES) {
167
		PyErr_SetString(SvError, "data has bad format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
168 169
		return NULL;
	}
170
	return svc_conversion(self, args, svRGB8toRGB32, (float) sizeof(long));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
171 172
}

173
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
174 175
svc_InterleaveFields(self, args)
	captureobject *self;
176
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
177 178
{
	if (self->ob_info.format != SV_RGB8_FRAMES) {
179
		PyErr_SetString(SvError, "data has bad format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
180 181
		return NULL;
	}
182
	return svc_conversion(self, args, svInterleaveFields, 1.0);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
183 184
}

185
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
186 187
svc_GetFields(self, args)
	captureobject *self;
188
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
189
{
190 191 192
	PyObject *f1 = NULL;
	PyObject *f2 = NULL;
	PyObject *ret = NULL;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
193
	int fieldsize;
194
	char* obcapture;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
195 196

	if (self->ob_info.format != SV_RGB8_FRAMES) {
197
		PyErr_SetString(SvError, "data has bad format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
198 199 200 201
		return NULL;
	}

	fieldsize = self->ob_info.width * self->ob_info.height / 2;
202 203 204 205 206 207 208 209 210 211 212 213
	obcapture = (char*)self->ob_capture;
	
	if (!(f1 = PyString_FromStringAndSize(obcapture, fieldsize)))
		goto finally;
	if (!(f2 = PyString_FromStringAndSize(obcapture + fieldsize,
					      fieldsize)))
		goto finally;
	ret = Py_BuildValue("(OO)", f1, f2);

  finally:
	Py_XDECREF(f1);
	Py_XDECREF(f2);
214
	return ret;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
215 216
}
	
217
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
218 219
svc_UnlockCaptureData(self, args)
	captureobject *self;
220
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
221
{
222
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
223 224 225
		return NULL;

	if (!self->ob_mustunlock) {
226
		PyErr_SetString(SvError, "buffer should not be unlocked");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
227 228 229 230 231 232 233 234
		return NULL;
	}

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

	self->ob_mustunlock = 0;

235 236
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
237 238 239 240 241
}

#ifdef USE_GL
#include <gl.h>

242
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
243 244
svc_lrectwrite(self, args)
	captureobject *self;
245
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
246 247 248
{
	Screencoord x1, x2, y1, y2;

249
	if (!PyArg_Parse(args, "(hhhh)", &x1, &x2, &y1, &y2))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
250 251 252 253
		return NULL;

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

254 255
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
256 257 258
}
#endif

259
static PyObject *
260
svc_writefile(self, args)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
261
	captureobject *self;
262
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
263
{
264
	PyObject *file;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
265
	int size;
266
	FILE* fp;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
267

268
	if (!PyArg_Parse(args, "O", &file))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
269 270
		return NULL;

271 272
	if (!PyFile_Check(file)) {
		PyErr_SetString(SvError, "not a file object");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
273 274 275
		return NULL;
	}

276 277 278
	if (!(fp = PyFile_AsFile(file)))
		return NULL;

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

281 282
	if (fwrite(self->ob_capture, sizeof(long), size, fp) != size) {
		PyErr_SetString(SvError, "writing failed");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
283 284 285
		return NULL;
	}

286 287
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
288 289
}

290
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
291 292
svc_FindVisibleRegion(self, args)
	captureobject *self;
293
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
294 295 296 297
{
	void *visible;
	int width;

298
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
299 300
		return NULL;

301 302 303
	if (svFindVisibleRegion(self->ob_svideo->ob_svideo,
				self->ob_capture, &visible,
				self->ob_info.width))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
304 305 306
		return sv_error();

	if (visible == NULL) {
307
		PyErr_SetString(SvError, "data in wrong format");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
308 309 310 311 312 313
		return NULL;
	}

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

314 315 316 317 318 319 320 321 322 323
static PyMethodDef capture_methods[] = {
	{"YUVtoRGB",		(PyCFunction)svc_YUVtoRGB},
	{"RGB8toRGB32",		(PyCFunction)svc_RGB8toRGB32},
	{"InterleaveFields",	(PyCFunction)svc_InterleaveFields},
	{"UnlockCaptureData",	(PyCFunction)svc_UnlockCaptureData},
	{"FindVisibleRegion",	(PyCFunction)svc_FindVisibleRegion},
	{"GetFields",		(PyCFunction)svc_GetFields},
	{"YUVtoYUV422DC",	(PyCFunction)svc_YUVtoYUV422DC},
	{"YUVtoYUV422DC_quarter",(PyCFunction)svc_YUVtoYUV422DC_quarter},
	{"YUVtoYUV422DC_sixteenth",(PyCFunction)svc_YUVtoYUV422DC_sixteenth},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
324
#ifdef USE_GL
325
	{"lrectwrite",		(PyCFunction)svc_lrectwrite},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
326
#endif
327
	{"writefile",		(PyCFunction)svc_writefile},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
328 329 330 331 332 333 334 335 336
	{NULL,			NULL} 		/* sentinel */
};

static void
capture_dealloc(self)
	captureobject *self;
{
	if (self->ob_capture != NULL) {
		if (self->ob_mustunlock)
337 338
			(void)svUnlockCaptureData(self->ob_svideo->ob_svideo,
						  self->ob_capture);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
339
		self->ob_capture = NULL;
340
		Py_DECREF(self->ob_svideo);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
341 342
		self->ob_svideo = NULL;
	}
343
	PyMem_DEL(self);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
344 345
}

346
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
347 348 349 350
capture_getattr(self, name)
	svobject *self;
	char *name;
{
351
	return Py_FindMethod(capture_methods, (PyObject *)self, name);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
352 353
}

354 355
PyTypeObject Capturetype = {
	PyObject_HEAD_INIT(&PyType_Type)
356 357 358 359
	0,				/*ob_size*/
	"capture",			/*tp_name*/
	sizeof(captureobject),		/*tp_size*/
	0,				/*tp_itemsize*/
Sjoerd Mullender's avatar
Sjoerd Mullender committed
360
	/* methods */
361 362 363 364 365 366
	(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
367 368
};

369
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
370 371 372 373 374 375 376
newcaptureobject(self, ptr, mustunlock)
	svobject *self;
	void *ptr;
	int mustunlock;
{
	captureobject *p;

377
	p = PyObject_NEW(captureobject, &Capturetype);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
378 379 380
	if (p == NULL)
		return NULL;
	p->ob_svideo = self;
381
	Py_INCREF(self);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
382 383 384
	p->ob_capture = ptr;
	p->ob_mustunlock = mustunlock;
	p->ob_info = self->ob_info;
385
	return (PyObject *) p;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
386 387
}

388
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
389 390
sv_GetCaptureData(self, args)
	svobject *self;
391
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
392 393 394
{
	void *ptr;
	long fieldID;
395
	PyObject *res, *c;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
396

397
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
398 399 400 401 402 403
		return NULL;

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

	if (ptr == NULL) {
404
		PyErr_SetString(SvError, "no data available");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
405 406 407 408 409 410
		return NULL;
	}

	c = newcaptureobject(self, ptr, 1);
	if (c == NULL)
		return NULL;
411 412
	res = Py_BuildValue("(Oi)", c, fieldID);
	Py_DECREF(c);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
413 414 415
	return res;
}

416
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
417 418
sv_BindGLWindow(self, args)
	svobject *self;
419
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
420 421 422 423
{
	long wid;
	int mode;

424
	if (!PyArg_Parse(args, "(ii)", &wid, &mode))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
425 426 427 428 429
		return NULL;

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

430 431
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
432 433
}

434
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
435 436
sv_EndContinuousCapture(self, args)
	svobject *self;
437
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
438 439
{

440
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
441 442 443 444 445
		return NULL;

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

446 447
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
448 449
}

450
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
451 452
sv_IsVideoDisplayed(self, args)
	svobject *self;
453
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
454 455 456
{
	int v;

457
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
458 459 460 461 462 463
		return NULL;

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

464
	return PyInt_FromLong((long) v);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
465 466
}

467
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
468 469
sv_OutputOffset(self, args)
	svobject *self;
470
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
471 472 473 474
{
	int x_offset;
	int y_offset;

475
	if (!PyArg_Parse(args, "(ii)", &x_offset, &y_offset))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
476 477 478 479 480
		return NULL;

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

481 482
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
483 484
}

485
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
486 487
sv_PutFrame(self, args)
	svobject *self;
488
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
489 490 491
{
	char *buffer;

492
	if (!PyArg_Parse(args, "s", &buffer))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
493 494 495 496 497
		return NULL;

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

498 499
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
500 501
}

502
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
503 504
sv_QuerySize(self, args)
	svobject *self;
505
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
506 507 508 509 510 511
{
	int w;
	int h;
	int rw;
	int rh;

512
	if (!PyArg_Parse(args, "(ii)", &w, &h))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
513 514 515 516 517
		return NULL;

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

518
	return Py_BuildValue("(ii)", (long) rw, (long) rh);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
519 520
}

521
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
522 523
sv_SetSize(self, args)
	svobject *self;
524
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
525 526 527 528
{
	int w;
	int h;

529
	if (!PyArg_Parse(args, "(ii)", &w, &h))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
530 531 532 533 534
		return NULL;

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

535 536
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
537 538
}

539
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
540 541
sv_SetStdDefaults(self, args)
	svobject *self;
542
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
543 544
{

545
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
546 547 548 549 550
		return NULL;

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

551 552
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
553 554
}

555
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
556 557
sv_UseExclusive(self, args)
	svobject *self;
558
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
559 560 561 562
{
	boolean onoff;
	int mode;

563
	if (!PyArg_Parse(args, "(ii)", &onoff, &mode))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
564 565 566 567 568
		return NULL;

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

569 570
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
571 572
}

573
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
574 575
sv_WindowOffset(self, args)
	svobject *self;
576
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
577 578 579 580
{
	int x_offset;
	int y_offset;

581
	if (!PyArg_Parse(args, "(ii)", &x_offset, &y_offset))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
582 583 584 585 586
		return NULL;

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

587 588
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
589 590
}

591
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
592 593
sv_CaptureBurst(self, args)
	svobject *self;
594
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
595 596 597 598
{
	int bytes, i;
	svCaptureInfo info;
	void *bitvector = NULL;
599 600
	PyObject *videodata = NULL;
	PyObject *bitvecobj = NULL;
601
	PyObject *res = NULL;
602 603 604 605 606
	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
607 608 609 610 611 612 613 614 615
		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:
616
		PyErr_SetString(SvError, "illegal format specified");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
617 618 619 620
		return NULL;
	}

	if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) {
621 622
		res = sv_error();
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
623 624
	}

625 626
	if (!(videodata = PyString_FromStringAndSize(NULL, bytes)))
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
627 628

	/* XXX -- need to do something about the bitvector */
629 630 631 632 633 634 635 636 637
	{
		char* str = PyString_AsString(videodata);
		if (!str)
			goto finally;
		
		if (svCaptureBurst(self->ob_svideo, &info, str, bitvector)) {
			res = sv_error();
			goto finally;
		}
Sjoerd Mullender's avatar
Sjoerd Mullender committed
638 639 640 641
	}

	if (bitvector) {
		if (evenitem == NULL) {
642 643
			if (!(evenitem = PyInt_FromLong(0)))
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
644 645
		}
		if (odditem == NULL) {
646 647
			if (!(odditem = PyInt_FromLong(1)))
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
648
		}
649 650 651
		if (!(bitvecobj = PyTuple_New(2 * info.size)))
			goto finally;

Sjoerd Mullender's avatar
Sjoerd Mullender committed
652
		for (i = 0; i < 2 * info.size; i++) {
653 654
			int sts;

Sjoerd Mullender's avatar
Sjoerd Mullender committed
655
			if (SV_GET_FIELD(bitvector, i) == SV_EVEN_FIELD) {
656 657
				Py_INCREF(evenitem);
				sts = PyTuple_SetItem(bitvecobj, i, evenitem);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
658
			} else {
659 660
				Py_INCREF(odditem);
				sts = PyTuple_SetItem(bitvecobj, i, odditem);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
661
			}
662 663
			if (sts < 0)
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
664 665
		}
	} else {
666 667
		bitvecobj = Py_None;
		Py_INCREF(Py_None);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
668 669
	}

670 671 672 673 674 675 676 677 678 679 680
	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
681 682 683
	return res;
}

684
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
685 686
sv_CaptureOneFrame(self, args)
	svobject *self;
687
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
688 689 690 691
{
	svCaptureInfo info;
	int format, width, height;
	int bytes;
692 693
	PyObject *videodata = NULL;
	PyObject *res = NULL;
694
	char *str;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
695
	
696
	if (!PyArg_Parse(args, "(iii)", &format, &width, &height))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
697
		return NULL;
698

Sjoerd Mullender's avatar
Sjoerd Mullender committed
699 700 701 702 703 704 705
	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();
706 707

	if (!(videodata = PyString_FromStringAndSize(NULL, bytes)))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
708
		return NULL;
709
	
710 711 712
	str = PyString_AsString(videodata);
	if (!str)
		goto finally;
713 714 715 716

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

719 720 721 722
	res = Py_BuildValue("(iiO)", width, height, videodata);

  finally:
	Py_XDECREF(videodata);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
723 724 725
	return res;
}

726
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
727 728
sv_InitContinuousCapture(self, args)
	svobject *self;
729
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
730 731 732
{
	svCaptureInfo info;

733 734 735
	if (!PyArg_Parse(args, "(iiiii)", &info.format,
			 &info.width, &info.height,
			 &info.size, &info.samplingrate))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
736 737 738 739 740 741 742
		return NULL;

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

	self->ob_info = info;

743 744
	return Py_BuildValue("(iiiii)", info.format, info.width, info.height,
			     info.size, info.samplingrate);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
745 746
}

747
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
748 749
sv_LoadMap(self, args)
	svobject *self;
750
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
751
{
752 753 754
	PyObject *rgb;
	PyObject *res = NULL;
	rgb_tuple *mapp = NULL;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
755
	int maptype;
756
	int i, j;			     /* indices */
Sjoerd Mullender's avatar
Sjoerd Mullender committed
757

758
	if (!PyArg_Parse(args, "(iO)", &maptype, &rgb))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
759
		return NULL;
760 761 762

	if (!PyList_Check(rgb) || PyList_Size(rgb) != 256) {
		PyErr_BadArgument();
Sjoerd Mullender's avatar
Sjoerd Mullender committed
763 764
		return NULL;
	}
765 766 767 768

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

Sjoerd Mullender's avatar
Sjoerd Mullender committed
769
	for (i = 0; i < 256; i++) {
770 771 772 773 774 775 776
		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
777 778
		}
		for (j = 0; j < 3; j++) {
779 780 781 782 783 784 785
			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
786 787
			}
			switch (j) {
788 789 790
			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
791
			}
792 793
			if (PyErr_Occurred())
				goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
794 795 796 797
		}
	}

	if (svLoadMap(self->ob_svideo, maptype, mapp)) {
798 799
		res = sv_error();
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
800 801
	}

802 803
	Py_INCREF(Py_None);
	res = Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
804

805 806 807
  finally:
	PyMem_DEL(mapp);
	return res;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
808 809
}
		
810
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
811 812
sv_CloseVideo(self, args)
	svobject *self;
813
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
814
{
815
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
816 817 818 819 820
		return NULL;

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

821 822 823
	self->ob_svideo = NULL;
	Py_INCREF(Py_None);
	return Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
824 825
}

826
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
827 828
doParams(self, args, func, modified)
	svobject *self;
829
	PyObject *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
830 831 832
	int (*func)(SV_nodeP, long *, int);
	int modified;
{
833 834 835
	PyObject *list;
	PyObject *res = NULL;
	long *PVbuffer = NULL;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
836 837 838
	long length;
	int i;
	
839
	if (!PyArg_Parse(args, "O", &list))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
840
		return NULL;
841 842 843

	if (!PyList_Check(list)) {
		PyErr_BadArgument();
Sjoerd Mullender's avatar
Sjoerd Mullender committed
844 845
		return NULL;
	}
846 847 848 849 850

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

	PVbuffer = PyMem_NEW(long, length);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
851
	if (PVbuffer == NULL)
852 853
		return PyErr_NoMemory();

Sjoerd Mullender's avatar
Sjoerd Mullender committed
854
	for (i = 0; i < length; i++) {
855 856 857 858 859 860 861
		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
862
		}
863 864 865 866 867 868
		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
869 870 871
	}

	if ((*func)(self->ob_svideo, PVbuffer, length)) {
872 873
		res = sv_error();
		goto finally;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
874 875 876
	}

	if (modified) {
877 878 879 880 881
		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
882 883
	}

884 885
	Py_INCREF(Py_None);
	res = Py_None;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
886

887 888 889
  finally:
	PyMem_DEL(PVbuffer);
	return res;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
890 891
}

892
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
893
sv_GetParam(self, args)
894
	PyObject *self, *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
895 896 897 898
{
	return doParams(self, args, svGetParam, 1);
}

899
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
900
sv_GetParamRange(self, args)
901
	PyObject *self, *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
902 903 904 905
{
	return doParams(self, args, svGetParamRange, 1);
}

906
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
907
sv_SetParam(self, args)
908
	PyObject *self, *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
909 910 911 912
{
	return doParams(self, args, svSetParam, 0);
}

913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
static PyMethodDef svideo_methods[] = {
	{"BindGLWindow",	(PyCFunction)sv_BindGLWindow},
	{"EndContinuousCapture",(PyCFunction)sv_EndContinuousCapture},
	{"IsVideoDisplayed",	(PyCFunction)sv_IsVideoDisplayed},
	{"OutputOffset",	(PyCFunction)sv_OutputOffset},
	{"PutFrame",		(PyCFunction)sv_PutFrame},
	{"QuerySize",		(PyCFunction)sv_QuerySize},
	{"SetSize",		(PyCFunction)sv_SetSize},
	{"SetStdDefaults",	(PyCFunction)sv_SetStdDefaults},
	{"UseExclusive",	(PyCFunction)sv_UseExclusive},
	{"WindowOffset",	(PyCFunction)sv_WindowOffset},
	{"InitContinuousCapture",(PyCFunction)sv_InitContinuousCapture},
	{"CaptureBurst",	(PyCFunction)sv_CaptureBurst},
	{"CaptureOneFrame",	(PyCFunction)sv_CaptureOneFrame},
	{"GetCaptureData",	(PyCFunction)sv_GetCaptureData},
	{"CloseVideo",		(PyCFunction)sv_CloseVideo},
	{"LoadMap",		(PyCFunction)sv_LoadMap},
	{"GetParam",		(PyCFunction)sv_GetParam},
	{"GetParamRange",	(PyCFunction)sv_GetParamRange},
	{"SetParam",		(PyCFunction)sv_SetParam},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
933 934 935
	{NULL,			NULL} 		/* sentinel */
};

936
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
937
sv_conversion(self, args, function, inputfactor, factor)
938
	PyObject *self, *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
939
	void (*function)();
940 941
	int inputfactor;
	float factor;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
942 943
{
	int invert, width, height, inputlength;
944 945
	char *input, *str;
	PyObject *output;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
946

947 948
	if (!PyArg_Parse(args, "(is#ii)", &invert,
			 &input, &inputlength, &width, &height))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
949 950 951
		return NULL;

	if (width * height * inputfactor > inputlength) {
952
		PyErr_SetString(SvError, "input buffer not long enough");
Sjoerd Mullender's avatar
Sjoerd Mullender committed
953 954 955
		return NULL;
	}

956 957
	if (!(output = PyString_FromStringAndSize(NULL,
					      (int)(width * height * factor))))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
958 959
		return NULL;

960 961 962 963 964 965
	str = PyString_AsString(output);
	if (!str) {
		Py_DECREF(output);
		return NULL;
	}
	(*function)(invert, input, str, width, height);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
966 967 968 969

	return output;
}

970
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
971
sv_InterleaveFields(self, args)
972
	PyObject *self, *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
973
{
974
	return sv_conversion(self, args, svInterleaveFields, 1, 1.0);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
975 976
}

977
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
978
sv_RGB8toRGB32(self, args)
979
	PyObject *self, *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
980
{
981
	return sv_conversion(self, args, svRGB8toRGB32, 1, (float) sizeof(long));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
982 983
}

984
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
985
sv_YUVtoRGB(self, args)
986
	PyObject *self, *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
987
{
988
	return sv_conversion(self, args, svYUVtoRGB, 2, (float) sizeof(long));
Sjoerd Mullender's avatar
Sjoerd Mullender committed
989 990 991 992 993 994 995 996
}

static void
svideo_dealloc(self)
	svobject *self;
{
	if (self->ob_svideo != NULL)
		(void) svCloseVideo(self->ob_svideo);
997
	PyMem_DEL(self);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
998 999
}

1000
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1001 1002 1003 1004
svideo_getattr(self, name)
	svobject *self;
	char *name;
{
1005
	return Py_FindMethod(svideo_methods, (PyObject *)self, name);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1006 1007
}

1008 1009
PyTypeObject Svtype = {
	PyObject_HEAD_INIT(&PyType_Type)
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1010 1011 1012 1013 1014
	0,			/*ob_size*/
	"sv",			/*tp_name*/
	sizeof(svobject),	/*tp_size*/
	0,			/*tp_itemsize*/
	/* methods */
1015
	(destructor)svideo_dealloc, /*tp_dealloc*/
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1016
	0,			/*tp_print*/
1017
	(getattrfunc)svideo_getattr, /*tp_getattr*/
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1018 1019 1020 1021 1022
	0,			/*tp_setattr*/
	0,			/*tp_compare*/
	0,			/*tp_repr*/
};

1023
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1024 1025 1026 1027 1028
newsvobject(svp)
	SV_nodeP svp;
{
	svobject *p;

1029
	p = PyObject_NEW(svobject, &Svtype);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1030 1031 1032 1033 1034 1035 1036 1037
	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;
1038
	return (PyObject *) p;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1039 1040
}

1041
static PyObject *
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1042
sv_OpenVideo(self, args)
1043
	PyObject *self, *args;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1044 1045 1046
{
	SV_nodeP svp;

1047
	if (!PyArg_Parse(args, ""))
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1048 1049 1050 1051 1052 1053 1054 1055 1056
		return NULL;

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

	return newsvobject(svp);
}

1057 1058 1059 1060 1061
static PyMethodDef sv_methods[] = {
	{"InterleaveFields",	(PyCFunction)sv_InterleaveFields},
	{"RGB8toRGB32",		(PyCFunction)sv_RGB8toRGB32},
	{"YUVtoRGB",		(PyCFunction)sv_YUVtoRGB},
	{"OpenVideo",		(PyCFunction)sv_OpenVideo},
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1062 1063 1064 1065 1066 1067
	{NULL,			NULL}	/* Sentinel */
};

void
initsv()
{
1068
	PyObject *m, *d;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1069

1070 1071
	m = Py_InitModule("sv", sv_methods);
	d = PyModule_GetDict(m);
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1072

1073
	SvError = PyErr_NewException("sv.error", NULL, NULL);
1074
	if (SvError == NULL || PyDict_SetItemString(d, "error", SvError) != 0)
1075
		return;
Sjoerd Mullender's avatar
Sjoerd Mullender committed
1076
}