2021-02-04 08:37:39 +01:00

868 lines
23 KiB
C
Executable File

#include <Python.h>
#include <windows.h>
#include <mmsystem.h>
/************************** DISPLAY PART ***************************/
typedef struct {
BITMAPINFOHEADER bmiHeader;
union {
DWORD bmiMask[3];
short bmiIndices[255];
};
} screenbmp_t;
typedef struct {
PyObject_HEAD
HWND win;
int width, height, bpp;
HDC dc;
HPALETTE hpal, hprevpal;
screenbmp_t screenbmpinfo;
unsigned char* screenbmpdata;
unsigned char* screenfirstline;
int screenscanline; /* < 0 ! */
PyObject* keyevents;
PyObject* mouseevents;
PyObject* motionevent;
} DisplayObject;
#define DisplayObject_Check(v) ((v)->ob_type == &Display_Type)
staticforward PyTypeObject Display_Type;
static void flush(DisplayObject* self)
{
/*GdiFlush();*/
}
static void release_window_data(DisplayObject* self)
{
if (self->hprevpal)
{
SelectPalette(self->dc, self->hprevpal, FALSE);
self->hprevpal = (HPALETTE) NULL;
}
if (self->hpal)
{
DeleteObject(self->hpal);
self->hpal = (HPALETTE) NULL;
}
if (self->dc && self->win)
{
ReleaseDC(self->win, self->dc);
self->dc = (HDC) NULL;
}
}
static void display_close(DisplayObject* self)
{
release_window_data(self);
if (self->win)
{
SetWindowLong(self->win, 0, 0);
DestroyWindow(self->win);
self->win = (HWND) NULL;
}
}
static LRESULT CALLBACK display_proc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
DisplayObject* self;
switch (uMsg) {
case WM_KEYDOWN:
case WM_KEYUP:
self = (DisplayObject*) GetWindowLong(hwnd, 0);
if (self)
{
PyObject* v;
int etype;
if (self->keyevents == NULL)
{
self->keyevents = PyList_New(0);
if (self->keyevents == NULL)
break;
}
etype = (uMsg == WM_KEYDOWN) ? 2 : 3;
v = Py_BuildValue("ii", (int) wParam, etype);
if (v == NULL)
break;
PyList_Append(self->keyevents, v);
Py_DECREF(v);
}
break;
case WM_LBUTTONDOWN:
self = (DisplayObject*) GetWindowLong(hwnd, 0);
if (self)
{
PyObject* v;
if (self->mouseevents == NULL)
{
self->mouseevents = PyList_New(0);
if (self->mouseevents == NULL)
break;
}
v = Py_BuildValue("ii", LOWORD(lParam), HIWORD(lParam));
if (v == NULL)
break;
PyList_Append(self->mouseevents, v);
Py_DECREF(v);
}
break;
case WM_MOUSEMOVE:
self = (DisplayObject*) GetWindowLong(hwnd, 0);
if (self)
{
Py_XDECREF(self->motionevent);
self->motionevent = Py_BuildValue("ii", LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_DESTROY:
self = (DisplayObject*) GetWindowLong(hwnd, 0);
if (self)
{
release_window_data(self);
self->win = (HWND) NULL;
}
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
static PyObject* new_display(PyObject* dummy, PyObject* args)
{
char* CLASSNAME = "winxshm";
WNDCLASS wcls;
DisplayObject* self;
int width, height, bytes, bpp, use_shm=0;
if (!PyArg_ParseTuple(args, "ii|i", &width, &height, &use_shm))
return NULL;
self = PyObject_New(DisplayObject, &Display_Type);
if (self == NULL)
return NULL;
memset(&self->win, 0, ((char*)(self+1)) - ((char*)(&self->win)));
self->width = width;
self->height = height;
/* set window class */
memset(&wcls, 0, sizeof(wcls));
wcls.style = CS_BYTEALIGNCLIENT;
wcls.lpfnWndProc = &display_proc;
wcls.cbWndExtra = sizeof(DisplayObject*);
//wcls.hInstance = HINSTANCE;
wcls.hCursor = LoadCursor(0, IDC_ARROW);
wcls.lpszClassName = CLASSNAME;
RegisterClass(&wcls);
/* Create the window */
self->win = CreateWindowEx(0, CLASSNAME, NULL,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
width + 2*GetSystemMetrics(SM_CXFIXEDFRAME),
height + 2*GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION),
(HWND) NULL, (HMENU) NULL,
/*HINSTANCE*/ 0, (LPVOID) NULL);
if (self->win == (HWND) NULL) goto err2;
SetWindowLong(self->win, 0, (long) self);
/* Create DC */
self->dc = GetDC(self->win);
if (!self->dc) goto err2;
self->bpp = bpp = GetDeviceCaps(self->dc, BITSPIXEL);
if (bpp == 8)
{
struct {
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[255];
} pal;
pal.palNumEntries = GetSystemPaletteEntries(self->dc, 0, 255, pal.palPalEntry);
if (pal.palNumEntries != 0)
{
int i;
pal.palVersion = 0x300;
self->hpal = CreatePalette((LOGPALETTE*)(&pal));
self->screenbmpinfo.bmiHeader.biClrUsed = pal.palNumEntries;
self->hprevpal = SelectPalette(self->dc, self->hpal, FALSE);
for (i=0; i<pal.palNumEntries; i++) {
self->screenbmpinfo.bmiIndices[i] = i;
}
}
}
if (bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32 && !self->hpal)
{
bpp = 24; /* default */
fprintf(stderr, "WARNING: a hi/true color screen mode of 15, 16, 24 or 32 bits per pixels\n");
fprintf(stderr, " is highly recommended !\n");
}
/* Allocate screen bitmaps */
bytes = (bpp+7)/8; /* per pixel */
bytes = (bytes*width+3)&~3; /* per scan line */
self->screenscanline = -bytes;
bytes = bytes*height; /* for the whole screen */
self->screenbmpdata = PyMem_Malloc(bytes);
self->screenfirstline = self->screenbmpdata + bytes + self->screenscanline;
if (self->screenbmpdata == NULL)
{
PyErr_NoMemory();
goto err2;
}
self->screenbmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
self->screenbmpinfo.bmiHeader.biWidth = self->width;
self->screenbmpinfo.bmiHeader.biHeight = self->height;
self->screenbmpinfo.bmiHeader.biPlanes = 1;
self->screenbmpinfo.bmiHeader.biBitCount = (bpp+7)&~7;
if (bpp == 16)
{
self->screenbmpinfo.bmiHeader.biCompression = BI_BITFIELDS;
self->screenbmpinfo.bmiMask[0] = 0xF800;
self->screenbmpinfo.bmiMask[1] = 0x07E0;
self->screenbmpinfo.bmiMask[2] = 0x001F;
}
flush(self);
return (PyObject*) self;
err2:
display_close(self);
Py_DECREF(self);
if (!PyErr_Occurred())
PyErr_SetString(PyExc_IOError, "cannot open window");
return NULL;
}
static void display_dealloc(DisplayObject* self)
{
display_close(self);
Py_XDECREF(self->keyevents);
Py_XDECREF(self->mouseevents);
Py_XDECREF(self->motionevent);
PyMem_Free(self->screenbmpdata);
PyObject_Del(self);
}
static PyObject* display_close1(DisplayObject* self, PyObject* args)
{
display_close(self);
Py_INCREF(Py_None);
return Py_None;
}
static int checkopen(DisplayObject* self)
{
if (self->win)
return 1;
//PyErr_SetString(PyExc_IOError, "the window was closed");
PyErr_SetString(PyExc_SystemExit, "window closed.");
return 0;
}
static PyObject* display_clear1(DisplayObject* self, PyObject* args)
{
if (!checkopen(self))
return NULL;
memset(self->screenbmpdata, 0, (-self->screenscanline) * self->height);
Py_INCREF(Py_None);
return Py_None;
}
static void pack_pixel(DisplayObject* self, unsigned char *data, int r, int g, int b,
int depth)
{
unsigned short pixel;
switch( depth )
{
case 8:
data[0] = GetNearestPaletteIndex(self->hpal, (b<<16) | (g<<8) | r);
break;
case 15:
pixel = ((r<<7) & 0x7c00) | ((g<<2) & 0x03e0) | ((b>>3) & 0x001f);
data[0] = (pixel) & 0xff;
data[1] = (pixel>>8) & 0xff;
break;
case 16:
/* assumes 5,6,5 model. */
pixel = ((r<<8) & 0xf800) | ((g<<3) & 0x07e0) | ((b>>3) & 0x001f);
data[0] = (pixel) & 0xff;
data[1] = (pixel>>8) & 0xff;
break;
case 24:
if( 1 )
{
data[0] = b;
data[1] = g;
data[2] = r;
break;
}
case 32:
*((long *)data) = (r<<16) | (g<<8) | b;
break;
}
}
static PyObject* display_pixmap1(DisplayObject* self, PyObject* args)
{
int w,h;
int length;
unsigned char* input = NULL;
long keycol = -1;
if (!checkopen(self))
return NULL;
if (!PyArg_ParseTuple(args, "ii|s#l", &w, &h, &input, &length, &keycol))
return NULL;
if (1) /* SHM */
{
int x, y;
unsigned char *dst;
int size, bytes_per_pixel;
long packed_keycol = keycol;
PyObject* result;
PyObject* str;
if (input == NULL )
{
Py_INCREF(Py_None);
return Py_None;
}
bytes_per_pixel = self->screenbmpinfo.bmiHeader.biBitCount/8;
size = bytes_per_pixel*w*h;
if( 3*w*h != length )
{
PyErr_SetString(PyExc_TypeError, "bad string length");
return NULL;
}
/* Create a new string and fill it with the correctly packed image */
str = PyString_FromStringAndSize(NULL, size);
if (!str)
return NULL;
if (keycol >= 0)
switch( self->bpp )
{
case 8:
packed_keycol = 0xFF;
break;
case 15:
packed_keycol = (1 << 10) | (1 << 5) | 1;
break;
case 16:
packed_keycol = (1 << 11) | (1 << 5) | 1;
break;
default:
packed_keycol = keycol;
break;
}
result = Py_BuildValue("iiOl", w, h, str, packed_keycol);
Py_DECREF(str); /* one ref left in 'result' */
if (!result)
return NULL;
dst = (unsigned char*) PyString_AS_STRING(str);
memset(dst,0,size);
for( y=0; y<h; y++ )
for( x=0; x<w; x++, input+=3, dst += bytes_per_pixel )
{
int r = input[0];
int g = input[1];
int b = input[2];
if( ((r<<16)|(g<<8)|b) == keycol )
for( b=0; b<bytes_per_pixel; b++ )
dst[b] = ((unsigned char *)&packed_keycol)[b];
else
pack_pixel(self, dst, r, g, b, self->bpp);
}
return result;
}
}
static PyObject* display_putppm1(DisplayObject* self, PyObject* args)
{
if (!checkopen(self))
return NULL;
if (1) /* SHM */
{
int x,y,w,h,scanline;
int clipx=0, clipy=0, clipw=65536, cliph=65536;
unsigned char* src;
int length;
long keycol;
int bytes_per_pixel = self->screenbmpinfo.bmiHeader.biBitCount/8;
unsigned char* data = self->screenfirstline;
if (!PyArg_ParseTuple(args, "ii(iis#l)|(iiii)",
&x, &y, &w, &h, &src, &length, &keycol,
&clipx, &clipy, &clipw, &cliph) || !data)
return NULL;
scanline = bytes_per_pixel*w;
if (scanline*h != length)
{
PyErr_SetString(PyExc_TypeError, "bad string length");
return NULL;
}
x -= clipx;
y -= clipy;
clipx += x;
clipy += y;
clipw += clipx;
cliph += clipy;
if (clipx<0) clipx=0;
if (clipy<0) clipy=0;
if (clipw>self->width) clipw=self->width;
if (cliph>self->height) cliph=self->height;
if (x<clipx) { src+=(clipx-x)*bytes_per_pixel; w+=x-clipx; x=clipx; }
if (y<clipy) { src+=(clipy-y)*scanline; h+=y-clipy; y=clipy; }
if (x+w > clipw) w = clipw-x;
if (y+h > cliph) h = cliph-y;
data += bytes_per_pixel*x+y*self->screenscanline;
while (h>0)
{
int i;
int b;
unsigned char* src0 = src;
unsigned char* data0 = data;
if (keycol < 0)
for (i=0; i<w; i++)
for (b=0; b<bytes_per_pixel; b++)
*data++ = *src++;
else
{
unsigned char *keycol_bytes = (unsigned char *)&keycol;
for (i=0; i<w; i++)
{
int transparent = 1;
for( b=0; b<bytes_per_pixel; b++ )
transparent = transparent && (keycol_bytes[b] == src[b]);
if (!transparent)
for( b=0; b<bytes_per_pixel; b++ )
*data++ = *src++;
else
{
data += bytes_per_pixel;
src += bytes_per_pixel;
}
}
}
src = src0 + scanline;
data = data0 + self->screenscanline;
h--;
}
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* display_getppm1(DisplayObject* self, PyObject* args)
{
if (!checkopen(self))
return NULL;
if (1) /* SHM */
{
int x,y,w,h,scanline;
int clipx=0, clipy=0, clipw=self->width, cliph=self->height;
unsigned char* dst;
int length;
PyObject* ignored;
PyObject* result;
PyObject* str;
int bytes_per_pixel = self->screenbmpinfo.bmiHeader.biBitCount/8;
unsigned char* data = self->screenfirstline;
if (!PyArg_ParseTuple(args, "(iiii)|O", &x, &y, &w, &h,
&ignored) || !data)
return NULL;
scanline = bytes_per_pixel*w;
length = scanline*h;
str = PyString_FromStringAndSize(NULL, length);
if (!str)
return NULL;
result = Py_BuildValue("iiOl", w, h, str, -1);
Py_DECREF(str); /* one ref left in 'result' */
if (!result)
return NULL;
dst = (unsigned char*) PyString_AS_STRING(str);
if (x<clipx) { dst+=(clipx-x)*bytes_per_pixel; w+=x-clipx; x=clipx; }
if (y<clipy) { dst+=(clipy-y)*scanline; h+=y-clipy; y=clipy; }
if (x+w > clipw) w = clipw-x;
if (y+h > cliph) h = cliph-y;
data += bytes_per_pixel*x+y*self->screenscanline;
while (h>0)
{
int i;
int b;
unsigned char* dst0 = dst;
unsigned char* data0 = data;
for (i=0; i<w; i++)
{
for( b=0; b<bytes_per_pixel; b++ )
*dst++ = *data++;
}
dst = dst0 + scanline;
data = data0 + self->screenscanline;
h--;
}
return result;
}
}
static int readXevents(DisplayObject* self)
{
MSG Msg;
while (PeekMessage(&Msg, (HWND) NULL, 0, 0, PM_REMOVE))
{
DispatchMessage(&Msg);
if (PyErr_Occurred())
return 0;
}
return checkopen(self);
}
#define ENABLE_EVENTS(mask) do { } while (0) /* nothing */
static PyObject* display_keyevents1(DisplayObject* self, PyObject* args)
{
PyObject* result;
ENABLE_EVENTS(KeyPressMask|KeyReleaseMask);
if (!readXevents(self))
return NULL;
result = self->keyevents;
if (result == NULL)
result = PyList_New(0);
else
self->keyevents = NULL;
return result;
}
static PyObject* display_mouseevents1(DisplayObject* self, PyObject* args)
{
PyObject* result;
ENABLE_EVENTS(ButtonPressMask);
result = self->mouseevents;
if (result == NULL)
result = PyList_New(0);
else
self->mouseevents = NULL;
return result;
}
static PyObject* display_pointermotion1(DisplayObject* self, PyObject* args)
{
PyObject* result;
ENABLE_EVENTS(PointerMotionMask);
result = self->motionevent;
if (result == NULL)
{
Py_INCREF(Py_None);
result = Py_None;
}
else
self->motionevent = NULL;
return result;
}
static PyObject* display_flip1(DisplayObject* self, PyObject* args)
{
int r;
if (!checkopen(self))
return NULL;
if (self->hpal)
RealizePalette(self->dc);
r = SetDIBitsToDevice(self->dc, 0, 0, self->width, self->height, 0, 0,
0, self->height, self->screenbmpdata, (BITMAPINFO*)(&self->screenbmpinfo),
DIB_PAL_COLORS);
if (!r)
{
PyErr_SetString(PyExc_IOError, "SetDIBitsToDevice failed");
return NULL;
}
flush(self);
if (!readXevents(self))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* display_shmmode(DisplayObject* self, PyObject *args)
{
return PyInt_FromLong(0);
}
static PyObject* display_settitle(DisplayObject* self, PyObject* args)
{
char* title;
if (!checkopen(self))
return NULL;
if (!PyArg_ParseTuple(args, "s", &title))
return NULL;
SetWindowText(self->win, title);
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef display_methods[] = {
{"close", (PyCFunction)display_close1, METH_VARARGS, NULL},
{"flip", (PyCFunction)display_flip1, METH_VARARGS, NULL},
{"clear", (PyCFunction)display_clear1, METH_VARARGS, NULL},
{"pixmap", (PyCFunction)display_pixmap1, METH_VARARGS, NULL},
{"putppm", (PyCFunction)display_putppm1, METH_VARARGS, NULL},
{"getppm", (PyCFunction)display_getppm1, METH_VARARGS, NULL},
{"keyevents",(PyCFunction)display_keyevents1,METH_VARARGS, NULL},
{"mouseevents",(PyCFunction)display_mouseevents1,METH_VARARGS,NULL},
{"pointermotion",(PyCFunction)display_pointermotion1,METH_VARARGS,NULL},
{"shmmode", (PyCFunction)display_shmmode, METH_VARARGS, NULL},
{"settitle", (PyCFunction)display_settitle, METH_VARARGS, NULL},
{NULL, NULL} /* sentinel */
};
static PyObject* display_getattr(DisplayObject* self, char* name)
{
return Py_FindMethod(display_methods, (PyObject*)self, name);
}
statichere PyTypeObject Display_Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Display", /*tp_name*/
sizeof(DisplayObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)display_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)display_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
};
/************************** AUDIO PART ***************************/
#define NUM_WAVE_HDR 2
typedef struct {
PyObject_HEAD
HWAVEOUT waveOut;
HANDLE doneEvent;
WAVEHDR waveHdr[NUM_WAVE_HDR];
int waveHdrCount, waveHdrNext;
} AudioObject;
#define AudioObject_Check(v) ((v)->ob_type == &Audio_Type)
staticforward PyTypeObject Audio_Type;
static PyObject* new_audio(PyObject* dummy, PyObject* args)
{
WAVEFORMATEX wf;
int channels, freq, bits, err, bufsize;
AudioObject* self;
if (!PyArg_ParseTuple(args, "iiii", &channels, &freq, &bits, &bufsize))
return NULL;
self = PyObject_New(AudioObject, &Audio_Type);
if (self == NULL)
return NULL;
self->waveHdrCount = 0;
self->waveHdrNext = 0;
self->waveOut = 0;
self->doneEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
memset(&wf, 0, sizeof(wf));
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.nChannels = channels;
wf.nSamplesPerSec = freq;
wf.wBitsPerSample = bits;
wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
err = waveOutOpen(&self->waveOut, WAVE_MAPPER, &wf, (DWORD) self->doneEvent, 0, CALLBACK_EVENT);
if (err != MMSYSERR_NOERROR || self->doneEvent == NULL) {
Py_DECREF(self);
PyErr_SetString(PyExc_IOError, "cannot open audio device");
return NULL;
}
while (self->waveHdrCount < NUM_WAVE_HDR) {
WAVEHDR* wh = &self->waveHdr[self->waveHdrCount];
wh->lpData = PyMem_Malloc(bufsize);
wh->dwBufferLength = bufsize;
wh->dwFlags = 0;
if (wh->lpData == NULL ||
waveOutPrepareHeader(self->waveOut, wh, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) {
Py_DECREF(self);
return NULL;
}
wh->dwFlags |= WHDR_DONE;
self->waveHdrCount++;
}
return (PyObject*) self;
}
static void audio_close(AudioObject* self)
{
if (self->waveOut != 0) {
waveOutReset(self->waveOut);
while (self->waveHdrCount > 0) {
WAVEHDR* wh = &self->waveHdr[--self->waveHdrCount];
waveOutUnprepareHeader(self->waveOut, wh, sizeof(WAVEHDR));
PyMem_Free(wh->lpData);
}
waveOutClose(self->waveOut);
self->waveOut = 0;
}
}
static void audio_dealloc(AudioObject* self)
{
audio_close(self);
PyObject_Del(self);
}
static PyObject* audio_wait1(AudioObject* self, PyObject* args)
{
float delay = -1.0;
if (!PyArg_ParseTuple(args, "|f", &delay))
return NULL;
if (self->waveHdrNext >= self->waveHdrCount) {
PyErr_SetString(PyExc_IOError, "audio device not ready");
return NULL;
}
Py_BEGIN_ALLOW_THREADS
while (!(self->waveHdr[self->waveHdrNext].dwFlags & WHDR_DONE)) {
WaitForSingleObject(self->doneEvent, delay<0.0?INFINITE:(DWORD)(delay*1000.0));
}
Py_END_ALLOW_THREADS
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* audio_ready1(AudioObject* self, PyObject* args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong(self->waveHdrNext < self->waveHdrCount &&
(self->waveHdr[self->waveHdrNext].dwFlags & WHDR_DONE));
}
static PyObject* audio_write1(AudioObject* self, PyObject* args)
{
WAVEHDR* wh;
char* buffer;
int bufsize;
if (!PyArg_ParseTuple(args, "s#", &buffer, &bufsize))
return NULL;
if (self->waveHdrNext >= self->waveHdrCount) {
PyErr_SetString(PyExc_IOError, "audio device not ready");
return NULL;
}
wh = &self->waveHdr[self->waveHdrNext];
if (!(wh->dwFlags & WHDR_DONE)) {
PyErr_SetString(PyExc_IOError, "audio device would block");
return NULL;
}
if ((DWORD) bufsize != wh->dwBufferLength) {
PyErr_SetString(PyExc_ValueError, "bufsize mismatch");
return NULL;
}
wh->dwFlags &= ~WHDR_DONE;
memcpy(wh->lpData, buffer, bufsize);
if (waveOutWrite(self->waveOut, wh, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) {
PyErr_SetString(PyExc_IOError, "audio device write error");
return NULL;
}
self->waveHdrNext++;
if (self->waveHdrNext >= self->waveHdrCount)
self->waveHdrNext = 0;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject* audio_close1(AudioObject* self, PyObject* args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
audio_close(self);
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef audio_methods[] = {
{"ready", (PyCFunction)audio_ready1, METH_VARARGS, NULL},
{"wait", (PyCFunction)audio_wait1, METH_VARARGS, NULL},
{"write", (PyCFunction)audio_write1, METH_VARARGS, NULL},
{"close", (PyCFunction)audio_close1, METH_VARARGS, NULL},
{NULL, NULL} /* sentinel */
};
static PyObject* audio_getattr(AudioObject* self, char* name)
{
return Py_FindMethod(audio_methods, (PyObject*)self, name);
}
statichere PyTypeObject Audio_Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Audio", /*tp_name*/
sizeof(AudioObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)audio_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)audio_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
};
static PyMethodDef WinMethods[] = {
{"Display", new_display, METH_VARARGS},
{"Audio", new_audio, METH_VARARGS},
{NULL, NULL} /* Sentinel */
};
void initwingame(void)
{
Display_Type.ob_type = &PyType_Type;
Audio_Type.ob_type = &PyType_Type;
Py_InitModule("wingame", WinMethods);
}