Update of /cvsroot/pure-data/externals/grill/py/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19856/source
Modified Files: main.cpp main.h modmeth.cpp py.cpp pysymbol.h Added Files: pybuffer.cpp pybuffer.h Log Message: 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
--- NEW FILE: pybuffer.cpp --- /*
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 <numarray/numarray.h> 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("<Samplebuffer %s>",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); }
Index: main.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/main.cpp,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** main.cpp 8 Mar 2005 04:59:25 -0000 1.27 --- main.cpp 9 Mar 2005 04:58:11 -0000 1.28 *************** *** 61,64 **** --- 61,65 ----
void initsymbol(); + void initsamplebuffer();
void py::lib_setup() *************** *** 70,79 **** post(""); post("using Python %s",Py_GetVersion()); #ifdef FLEXT_DEBUG post(""); post("DEBUG version compiled on %s %s",__DATE__,__TIME__); #endif - post("------------------------------------------------"); - post("");
// ------------------------------------------------------------- --- 71,79 ---- post(""); post("using Python %s",Py_GetVersion()); + #ifdef FLEXT_DEBUG post(""); post("DEBUG version compiled on %s %s",__DATE__,__TIME__); #endif
// ------------------------------------------------------------- *************** *** 116,119 **** --- 116,123 ---- PyModule_AddObject(module_obj,"_s_int",(PyObject *)pySymbol_int);
+ // add samplebuffer type + initsamplebuffer(); + PyModule_AddObject(module_obj,"Buffer",(PyObject *)&pySamplebuffer_Type); + // redirect stdout PyObject* py_out; *************** *** 139,142 **** --- 143,149 ---- PyEval_ReleaseLock(); #endif + + post("------------------------------------------------"); + post(""); }
*************** *** 190,199 **** if(thrcount) { // Wait for a certain time ! for(int i = 0; i < (PY_STOP_WAIT/PY_STOP_TICK) && thrcount; ++i) Sleep(PY_STOP_TICK/1000.f); ! ! // Wait forever ! post("%s - Waiting for thread termination!",thisName()); ! while(thrcount) Sleep(PY_STOP_TICK/1000.f); ! post("%s - Okay, all threads have terminated",thisName()); } #endif --- 197,208 ---- if(thrcount) { // Wait for a certain time ! for(int i = 0; i < (PY_STOP_WAIT/PY_STOP_TICK) && thrcount; ++i) ! Sleep(PY_STOP_TICK*0.001f); ! if(thrcount) { ! // Wait forever ! post("%s - Waiting for thread termination!",thisName()); ! while(thrcount) Sleep(PY_STOP_TICK*0.001f); ! post("%s - Okay, all threads have terminated",thisName()); ! } } #endif
Index: main.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/main.h,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** main.h 8 Mar 2005 04:59:25 -0000 1.34 --- main.h 9 Mar 2005 04:58:11 -0000 1.35 *************** *** 14,17 **** --- 14,18 ---- #include "pyprefix.h" #include "pysymbol.h" + #include "pybuffer.h" #include <flcontainers.h>
*************** *** 108,111 **** --- 109,118 ---- #endif
+ #ifdef PY_NUMARRAY + static void setupNumarray(); + static PyObject *py_import(PyObject *,PyObject *args); + static PyObject *py_export(PyObject *,PyObject *args); + #endif + // ----thread stuff ------------
Index: modmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/modmeth.cpp,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** modmeth.cpp 8 Mar 2005 04:59:25 -0000 1.15 --- modmeth.cpp 9 Mar 2005 04:58:11 -0000 1.16 *************** *** 27,31 **** { "_setvalue", py::py_setvalue, METH_VARARGS,"Set value of a 'value' object" }, #endif - {NULL, NULL, 0, NULL} // sentinel }; --- 27,30 ---- *************** *** 222,225 **** } #endif - - --- 221,222 ----
Index: py.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/py.cpp,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** py.cpp 11 Jan 2005 04:59:27 -0000 1.18 --- py.cpp 9 Mar 2005 04:58:11 -0000 1.19 *************** *** 332,336 **** post("%s: no valid function defined",thisName()); } ! else { // no function defined as creation argument -> use message tag PyObject *func = PyObject_GetAttrString(module,const_cast<char *>(GetString(s))); --- 332,336 ---- post("%s: no valid function defined",thisName()); } ! else if(module) { // no function defined as creation argument -> use message tag PyObject *func = PyObject_GetAttrString(module,const_cast<char *>(GetString(s)));
Index: pysymbol.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pysymbol.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pysymbol.h 19 Jan 2005 04:58:36 -0000 1.2 --- pysymbol.h 9 Mar 2005 04:58:11 -0000 1.3 *************** *** 64,68 **** inline PyObject *pySymbol_FromString(PyObject *str) { ! return pySymbol_FromSymbol(flext::MakeSymbol(PyString_AsString(str))); }
--- 64,68 ---- inline PyObject *pySymbol_FromString(PyObject *str) { ! return pySymbol_FromString(PyString_AsString(str)); }
--- NEW FILE: pybuffer.h --- /*
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.
*/
#ifndef __PYBUFFER_H #define __PYBUFFER_H
#include <flext.h>
#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) #error You need at least flext version 0.5.0 #endif
#if FLEXT_OS == FLEXT_OS_MAC #include <Python/Python.h> #else #include <Python.h> #endif
#ifdef _MSC_VER #ifdef PY_EXPORTS #define PY_EXPORT __declspec(dllexport) #else #define PY_EXPORT __declspec(dllimport) #endif #else #define PY_EXPORT #endif
typedef struct { PyObject_HEAD /* Type-specific fields go here. */ const t_symbol *sym; flext::buffer *buf; flext::buffer::lock_t lock; bool dirty; } pySamplebuffer;
PY_EXPORT extern PyTypeObject pySamplebuffer_Type;
#define pySamplebuffer_Check(op) PyObject_TypeCheck(op, &pySamplebuffer_Type) #define pySamplebuffer_CheckExact(op) ((op)->ob_type == &PySamplebuffer_Type)
PY_EXPORT PyObject *pySamplebuffer_FromSymbol(const t_symbol *sym);
inline PyObject *pySamplebuffer_FromString(const char *str) { return pySamplebuffer_FromSymbol(flext::MakeSymbol(str)); }
inline PyObject *pySamplebuffer_FromString(PyObject *str) { return pySamplebuffer_FromString(PyString_AsString(str)); }
inline const t_symbol *pySamplebuffer_AS_SYMBOL(PyObject *op) { return ((pySamplebuffer *)op)->sym; }
inline const t_symbol *pySamplebuffer_AsSymbol(PyObject *op) { return pySamplebuffer_Check(op)?pySamplebuffer_AS_SYMBOL(op):NULL; }
inline const char *pySamplebuffer_AS_STRING(PyObject *op) { return flext::GetString(pySamplebuffer_AS_SYMBOL(op)); }
#endif