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(a)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(a)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