From e854889b99b9e515dc69d237b1031b5705e83b60 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Wed, 9 Mar 2005 04:58:11 +0000 Subject: fixes for detached operation and single-threaded version use lock count instead of message queuing to avoid py->py messaging deadlock support for buffer objects (preliminary) updated build system little restructuring fixes for single-threaded compilation added support for numarray svn path=/trunk/; revision=2610 --- externals/grill/py/source/pybuffer.cpp | 244 +++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 externals/grill/py/source/pybuffer.cpp (limited to 'externals/grill/py/source/pybuffer.cpp') diff --git a/externals/grill/py/source/pybuffer.cpp b/externals/grill/py/source/pybuffer.cpp new file mode 100644 index 00000000..ed1b2749 --- /dev/null +++ b/externals/grill/py/source/pybuffer.cpp @@ -0,0 +1,244 @@ +/* + +py/pyext - python script object for PD and Max/MSP + +Copyright (c)2002-2005 Thomas Grill (gr@grrrr.org) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +#include "main.h" + +#ifdef PY_NUMARRAY +#include +static bool nasupport = false; +static NumarrayType numtype; +#endif + +// PD defines a T_OBJECT symbol +#undef T_OBJECT +#include "structmember.h" +#include "bufferobject.h" + +static PyObject *buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + pySamplebuffer *self = (pySamplebuffer *)pySamplebuffer_Type.tp_alloc(&pySamplebuffer_Type, 0); + self->sym = NULL; + self->buf = NULL; + self->dirty = false; + return (PyObject *)self; +} + +static void buffer_dealloc(PyObject *obj) +{ + pySamplebuffer *self = (pySamplebuffer *)obj; + + if(self->buf) { + self->buf->Unlock(self->lock); + if(self->dirty) self->buf->Dirty(true); + delete self->buf; + } + + obj->ob_type->tp_free(obj); +} + +static int buffer_init(PyObject *obj, PyObject *args, PyObject *kwds) +{ + FLEXT_ASSERT(pySamplebuffer_Check(obj)); + + PyObject *arg = PySequence_GetItem(args,0); // new reference + if(!arg) return -1; + + int ret = 0; + + pySamplebuffer *self = (pySamplebuffer *)obj; + FLEXT_ASSERT(!self->sym && !self->buf); + + if(pySymbol_Check(arg)) + self->sym = pySymbol_AS_SYMBOL(arg); + else if(PyString_Check(arg)) + self->sym = flext::MakeSymbol(PyString_AS_STRING(arg)); + else + ret = -1; + Py_DECREF(arg); + + if(self->sym) { + flext::buffer *b = new flext::buffer(self->sym); + if(b->Ok() && b->Valid()) + self->lock = (self->buf = b)->Lock(); + else + delete b; + } + + return ret; +} + +static PyObject *buffer_repr(PyObject *self) +{ + FLEXT_ASSERT(pySamplebuffer_Check(self)); + return (PyObject *)PyString_FromFormat("",pySamplebuffer_AS_STRING(self)); +} + +static long buffer_hash(PyObject *self) +{ + FLEXT_ASSERT(pySamplebuffer_Check(self)); + return (long)(((pySamplebuffer *)self)->buf); +} + +static PyObject *buffer_getsymbol(pySamplebuffer* self,void *closure) +{ + if(self->sym) + return pySymbol_FromSymbol(self->sym); + else { + Py_INCREF(Py_None); + return Py_None; + } +} + +static PyGetSetDef buffer_getseters[] = { + {"symbol",(getter)buffer_getsymbol, NULL, NULL}, + {NULL} /* Sentinel */ +}; + +static PyObject *buffer_array(PyObject *obj) +{ + PyObject *ret; +#ifdef PY_NUMARRAY + if(nasupport) { + pySamplebuffer *self = (pySamplebuffer *)obj; + if(self->buf) { + maybelong shape[2]; + shape[0] = self->buf->Frames(); + shape[1] = self->buf->Channels(); + ret = (PyObject *)NA_NewAllFromBuffer(2,shape,numtype,(PyObject *)self,0,sizeof(t_sample *),NA_ByteOrder(),1,1); + } + else + Py_INCREF(ret = Py_None); + } + else { + PyErr_Format(PyExc_RuntimeError,"No numarray support"); + ret = NULL; + } +#else + Py_INCREF(ret = Py_None); +#endif + return ret; +} + +static PyObject *buffer_dirty(PyObject *obj) +{ + ((pySamplebuffer *)obj)->dirty = true; + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef buffer_methods[] = { + {"array", (PyCFunction)buffer_array,METH_NOARGS,"Return a numarray object"}, + {"dirty", (PyCFunction)buffer_dirty,METH_NOARGS,"Mark buffer as dirty"}, + {NULL} /* Sentinel */ +}; + + + +// support the buffer protocol +static int buffer_readbuffer(PyObject *obj, int segment, void **ptrptr) +{ + flext::buffer *b = ((pySamplebuffer *)obj)->buf; + ptrptr[0] = b->Data(); + return b->Channels()*b->Frames()*sizeof(t_sample); +} + +static int buffer_writebuffer(PyObject *obj, int segment, void **ptrptr) +{ + flext::buffer *b = ((pySamplebuffer *)obj)->buf; + ptrptr[0] = b->Data(); + return b->Channels()*b->Frames()*sizeof(t_sample); +} + +static int buffer_segcount(PyObject *obj, int *lenp) +{ + flext::buffer *b = ((pySamplebuffer *)obj)->buf; + if(lenp) lenp[0] = b->Channels()*b->Frames()*sizeof(t_sample); + return 1; +} + +static int buffer_charbuffer(PyObject *obj, int segment, const char **ptrptr) +{ + flext::buffer *b = ((pySamplebuffer *)obj)->buf; + ptrptr[0] = (char *)b->Data(); + return b->Channels()*b->Frames()*sizeof(t_sample); +} + +static PyBufferProcs bufferprocs = { + buffer_readbuffer, + buffer_writebuffer, + buffer_segcount, + buffer_charbuffer +}; + +PyTypeObject pySamplebuffer_Type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "Buffer", /*tp_name*/ + sizeof(pySamplebuffer), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + buffer_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + buffer_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + buffer_hash, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + &bufferprocs, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ + "Samplebuffer objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0 /*buffer_richcompare*/, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + buffer_methods, /* tp_methods */ + 0, /* tp_members */ + buffer_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + buffer_init, /* tp_init */ + 0, /* tp_alloc */ + buffer_new, /* tp_new */ +}; + +void initsamplebuffer() +{ +#ifdef PY_NUMARRAY + import_libnumarray(); + if(PyErr_Occurred()) + // catch import error + PyErr_Clear(); + else { + // numarray support ok + nasupport = true; + post(""); + post("Numarray support enabled"); + } + + numtype = sizeof(t_sample) == 4?tFloat32:tFloat64; +#endif + + if(PyType_Ready(&pySamplebuffer_Type) < 0) + FLEXT_ASSERT(false); + else + Py_INCREF(&pySamplebuffer_Type); +} + -- cgit v1.2.1