[PD-cvs] externals/grill/py/source pybuffer.cpp,NONE,1.1 pybuffer.h,NONE,1.1 main.cpp,1.27,1.28 main.h,1.34,1.35 modmeth.cpp,1.15,1.16 py.cpp,1.18,1.19 pysymbol.h,1.2,1.3

Thomas Grill xovo at users.sourceforge.net
Wed Mar 9 05:58:14 CET 2005


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 at 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 at 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





More information about the Pd-cvs mailing list