diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2005-03-09 04:58:11 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2005-03-09 04:58:11 +0000 |
commit | e854889b99b9e515dc69d237b1031b5705e83b60 (patch) | |
tree | 6b525184d850f15012e316ca51cf0a11563261ea /externals/grill/py/source | |
parent | 9ccbbc943fa25426542b4fb6d6bc280c3281001b (diff) |
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
Diffstat (limited to 'externals/grill/py/source')
-rw-r--r-- | externals/grill/py/source/main.cpp | 25 | ||||
-rw-r--r-- | externals/grill/py/source/main.h | 7 | ||||
-rw-r--r-- | externals/grill/py/source/modmeth.cpp | 3 | ||||
-rw-r--r-- | externals/grill/py/source/py.cpp | 2 | ||||
-rw-r--r-- | externals/grill/py/source/pybuffer.cpp | 244 | ||||
-rw-r--r-- | externals/grill/py/source/pybuffer.h | 79 | ||||
-rw-r--r-- | externals/grill/py/source/pysymbol.h | 2 |
7 files changed, 349 insertions, 13 deletions
diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp index 01dc0afa..c24f998c 100644 --- a/externals/grill/py/source/main.cpp +++ b/externals/grill/py/source/main.cpp @@ -60,6 +60,7 @@ void py::FreeThreadState() void initsymbol(); +void initsamplebuffer(); void py::lib_setup() { @@ -69,12 +70,11 @@ void py::lib_setup() post("(C)2002-2005 Thomas Grill - http://grrrr.org/ext"); post(""); post("using Python %s",Py_GetVersion()); + #ifdef FLEXT_DEBUG post(""); post("DEBUG version compiled on %s %s",__DATE__,__TIME__); #endif - post("------------------------------------------------"); - post(""); // ------------------------------------------------------------- @@ -115,6 +115,10 @@ void py::lib_setup() PyModule_AddObject(module_obj,"_s_float",(PyObject *)pySymbol_float); 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; py_out = Py_InitModule("stdout", StdOut_Methods); @@ -138,6 +142,9 @@ void py::lib_setup() // release global lock PyEval_ReleaseLock(); #endif + + post("------------------------------------------------"); + post(""); } FLEXT_LIB_SETUP(py,py::lib_setup) @@ -189,12 +196,14 @@ void py::Exit() qucond.Signal(); 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()); + 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 flext_base::Exit(); diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h index 2d495461..7079dc2f 100644 --- a/externals/grill/py/source/main.h +++ b/externals/grill/py/source/main.h @@ -13,6 +13,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "pyprefix.h" #include "pysymbol.h" +#include "pybuffer.h" #include <flcontainers.h> #if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX @@ -107,6 +108,12 @@ protected: static PyObject *py_setvalue(PyObject *,PyObject *args); #endif +#ifdef PY_NUMARRAY + static void setupNumarray(); + static PyObject *py_import(PyObject *,PyObject *args); + static PyObject *py_export(PyObject *,PyObject *args); +#endif + // ----thread stuff ------------ virtual void m_stop(int argc,const t_atom *argv); diff --git a/externals/grill/py/source/modmeth.cpp b/externals/grill/py/source/modmeth.cpp index 70eb536a..4054d3ce 100644 --- a/externals/grill/py/source/modmeth.cpp +++ b/externals/grill/py/source/modmeth.cpp @@ -26,7 +26,6 @@ PyMethodDef py::func_tbl[] = { "_getvalue", py::py_getvalue, METH_VARARGS,"Get value of a 'value' object" }, { "_setvalue", py::py_setvalue, METH_VARARGS,"Set value of a 'value' object" }, #endif - {NULL, NULL, 0, NULL} // sentinel }; @@ -221,5 +220,3 @@ PyObject *py::py_setvalue(PyObject *self,PyObject *args) return Py_None; } #endif - - diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp index 68f805b8..3856739e 100644 --- a/externals/grill/py/source/py.cpp +++ b/externals/grill/py/source/py.cpp @@ -331,7 +331,7 @@ void pyobj::callwork(const t_symbol *s,int argc,const t_atom *argv) else post("%s: no valid function defined",thisName()); } - else { + else if(module) { // no function defined as creation argument -> use message tag PyObject *func = PyObject_GetAttrString(module,const_cast<char *>(GetString(s))); if(func) { 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 <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);
+}
+
diff --git a/externals/grill/py/source/pybuffer.h b/externals/grill/py/source/pybuffer.h new file mode 100644 index 00000000..1d59dd95 --- /dev/null +++ b/externals/grill/py/source/pybuffer.h @@ -0,0 +1,79 @@ +/*
+
+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
diff --git a/externals/grill/py/source/pysymbol.h b/externals/grill/py/source/pysymbol.h index c6e057d4..e711f424 100644 --- a/externals/grill/py/source/pysymbol.h +++ b/externals/grill/py/source/pysymbol.h @@ -63,7 +63,7 @@ inline PyObject *pySymbol_FromString(const char *str) inline PyObject *pySymbol_FromString(PyObject *str) { - return pySymbol_FromSymbol(flext::MakeSymbol(PyString_AsString(str))); + return pySymbol_FromString(PyString_AsString(str)); } inline const t_symbol *pySymbol_AS_SYMBOL(PyObject *op)
|