Update of /cvsroot/pure-data/externals/grill/py/source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18937/source
Modified Files: bound.cpp clmeth.cpp modmeth.cpp py.cpp pyatom.cpp pyatom.h pybase.cpp pybase.h pybundle.cpp pybundle.h pydsp.cpp pyext.cpp pyext.h pymeth.cpp pyprefix.h pysymbol.cpp pysymbol.h Log Message: multiply inlets for py (hot and cold inlets) small optimizations and fixes use PyGILState_*() functionality (enabled with PY_USE_GIL) updates for DSP processing __str__ method for pyext, to enable print self calls added message bundle functionality (pyext.Bundle class) enable compiled-only scripts (without .py) enable optimization of Python code in reease build let _inlets and _outlets default to 0 fix for numpy some ASSERTs for explicitly created pyext classes (should be runtime checks i guess) open editor for script under OS X fixing numpy initialization quirks enable symbol binding for all callables (not only functions and methods) _isthreaded is now a data member instead of a method fix for gcc4 added pyext._list and pyext._tuple to convert input lists to Python sequence objects enable module packages (module/__init__.py[co]), now also for Max python-like dotted module.function syntax cleaned up float vs. int pyext tags compiler flag to exclude DSP objects some optimizations and py reload fix more safety for calls where association python-pd has already been removed always run Python interpreter in the background
Index: clmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/clmeth.cpp,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** clmeth.cpp 12 Dec 2005 00:18:42 -0000 1.27 --- clmeth.cpp 7 Mar 2007 13:40:14 -0000 1.28 *************** *** 3,7 **** py/pyext - python external 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. --- 3,7 ---- py/pyext - python external object for PD and Max/MSP
! Copyright (c)2002-2007 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. *************** *** 44,48 ****
const char *pyext::pyext_doc = ! "py/pyext - python external object for PD and Max/MSP, (C)2002-2005 Thomas Grill\n" "\n" "This is the pyext base class. Available methods:\n" --- 44,48 ----
const char *pyext::pyext_doc = ! "py/pyext - python external object for PD and Max/MSP, (C)2002-2007 Thomas Grill\n" "\n" "This is the pyext base class. Available methods:\n"
Index: pyprefix.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyprefix.h,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** pyprefix.h 1 Aug 2005 11:58:01 -0000 1.5 --- pyprefix.h 7 Mar 2007 13:40:14 -0000 1.6 *************** *** 1,43 **** ! /* ! ! py/pyext - python script object for PD and MaxMSP ! ! 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 __PYPREFIX_H ! #define __PYPREFIX_H ! ! #define FLEXT_ATTRIBUTES 1 ! #include <flext.h> ! ! // hack: must include math.h before Python.h (at least on OSX) ! // otherwise some functions don't get defined ! #include <math.h> ! ! #if FLEXT_OS == FLEXT_OS_MAC ! #include <Python/Python.h> ! #else ! #include <Python.h> ! #endif ! ! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 501) ! #error You need at least flext version 0.5.1 ! #endif ! ! #if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX ! #include <unistd.h> ! #endif ! ! #if FLEXT_SYS == FLEXT_SYS_PD && (!defined (PD_MINOR_VERSION) || PD_MINOR_VERSION < 37) ! #error PD version >= 0.37 required, please upgrade! ! #endif ! ! #include <flcontainers.h> ! #include <string> ! ! ! #endif --- 1,43 ---- ! /* ! ! py/pyext - python script object for PD and MaxMSP ! ! 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 __PYPREFIX_H ! #define __PYPREFIX_H ! ! #define FLEXT_ATTRIBUTES 1 ! #include <flext.h> ! ! // hack: must include math.h before Python.h (at least on OSX) ! // otherwise some functions don't get defined ! #include <math.h> ! ! #if FLEXT_OS == FLEXT_OS_MAC ! #include <Python/Python.h> ! #else ! #include <Python.h> ! #endif ! ! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 501) ! #error You need at least flext version 0.5.1 ! #endif ! ! #if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX ! #include <unistd.h> ! #endif ! ! #if FLEXT_SYS == FLEXT_SYS_PD && (!defined (PD_MINOR_VERSION) || PD_MINOR_VERSION < 37) ! #error PD version >= 0.37 required, please upgrade! ! #endif ! ! #include <flcontainers.h> ! #include <string> ! ! ! #endif
Index: pyext.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.h,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -d -r1.30 -r1.31 *** pyext.h 12 Dec 2005 00:18:42 -0000 1.30 --- pyext.h 7 Mar 2007 13:40:14 -0000 1.31 *************** *** 115,119 **** static bool stcallpy(PyObject *fun,PyObject *args);
! PyThreadState *pythr;
private: --- 115,121 ---- static bool stcallpy(PyObject *fun,PyObject *args);
! #ifndef PY_USE_GIL ! ThrState pythr; ! #endif
private:
Index: modmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/modmeth.cpp,v retrieving revision 1.23 retrieving revision 1.24 diff -C2 -d -r1.23 -r1.24 *** modmeth.cpp 3 Aug 2006 16:33:37 -0000 1.23 --- modmeth.cpp 7 Mar 2007 13:40:14 -0000 1.24 *************** *** 3,7 **** py/pyext - python external object for PD and Max/MSP
! Copyright (c)2002-2006 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. --- 3,7 ---- py/pyext - python external object for PD and Max/MSP
! Copyright (c)2002-2007 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. *************** *** 36,40 ****
const char *pybase::py_doc = ! "py/pyext - python external object for PD and Max/MSP, (C)2002-2006 Thomas Grill\n" "\n" "This is the pyext module. Available function:\n" --- 36,40 ----
const char *pybase::py_doc = ! "py/pyext - python external object for PD and Max/MSP, (C)2002-2007 Thomas Grill\n" "\n" "This is the pyext module. Available function:\n"
Index: bound.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/bound.cpp,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** bound.cpp 21 Sep 2005 10:52:33 -0000 1.18 --- bound.cpp 7 Mar 2007 13:40:14 -0000 1.19 *************** *** 65,69 **** pyext *pyth = static_cast<pyext *>(th);
! PyThreadState *state = pyth->PyLock();
PyObject *args = MakePyArgs(sym,argc,argv); --- 65,69 ---- pyext *pyth = static_cast<pyext *>(th);
! ThrState state = pyth->PyLock();
PyObject *args = MakePyArgs(sym,argc,argv);
Index: pyext.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.cpp,v retrieving revision 1.46 retrieving revision 1.47 diff -C2 -d -r1.46 -r1.47 *** pyext.cpp 23 Mar 2006 01:42:05 -0000 1.46 --- pyext.cpp 7 Mar 2007 13:40:14 -0000 1.47 *************** *** 118,123 **** pyobj(NULL), inlets(-1),outlets(-1), ! siginlets(0),sigoutlets(0), ! pythr(NULL) { #ifdef FLEXT_THREADS --- 118,125 ---- pyobj(NULL), inlets(-1),outlets(-1), ! siginlets(0),sigoutlets(0) ! #ifndef PY_USE_GIL ! ,pythr(NULL) ! #endif { #ifdef FLEXT_THREADS *************** *** 142,146 **** bool dotted = strrchr(thisName(),'.') != NULL;
! PyThreadState *state = PyLockSys();
// init script module --- 144,148 ---- bool dotted = strrchr(thisName(),'.') != NULL;
! ThrState state = PyLockSys();
// init script module *************** *** 195,199 **** bool pyext::Init() { ! PyThreadState *state = PyLockSys();
if(methname) { --- 197,201 ---- bool pyext::Init() { ! ThrState state = PyLockSys();
if(methname) { *************** *** 222,226 **** pybase::Exit(); // exit threads
! PyThreadState *state = PyLockSys(); DoExit();
--- 224,228 ---- pybase::Exit(); // exit threads
! ThrState state = PyLockSys(); DoExit();
*************** *** 415,419 **** void pyext::m_get(const t_symbol *s) { ! PyThreadState *state = PyLockSys();
PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast<char *>(GetString(s))); /* fetch bound method */ --- 417,421 ---- void pyext::m_get(const t_symbol *s) { ! ThrState state = PyLockSys();
PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast<char *>(GetString(s))); /* fetch bound method */ *************** *** 438,442 **** void pyext::m_set(int argc,const t_atom *argv) { ! PyThreadState *state = PyLockSys();
if(argc < 2 || !IsString(argv[0])) --- 440,444 ---- void pyext::m_set(int argc,const t_atom *argv) { ! ThrState state = PyLockSys();
if(argc < 2 || !IsString(argv[0])) *************** *** 543,547 **** bool ret = false;
! PyThreadState *state = PyLock();
// should be enough... --- 545,549 ---- bool ret = false;
! ThrState state = PyLock();
// should be enough...
Index: pyatom.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyatom.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pyatom.h 8 Jul 2005 14:30:31 -0000 1.1 --- pyatom.h 7 Mar 2007 13:40:14 -0000 1.2 *************** *** 1,19 **** ! /* ! ! 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" ! ! class PyAtom ! { ! public: ! static size_t Register(PyObject *obj); ! static PyObject *Retrieve(size_t id); ! static void Collect(); ! }; --- 1,19 ---- ! /* ! ! 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" ! ! class PyAtom ! { ! public: ! static size_t Register(PyObject *obj); ! static PyObject *Retrieve(size_t id); ! static void Collect(); ! };
Index: pyatom.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyatom.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pyatom.cpp 8 Jul 2005 14:30:31 -0000 1.1 --- pyatom.cpp 7 Mar 2007 13:40:14 -0000 1.2 *************** *** 1,61 **** ! /* ! ! 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 "pyatom.h" ! #include <map> ! ! #define INTV 0.01 ! ! typedef std::map<size_t,PyObject *> ObjMap; ! ! static ObjMap objmap; ! static size_t collix = 0,curix = 0; ! static double last = 0; ! ! size_t PyAtom::Register(PyObject *obj) ! { ! Collect(); ! ! Py_INCREF(obj); ! objmap[++curix] = obj; ! ! #ifdef _DEBUG ! // post("REG %p (%i)\n",obj,objmap.size()); ! #endif ! return curix; ! } ! ! PyObject *PyAtom::Retrieve(size_t id) ! { ! ObjMap::iterator it = objmap.find(id); ! PyObject *ret = it == objmap.end()?NULL:it->second; ! Collect(); ! return ret; ! } ! ! void PyAtom::Collect() ! { ! for(;;) { ! ObjMap::iterator it = objmap.begin(); ! if(it == objmap.end() || it->first > collix) break; ! ! PyObject *obj = it->second; ! Py_DECREF(obj); ! objmap.erase(it); ! ! #ifdef _DEBUG ! // post("DEL %p\n",obj); ! #endif ! } ! ! // schedule next collect time ! double tm = flext::GetTime(); ! if(tm > last+INTV) last = tm,collix = curix; ! } --- 1,61 ---- ! /* ! ! 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 "pyatom.h" ! #include <map> ! ! #define INTV 0.01 ! ! typedef std::map<size_t,PyObject *> ObjMap; ! ! static ObjMap objmap; ! static size_t collix = 0,curix = 0; ! static double last = 0; ! ! size_t PyAtom::Register(PyObject *obj) ! { ! Collect(); ! ! Py_INCREF(obj); ! objmap[++curix] = obj; ! ! #ifdef _DEBUG ! // post("REG %p (%i)\n",obj,objmap.size()); ! #endif ! return curix; ! } ! ! PyObject *PyAtom::Retrieve(size_t id) ! { ! ObjMap::iterator it = objmap.find(id); ! PyObject *ret = it == objmap.end()?NULL:it->second; ! Collect(); ! return ret; ! } ! ! void PyAtom::Collect() ! { ! for(;;) { ! ObjMap::iterator it = objmap.begin(); ! if(it == objmap.end() || it->first > collix) break; ! ! PyObject *obj = it->second; ! Py_DECREF(obj); ! objmap.erase(it); ! ! #ifdef _DEBUG ! // post("DEL %p\n",obj); ! #endif ! } ! ! // schedule next collect time ! double tm = flext::GetTime(); ! if(tm > last+INTV) last = tm,collix = curix; ! }
Index: pybundle.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pybundle.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pybundle.h 12 Dec 2005 13:55:28 -0000 1.1 --- pybundle.h 7 Mar 2007 13:40:14 -0000 1.2 *************** *** 1,15 **** ! /* ! ! 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 __PYBUNDLE_H ! #define __PYBUNDLE_H ! #include <flext.h>
--- 1,15 ---- ! /* ! ! 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 __PYBUNDLE_H ! #define __PYBUNDLE_H ! #include <flext.h>
*************** *** 34,60 **** #define PY_EXPORT #endif ! ! typedef struct { ! PyObject_HEAD ! /* Type-specific fields go here. */ ! flext::MsgBundle *bundle; ! } pyBundle; ! ! PY_EXPORT extern PyTypeObject pyBundle_Type; ! #define pyBundle_Check(op) PyObject_TypeCheck(op, &pyBundle_Type) #define pyBundle_CheckExact(op) ((op)->ob_type == &pyBundle_Type)
! inline flext::MsgBundle *pyBundle_AS_BUNDLE(PyObject *op) ! { ! return ((pyBundle *)op)->bundle; ! } ! ! inline flext::MsgBundle *pyBundle_AsBundle(PyObject *op) ! { ! return pyBundle_Check(op)?pyBundle_AS_BUNDLE(op):NULL; ! } !
! #endif --- 34,60 ---- #define PY_EXPORT #endif ! ! typedef struct { ! PyObject_HEAD ! /* Type-specific fields go here. */ ! flext::MsgBundle *bundle; ! } pyBundle; ! ! PY_EXPORT extern PyTypeObject pyBundle_Type; ! #define pyBundle_Check(op) PyObject_TypeCheck(op, &pyBundle_Type) #define pyBundle_CheckExact(op) ((op)->ob_type == &pyBundle_Type)
! inline flext::MsgBundle *pyBundle_AS_BUNDLE(PyObject *op) ! { ! return ((pyBundle *)op)->bundle; ! }
! inline flext::MsgBundle *pyBundle_AsBundle(PyObject *op) ! { ! return pyBundle_Check(op)?pyBundle_AS_BUNDLE(op):NULL; ! } ! ! ! #endif
Index: pysymbol.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pysymbol.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pysymbol.cpp 20 Jan 2007 14:27:22 -0000 1.6 --- pysymbol.cpp 7 Mar 2007 13:40:14 -0000 1.7 *************** *** 1,254 **** ! /* ! ! 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 "pyprefix.h" ! #include "pysymbol.h" ! ! inline pySymbol *symbol_newsym(const t_symbol *sym) ! { ! pySymbol *self = (pySymbol *)pySymbol_Type.tp_alloc(&pySymbol_Type, 0); ! if(self) self->sym = sym; ! return self; ! } ! ! static PyObject *symbol_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ! { ! return (PyObject *)symbol_newsym(flext::sym__); ! } ! ! static int symbol_init(PyObject *self, PyObject *args, PyObject *kwds) ! { ! FLEXT_ASSERT(pySymbol_Check(self)); ! ! PyObject *arg = PySequence_GetItem(args,0); // new reference ! if(!arg) return -1; ! ! int ret = 0; ! ! if(pySymbol_Check(arg)) ! ((pySymbol *)self)->sym = pySymbol_AS_SYMBOL(arg); ! else if(PyString_Check(arg)) ! ((pySymbol *)self)->sym = flext::MakeSymbol(PyString_AS_STRING(arg)); ! else { ! PyErr_SetString(PyExc_TypeError,"string or symbol argument expected"); ! ret = -1; ! } ! Py_DECREF(arg); ! ! return ret; ! } ! ! static PyObject *symbol_str(PyObject *self) ! { ! FLEXT_ASSERT(pySymbol_Check(self)); ! return (PyObject *)PyString_FromString(pySymbol_AS_STRING(self)); ! } ! ! static PyObject *symbol_repr(PyObject *self) ! { ! FLEXT_ASSERT(pySymbol_Check(self)); ! return (PyObject *)PyString_FromFormat("<Symbol %s>",pySymbol_AS_STRING(self)); ! } ! ! static PyObject *symbol_richcompare(PyObject *a,PyObject *b,int cmp) ! { ! if(pySymbol_Check(a) && pySymbol_Check(b)) { ! const t_symbol *asym = pySymbol_AS_SYMBOL(a); ! const t_symbol *bsym = pySymbol_AS_SYMBOL(b); ! bool ret; ! switch(cmp) { ! case Py_LT: ret = asym < bsym; break; ! case Py_LE: ret = asym <= bsym; break; ! case Py_EQ: ret = asym == bsym; break; ! case Py_NE: ret = asym != bsym; break; ! case Py_GT: ret = asym > bsym; break; ! case Py_GE: ret = asym >= bsym; break; ! } ! return PyBool_FromLong(ret); ! } ! Py_INCREF(Py_NotImplemented); ! return Py_NotImplemented; ! } ! ! static long symbol_hash(PyObject *self) ! { ! FLEXT_ASSERT(pySymbol_Check(self)); ! return (long)pySymbol_AS_SYMBOL(self); ! } ! ! ! static int symbol_length(pySymbol *self) ! { ! return strlen(flext::GetString(self->sym)); ! } ! ! static PyObject *symbol_item(pySymbol *self, int i) ! { ! const char *str = flext::GetString(self->sym); ! int len = strlen(str); ! if(i < 0) i += len; ! ! if(i >= 0 && i < len) ! return PyString_FromStringAndSize(str+i,1); ! else { ! Py_INCREF(Py_None); ! return Py_None; ! } ! } ! ! static PyObject *symbol_slice(pySymbol *self,int ilow = 0,int ihigh = 1<<(sizeof(int)*8-2)) ! { ! const char *str = flext::GetString(self->sym); ! int len = strlen(str); ! if(ilow < 0) { ! ilow += len; ! if(ilow < 0) ilow = 0; ! } ! if(ihigh < 0) ihigh += len; ! if(ihigh >= len) ihigh = len-1; ! ! return PyString_FromStringAndSize(str+ilow,ilow <= ihigh?ihigh-ilow+1:0); ! } ! ! static PyObject *symbol_concat(pySymbol *self,PyObject *op) ! { ! PyObject *nobj = symbol_slice(self); // take all ! if(nobj) { ! PyObject *ret = PySequence_Concat(nobj,op); ! Py_DECREF(nobj); ! return ret; ! } ! else ! return NULL; ! } ! ! static PyObject *symbol_repeat(pySymbol *self,int rep) ! { ! PyObject *nobj = symbol_slice(self); // take all ! if(nobj) { ! PyObject *ret = PySequence_Repeat(nobj,rep); ! Py_DECREF(nobj); ! return ret; ! } ! else ! return NULL; ! } ! ! static PySequenceMethods symbol_as_seq = { ! (inquiry)symbol_length, /* inquiry sq_length; __len__ */ ! (binaryfunc)symbol_concat, /* __add__ */ ! (intargfunc)symbol_repeat, /* __mul__ */ ! (intargfunc)symbol_item, /* intargfunc sq_item; __getitem__ */ ! (intintargfunc)symbol_slice, /* intintargfunc sq_slice; __getslice__ */ ! NULL, /* intobjargproc sq_ass_item; __setitem__ */ ! NULL, /* intintobjargproc sq_ass_slice; __setslice__ */ ! }; ! ! static PyObject *symbol_iter(PyObject *obj) ! { ! pySymbol *self = (pySymbol *)obj; ! PyObject *nobj = symbol_slice(self); ! if(nobj) { ! PyObject *it = PyObject_GetIter(nobj); ! Py_DECREF(nobj); ! return it; ! } ! else ! return NULL; ! } ! ! ! ! PyTypeObject pySymbol_Type = { ! PyObject_HEAD_INIT(NULL) ! 0, /*ob_size*/ ! "Symbol", /*tp_name*/ ! sizeof(pySymbol), /*tp_basicsize*/ ! 0, /*tp_itemsize*/ ! 0, /*tp_dealloc*/ ! 0, /*tp_print*/ ! 0, /*tp_getattr*/ ! 0, /*tp_setattr*/ ! 0, /*tp_compare*/ ! symbol_repr, /*tp_repr*/ ! 0, /*tp_as_number*/ ! &symbol_as_seq, /*tp_as_sequence*/ ! 0, /*tp_as_mapping*/ ! symbol_hash, /*tp_hash */ ! 0, /*tp_call*/ ! symbol_str, /*tp_str*/ ! 0, /*tp_getattro*/ ! 0, /*tp_setattro*/ ! 0, /*tp_as_buffer*/ ! Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ ! "Symbol objects", /* tp_doc */ ! 0, /* tp_traverse */ ! 0, /* tp_clear */ ! symbol_richcompare, /* tp_richcompare */ ! 0, /* tp_weaklistoffset */ ! symbol_iter, /* tp_iter */ ! 0, /* tp_iternext */ ! 0, /* tp_methods */ ! 0, /* tp_members */ ! 0, /* tp_getset */ ! 0, /* tp_base */ ! 0, /* tp_dict */ ! 0, /* tp_descr_get */ ! 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! symbol_init, /* tp_init */ ! 0, /* tp_alloc */ ! symbol_new, /* tp_new */ ! }; ! ! pySymbol *pySymbol__; ! pySymbol *pySymbol_bang; ! pySymbol *pySymbol_list; ! pySymbol *pySymbol_symbol; ! pySymbol *pySymbol_float; ! pySymbol *pySymbol_int; ! ! ! void initsymbol() ! { ! if(PyType_Ready(&pySymbol_Type) < 0) ! return; ! ! Py_INCREF(&pySymbol_Type); ! ! // initialize predefined objects ! pySymbol__ = symbol_newsym(flext::sym__); ! pySymbol_bang = symbol_newsym(flext::sym_bang); ! pySymbol_list = symbol_newsym(flext::sym_list); ! pySymbol_symbol = symbol_newsym(flext::sym_symbol); ! pySymbol_float = symbol_newsym(flext::sym_float); ! pySymbol_int = symbol_newsym(flext::sym_int); ! } ! ! ! PyObject *pySymbol_FromSymbol(const t_symbol *sym) ! { ! pySymbol *op; ! if(sym == flext::sym__) ! Py_INCREF(op = pySymbol__); ! else if(sym == flext::sym_bang) ! Py_INCREF(op = pySymbol_bang); ! else if(sym == flext::sym_list) ! Py_INCREF(op = pySymbol_list); ! else if(sym == flext::sym_symbol) ! Py_INCREF(op = pySymbol_symbol); ! else if(sym == flext::sym_float) ! Py_INCREF(op = pySymbol_float); ! else if(sym == flext::sym_int) ! Py_INCREF(op = pySymbol_int); ! else ! op = symbol_newsym(sym); ! return (PyObject *)op; ! } --- 1,254 ---- ! /* ! ! 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 "pyprefix.h" ! #include "pysymbol.h" ! ! inline pySymbol *symbol_newsym(const t_symbol *sym) ! { ! pySymbol *self = (pySymbol *)pySymbol_Type.tp_alloc(&pySymbol_Type, 0); ! if(self) self->sym = sym; ! return self; ! } ! ! static PyObject *symbol_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ! { ! return (PyObject *)symbol_newsym(flext::sym__); ! } ! ! static int symbol_init(PyObject *self, PyObject *args, PyObject *kwds) ! { ! FLEXT_ASSERT(pySymbol_Check(self)); ! ! PyObject *arg = PySequence_GetItem(args,0); // new reference ! if(!arg) return -1; ! ! int ret = 0; ! ! if(pySymbol_Check(arg)) ! ((pySymbol *)self)->sym = pySymbol_AS_SYMBOL(arg); ! else if(PyString_Check(arg)) ! ((pySymbol *)self)->sym = flext::MakeSymbol(PyString_AS_STRING(arg)); ! else { ! PyErr_SetString(PyExc_TypeError,"string or symbol argument expected"); ! ret = -1; ! } ! Py_DECREF(arg); ! ! return ret; ! } ! ! static PyObject *symbol_str(PyObject *self) ! { ! FLEXT_ASSERT(pySymbol_Check(self)); ! return (PyObject *)PyString_FromString(pySymbol_AS_STRING(self)); ! } ! ! static PyObject *symbol_repr(PyObject *self) ! { ! FLEXT_ASSERT(pySymbol_Check(self)); ! return (PyObject *)PyString_FromFormat("<Symbol %s>",pySymbol_AS_STRING(self)); ! } ! ! static PyObject *symbol_richcompare(PyObject *a,PyObject *b,int cmp) ! { ! if(pySymbol_Check(a) && pySymbol_Check(b)) { ! const t_symbol *asym = pySymbol_AS_SYMBOL(a); ! const t_symbol *bsym = pySymbol_AS_SYMBOL(b); ! bool ret; ! switch(cmp) { ! case Py_LT: ret = asym < bsym; break; ! case Py_LE: ret = asym <= bsym; break; ! case Py_EQ: ret = asym == bsym; break; ! case Py_NE: ret = asym != bsym; break; ! case Py_GT: ret = asym > bsym; break; ! case Py_GE: ret = asym >= bsym; break; ! } ! return PyBool_FromLong(ret); ! } ! Py_INCREF(Py_NotImplemented); ! return Py_NotImplemented; ! } ! ! static long symbol_hash(PyObject *self) ! { ! FLEXT_ASSERT(pySymbol_Check(self)); ! return (long)pySymbol_AS_SYMBOL(self); ! } ! ! ! static int symbol_length(pySymbol *self) ! { ! return strlen(flext::GetString(self->sym)); ! } ! ! static PyObject *symbol_item(pySymbol *self, int i) ! { ! const char *str = flext::GetString(self->sym); ! int len = strlen(str); ! if(i < 0) i += len; ! ! if(i >= 0 && i < len) ! return PyString_FromStringAndSize(str+i,1); ! else { ! Py_INCREF(Py_None); ! return Py_None; ! } ! } ! ! static PyObject *symbol_slice(pySymbol *self,int ilow = 0,int ihigh = 1<<(sizeof(int)*8-2)) ! { ! const char *str = flext::GetString(self->sym); ! int len = strlen(str); ! if(ilow < 0) { ! ilow += len; ! if(ilow < 0) ilow = 0; ! } ! if(ihigh < 0) ihigh += len; ! if(ihigh >= len) ihigh = len-1; ! ! return PyString_FromStringAndSize(str+ilow,ilow <= ihigh?ihigh-ilow+1:0); ! } ! ! static PyObject *symbol_concat(pySymbol *self,PyObject *op) ! { ! PyObject *nobj = symbol_slice(self); // take all ! if(nobj) { ! PyObject *ret = PySequence_Concat(nobj,op); ! Py_DECREF(nobj); ! return ret; ! } ! else ! return NULL; ! } ! ! static PyObject *symbol_repeat(pySymbol *self,int rep) ! { ! PyObject *nobj = symbol_slice(self); // take all ! if(nobj) { ! PyObject *ret = PySequence_Repeat(nobj,rep); ! Py_DECREF(nobj); ! return ret; ! } ! else ! return NULL; ! } ! ! static PySequenceMethods symbol_as_seq = { ! (inquiry)symbol_length, /* inquiry sq_length; __len__ */ ! (binaryfunc)symbol_concat, /* __add__ */ ! (intargfunc)symbol_repeat, /* __mul__ */ ! (intargfunc)symbol_item, /* intargfunc sq_item; __getitem__ */ ! (intintargfunc)symbol_slice, /* intintargfunc sq_slice; __getslice__ */ ! NULL, /* intobjargproc sq_ass_item; __setitem__ */ ! NULL, /* intintobjargproc sq_ass_slice; __setslice__ */ ! }; ! ! static PyObject *symbol_iter(PyObject *obj) ! { ! pySymbol *self = (pySymbol *)obj; ! PyObject *nobj = symbol_slice(self); ! if(nobj) { ! PyObject *it = PyObject_GetIter(nobj); ! Py_DECREF(nobj); ! return it; ! } ! else ! return NULL; ! } ! ! ! ! PyTypeObject pySymbol_Type = { ! PyObject_HEAD_INIT(NULL) ! 0, /*ob_size*/ ! "Symbol", /*tp_name*/ ! sizeof(pySymbol), /*tp_basicsize*/ ! 0, /*tp_itemsize*/ ! 0, /*tp_dealloc*/ ! 0, /*tp_print*/ ! 0, /*tp_getattr*/ ! 0, /*tp_setattr*/ ! 0, /*tp_compare*/ ! symbol_repr, /*tp_repr*/ ! 0, /*tp_as_number*/ ! &symbol_as_seq, /*tp_as_sequence*/ ! 0, /*tp_as_mapping*/ ! symbol_hash, /*tp_hash */ ! 0, /*tp_call*/ ! symbol_str, /*tp_str*/ ! 0, /*tp_getattro*/ ! 0, /*tp_setattro*/ ! 0, /*tp_as_buffer*/ ! Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ ! "Symbol objects", /* tp_doc */ ! 0, /* tp_traverse */ ! 0, /* tp_clear */ ! symbol_richcompare, /* tp_richcompare */ ! 0, /* tp_weaklistoffset */ ! symbol_iter, /* tp_iter */ ! 0, /* tp_iternext */ ! 0, /* tp_methods */ ! 0, /* tp_members */ ! 0, /* tp_getset */ ! 0, /* tp_base */ ! 0, /* tp_dict */ ! 0, /* tp_descr_get */ ! 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! symbol_init, /* tp_init */ ! 0, /* tp_alloc */ ! symbol_new, /* tp_new */ ! }; ! ! pySymbol *pySymbol__; ! pySymbol *pySymbol_bang; ! pySymbol *pySymbol_list; ! pySymbol *pySymbol_symbol; ! pySymbol *pySymbol_float; ! pySymbol *pySymbol_int; ! ! ! void initsymbol() ! { ! if(PyType_Ready(&pySymbol_Type) < 0) ! return; ! ! Py_INCREF(&pySymbol_Type); ! ! // initialize predefined objects ! pySymbol__ = symbol_newsym(flext::sym__); ! pySymbol_bang = symbol_newsym(flext::sym_bang); ! pySymbol_list = symbol_newsym(flext::sym_list); ! pySymbol_symbol = symbol_newsym(flext::sym_symbol); ! pySymbol_float = symbol_newsym(flext::sym_float); ! pySymbol_int = symbol_newsym(flext::sym_int); ! } ! ! ! PyObject *pySymbol_FromSymbol(const t_symbol *sym) ! { ! pySymbol *op; ! if(sym == flext::sym__) ! Py_INCREF(op = pySymbol__); ! else if(sym == flext::sym_bang) ! Py_INCREF(op = pySymbol_bang); ! else if(sym == flext::sym_list) ! Py_INCREF(op = pySymbol_list); ! else if(sym == flext::sym_symbol) ! Py_INCREF(op = pySymbol_symbol); ! else if(sym == flext::sym_float) ! Py_INCREF(op = pySymbol_float); ! else if(sym == flext::sym_int) ! Py_INCREF(op = pySymbol_int); ! else ! op = symbol_newsym(sym); ! return (PyObject *)op; ! }
Index: pydsp.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pydsp.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pydsp.cpp 20 Sep 2005 20:50:40 -0000 1.6 --- pydsp.cpp 7 Mar 2007 13:40:14 -0000 1.7 *************** *** 1,190 **** ! /* ! ! 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 PY_NODSP ! ! #include "pyext.h" ! ! class pydsp ! : public pyext ! { ! FLEXT_HEADER(pydsp,pyext) ! public: ! pydsp(int argc,const t_atom *argv); ! ! protected: ! virtual bool CbDsp(); ! virtual void CbSignal(); ! ! virtual bool DoInit(); ! virtual void DoExit(); ! ! virtual PyObject *GetSig(int ix,bool in); ! ! void NewBuffers(); ! void FreeBuffers(); ! ! PyObject *dspfun,*sigfun; ! PyObject **buffers; ! }; ! ! FLEXT_LIB_DSP_V("pyext~ pyext.~ pyx~ pyx.~",pydsp) ! ! pydsp::pydsp(int argc,const t_atom *argv) ! : pyext(argc,argv,true) ! , dspfun(NULL),sigfun(NULL) ! {} ! ! bool pydsp::DoInit() ! { ! if(!pyext::DoInit()) return false; ! ! if(pyobj) ! { ! dspfun = PyObject_GetAttrString(pyobj,"_dsp"); // get ref ! if(!dspfun) ! PyErr_Clear(); ! else if(!PyMethod_Check(dspfun)) { ! Py_DECREF(dspfun); ! dspfun = NULL; ! } ! } ! return true; ! } ! ! void pydsp::DoExit() ! { ! if(dspfun) { Py_DECREF(dspfun); dspfun = NULL; } ! if(sigfun) { Py_DECREF(sigfun); sigfun = NULL; } ! ! FreeBuffers(); ! } ! ! PyObject *arrayfrombuffer(PyObject *buf,int c,int n); ! ! void pydsp::NewBuffers() ! { ! int i,n = Blocksize(); ! const int ins = CntInSig(),outs = CntOutSig(); ! t_sample *const *insigs = InSig(); ! t_sample *const *outsigs = OutSig(); ! ! // inlet/outlet count can't change so we don't have to deallocate ! if(!buffers) { ! int cnt = ins+outs; ! buffers = new PyObject *[cnt]; ! memset(buffers,0,cnt*sizeof(*buffers)); ! } ! ! for(i = 0; i < ins; ++i) { ! Py_XDECREF(buffers[i]); ! PyObject *b = PyBuffer_FromReadWriteMemory(insigs[i],n*sizeof(t_sample)); ! buffers[i] = arrayfrombuffer(b,1,n); ! Py_DECREF(b); ! } ! for(i = 0; i < outs; ++i) { ! Py_XDECREF(buffers[ins+i]); ! if(i < ins && outsigs[i] == insigs[i]) { ! // same vectors - share the objects! ! buffers[ins+i] = buffers[i]; ! Py_XINCREF(buffers[i]); ! } ! else { ! PyObject *b = PyBuffer_FromReadWriteMemory(outsigs[i],n*sizeof(t_sample)); ! buffers[ins+i] = arrayfrombuffer(b,1,n); ! Py_DECREF(b); ! } ! } ! } ! ! void pydsp::FreeBuffers() ! { ! if(buffers) { ! int cnt = CntInSig()+CntOutSig(); ! for(int i = 0; i < cnt; ++i) Py_XDECREF(buffers[i]); ! delete[] buffers; ! buffers = NULL; ! } ! } ! ! bool pydsp::CbDsp() ! { ! if(pyobj && (CntInSig() || CntOutSig())) ! { ! PyThreadState *state = PyLockSys(); ! ! NewBuffers(); ! ! bool dodsp = true; ! if(dspfun) { ! PyObject *ret = PyObject_CallObject(dspfun,NULL); ! if(ret) { ! dodsp = PyObject_IsTrue(ret) != 0; ! Py_DECREF(ret); ! } ! else { ! #ifdef FLEXT_DEBUG ! PyErr_Print(); ! #else ! PyErr_Clear(); ! #endif ! } ! } ! ! // do that here instead of where dspfun is initialized, so that ! // _signal can be assigned in _dsp ! // optimizations may be done there to assign the right _signal version ! Py_XDECREF(sigfun); ! ! if(dodsp) { ! sigfun = PyObject_GetAttrString(pyobj,"_signal"); // get ref ! if(!sigfun) ! PyErr_Clear(); ! else if(!PyMethod_Check(sigfun)) { ! Py_DECREF(sigfun); ! sigfun = NULL; ! } ! } ! else ! sigfun = NULL; ! ! PyUnlock(state); ! return sigfun != NULL; ! } ! else ! // switch on dsp only if there are signal inlets or outlets ! return false; ! } ! ! void pydsp::CbSignal() ! { ! PyThreadState *state = PyLockSys(); ! PyObject *ret = PyObject_CallObject(sigfun,NULL); ! ! if(ret) ! Py_DECREF(ret); ! else { ! #ifdef FLEXT_DEBUG ! PyErr_Print(); ! #else ! PyErr_Clear(); ! #endif ! } ! PyUnlock(state); ! } ! ! PyObject *pydsp::GetSig(int ix,bool in) ! { ! PyObject *r = buffers[in?ix:CntInSig()+ix]; ! Py_XINCREF(r); ! return r; ! } ! ! #endif --- 1,190 ---- ! /* ! ! 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 PY_NODSP ! ! #include "pyext.h" ! ! class pydsp ! : public pyext ! { ! FLEXT_HEADER(pydsp,pyext) ! public: ! pydsp(int argc,const t_atom *argv); ! ! protected: ! virtual bool CbDsp(); ! virtual void CbSignal(); ! ! virtual bool DoInit(); ! virtual void DoExit(); ! ! virtual PyObject *GetSig(int ix,bool in); ! ! void NewBuffers(); ! void FreeBuffers(); ! ! PyObject *dspfun,*sigfun; ! PyObject **buffers; ! }; ! ! FLEXT_LIB_DSP_V("pyext~ pyext.~ pyx~ pyx.~",pydsp) ! ! pydsp::pydsp(int argc,const t_atom *argv) ! : pyext(argc,argv,true) ! , dspfun(NULL),sigfun(NULL) ! {} ! ! bool pydsp::DoInit() ! { ! if(!pyext::DoInit()) return false; ! ! if(pyobj) ! { ! dspfun = PyObject_GetAttrString(pyobj,"_dsp"); // get ref ! if(!dspfun) ! PyErr_Clear(); ! else if(!PyMethod_Check(dspfun)) { ! Py_DECREF(dspfun); ! dspfun = NULL; ! } ! } ! return true; ! } ! ! void pydsp::DoExit() ! { ! if(dspfun) { Py_DECREF(dspfun); dspfun = NULL; } ! if(sigfun) { Py_DECREF(sigfun); sigfun = NULL; } ! ! FreeBuffers(); ! } ! ! PyObject *arrayfrombuffer(PyObject *buf,int c,int n); ! ! void pydsp::NewBuffers() ! { ! int i,n = Blocksize(); ! const int ins = CntInSig(),outs = CntOutSig(); ! t_sample *const *insigs = InSig(); ! t_sample *const *outsigs = OutSig(); ! ! // inlet/outlet count can't change so we don't have to deallocate ! if(!buffers) { ! int cnt = ins+outs; ! buffers = new PyObject *[cnt]; ! memset(buffers,0,cnt*sizeof(*buffers)); ! } ! ! for(i = 0; i < ins; ++i) { ! Py_XDECREF(buffers[i]); ! PyObject *b = PyBuffer_FromReadWriteMemory(insigs[i],n*sizeof(t_sample)); ! buffers[i] = arrayfrombuffer(b,1,n); ! Py_DECREF(b); ! } ! for(i = 0; i < outs; ++i) { ! Py_XDECREF(buffers[ins+i]); ! if(i < ins && outsigs[i] == insigs[i]) { ! // same vectors - share the objects! ! buffers[ins+i] = buffers[i]; ! Py_XINCREF(buffers[i]); ! } ! else { ! PyObject *b = PyBuffer_FromReadWriteMemory(outsigs[i],n*sizeof(t_sample)); ! buffers[ins+i] = arrayfrombuffer(b,1,n); ! Py_DECREF(b); ! } ! } ! } ! ! void pydsp::FreeBuffers() ! { ! if(buffers) { ! int cnt = CntInSig()+CntOutSig(); ! for(int i = 0; i < cnt; ++i) Py_XDECREF(buffers[i]); ! delete[] buffers; ! buffers = NULL; ! } ! } ! ! bool pydsp::CbDsp() ! { ! if(pyobj && (CntInSig() || CntOutSig())) ! { ! ThrState state = PyLockSys(); ! ! NewBuffers(); ! ! bool dodsp = true; ! if(dspfun) { ! PyObject *ret = PyObject_CallObject(dspfun,NULL); ! if(ret) { ! dodsp = PyObject_IsTrue(ret) != 0; ! Py_DECREF(ret); ! } ! else { ! #ifdef FLEXT_DEBUG ! PyErr_Print(); ! #else ! PyErr_Clear(); ! #endif ! } ! } ! ! // do that here instead of where dspfun is initialized, so that ! // _signal can be assigned in _dsp ! // optimizations may be done there to assign the right _signal version ! Py_XDECREF(sigfun); ! ! if(dodsp) { ! sigfun = PyObject_GetAttrString(pyobj,"_signal"); // get ref ! if(!sigfun) ! PyErr_Clear(); ! else if(!PyMethod_Check(sigfun)) { ! Py_DECREF(sigfun); ! sigfun = NULL; ! } ! } ! else ! sigfun = NULL; ! ! PyUnlock(state); ! return sigfun != NULL; ! } ! else ! // switch on dsp only if there are signal inlets or outlets ! return false; ! } ! ! void pydsp::CbSignal() ! { ! ThrState state = PyLockSys(); ! PyObject *ret = PyObject_CallObject(sigfun,NULL); ! ! if(ret) ! Py_DECREF(ret); ! else { ! #ifdef FLEXT_DEBUG ! PyErr_Print(); ! #else ! PyErr_Clear(); ! #endif ! } ! PyUnlock(state); ! } ! ! PyObject *pydsp::GetSig(int ix,bool in) ! { ! PyObject *r = buffers[in?ix:CntInSig()+ix]; ! Py_XINCREF(r); ! return r; ! } ! ! #endif
Index: pymeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pymeth.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pymeth.cpp 11 Aug 2005 15:00:58 -0000 1.6 --- pymeth.cpp 7 Mar 2007 13:40:14 -0000 1.7 *************** *** 1,428 **** ! /* ! ! 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 "pybase.h" ! #include <map> ! ! struct xlt { const t_symbol *from,*to; }; ! ! static const xlt xtdefs[] = { ! { flext::MakeSymbol("+"),flext::MakeSymbol("__add__") }, ! { flext::MakeSymbol("+="),flext::MakeSymbol("__iadd__") }, ! { flext::MakeSymbol("!+"),flext::MakeSymbol("__radd__") }, ! { flext::MakeSymbol("-"),flext::MakeSymbol("__sub__") }, ! { flext::MakeSymbol("-="),flext::MakeSymbol("__isub__") }, ! { flext::MakeSymbol("!-"),flext::MakeSymbol("__rsub__") }, ! { flext::MakeSymbol("*"),flext::MakeSymbol("__mul__") }, ! { flext::MakeSymbol("*="),flext::MakeSymbol("__imul__") }, ! { flext::MakeSymbol("!*"),flext::MakeSymbol("__rmul__") }, ! { flext::MakeSymbol("/"),flext::MakeSymbol("__div__") }, ! { flext::MakeSymbol("/="),flext::MakeSymbol("__idiv__") }, ! { flext::MakeSymbol("!/"),flext::MakeSymbol("__rdiv__") }, ! { flext::MakeSymbol("//"),flext::MakeSymbol("__floordiv__") }, ! { flext::MakeSymbol("//="),flext::MakeSymbol("__ifloordiv__") }, ! { flext::MakeSymbol("!//"),flext::MakeSymbol("__rfloordiv__") }, ! { flext::MakeSymbol("%"),flext::MakeSymbol("__mod__") }, ! { flext::MakeSymbol("%="),flext::MakeSymbol("__imod__") }, ! { flext::MakeSymbol("!%"),flext::MakeSymbol("__rmod__") }, ! { flext::MakeSymbol("**"),flext::MakeSymbol("__pow__") }, ! { flext::MakeSymbol("**="),flext::MakeSymbol("__ipow__") }, ! { flext::MakeSymbol("!**"),flext::MakeSymbol("__rpow__") }, ! { flext::MakeSymbol("&"),flext::MakeSymbol("__and__") }, ! { flext::MakeSymbol("&="),flext::MakeSymbol("__iand__") }, ! { flext::MakeSymbol("!&"),flext::MakeSymbol("__rand__") }, ! { flext::MakeSymbol("|"),flext::MakeSymbol("__or__") }, ! { flext::MakeSymbol("|="),flext::MakeSymbol("__ior__") }, ! { flext::MakeSymbol("!|"),flext::MakeSymbol("__ror__") }, ! { flext::MakeSymbol("^"),flext::MakeSymbol("__xor__") }, ! { flext::MakeSymbol("^="),flext::MakeSymbol("__ixor__") }, ! { flext::MakeSymbol("!^"),flext::MakeSymbol("__rxor__") }, ! { flext::MakeSymbol("<<"),flext::MakeSymbol("__lshift__") }, ! { flext::MakeSymbol("<<="),flext::MakeSymbol("__ilshift__") }, ! { flext::MakeSymbol("!<<"),flext::MakeSymbol("__rlshift__") }, ! { flext::MakeSymbol(">>"),flext::MakeSymbol("__rshift__") }, ! { flext::MakeSymbol(">>="),flext::MakeSymbol("__irshift__") }, ! { flext::MakeSymbol("!>>"),flext::MakeSymbol("__rrshift__") }, ! { flext::MakeSymbol("=="),flext::MakeSymbol("__eq__") }, ! { flext::MakeSymbol("!="),flext::MakeSymbol("__ne__") }, ! { flext::MakeSymbol("<"),flext::MakeSymbol("__lt__") }, ! { flext::MakeSymbol(">"),flext::MakeSymbol("__gt__") }, ! { flext::MakeSymbol("<="),flext::MakeSymbol("__le__") }, ! { flext::MakeSymbol(">="),flext::MakeSymbol("__ge__") }, ! { flext::MakeSymbol("!"),flext::MakeSymbol("__nonzero__") }, ! { flext::MakeSymbol("~"),flext::MakeSymbol("__invert__") }, ! { flext::MakeSymbol("[]"),flext::MakeSymbol("__getitem__") }, ! { flext::MakeSymbol("[]="),flext::MakeSymbol("__setitem__") }, ! { flext::MakeSymbol("[:]"),flext::MakeSymbol("__getslice__") }, ! { flext::MakeSymbol("[:]="),flext::MakeSymbol("__setslice__") }, ! ! { flext::MakeSymbol(".abs"),flext::MakeSymbol("__abs__") }, ! { flext::MakeSymbol(".neg"),flext::MakeSymbol("__neg__") }, ! { flext::MakeSymbol(".pos"),flext::MakeSymbol("__pos__") }, ! { flext::MakeSymbol(".divmod"),flext::MakeSymbol("__divmod__") }, ! ! { flext::MakeSymbol(".int"),flext::MakeSymbol("__int__") }, ! { flext::MakeSymbol(".long"),flext::MakeSymbol("__long__") }, ! { flext::MakeSymbol(".float"),flext::MakeSymbol("__float__") }, ! { flext::MakeSymbol(".complex"),flext::MakeSymbol("__complex__") }, ! { flext::MakeSymbol(".str"),flext::MakeSymbol("__str__") }, ! { flext::MakeSymbol(".coerce"),flext::MakeSymbol("__coerce__") }, ! ! { flext::MakeSymbol(".doc"),flext::MakeSymbol("__doc__") }, ! { flext::MakeSymbol(".repr"),flext::MakeSymbol("__repr__") }, ! ! { flext::MakeSymbol(".len"),flext::MakeSymbol("__len__") }, ! { flext::MakeSymbol(".in"),flext::MakeSymbol("__contains") }, ! ! { NULL,NULL } // sentinel ! }; ! ! typedef std::map<const t_symbol *,const t_symbol *> XTable; ! static XTable xtable; ! ! ! class pymeth ! : public pybase ! , public flext_base ! { ! FLEXT_HEADER_S(pymeth,flext_base,Setup) ! ! public: ! pymeth(int argc,const t_atom *argv); ! ~pymeth(); ! ! protected: ! virtual void Exit(); ! ! virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv); ! ! void m_help(); ! ! void m_reload() { Reload(); } ! void m_reload_(int argc,const t_atom *argv) { args(argc,argv); Reload(); } ! void m_set(int argc,const t_atom *argv); ! void m_dir_() { m__dir(function); } ! void m_doc_() { m__doc(function); } ! ! const t_symbol *funname; ! PyObject *function; ! ! virtual void LoadModule(); ! virtual void UnloadModule(); ! ! virtual void Load(); ! virtual void Unload(); ! ! void SetFunction(const t_symbol *func); ! void ResetFunction(); ! ! virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv); ! ! PyObject **objects; ! ! private: ! ! virtual void callpy(PyObject *fun,PyObject *args); ! ! static void Setup(t_classid c); ! ! FLEXT_CALLBACK(m_help) ! FLEXT_CALLBACK(m_reload) ! FLEXT_CALLBACK_V(m_reload_) ! FLEXT_CALLBACK_V(m_set) ! FLEXT_CALLBACK(m_dir_) ! FLEXT_CALLBACK(m_doc_) ! ! // callbacks ! FLEXT_ATTRVAR_I(detach) ! FLEXT_ATTRVAR_B(pymsg) ! FLEXT_ATTRVAR_B(respond) ! ! FLEXT_CALLBACK_V(m_stop) ! FLEXT_CALLBACK(m_dir) ! FLEXT_CALLGET_V(mg_dir) ! FLEXT_CALLBACK(m_doc) ! ! #ifdef FLEXT_THREADS ! FLEXT_CALLBACK_T(tick) ! #endif ! }; ! ! FLEXT_LIB_V("pym",pymeth) ! ! ! void pymeth::Setup(t_classid c) ! { ! FLEXT_CADDMETHOD_(c,0,"doc",m_doc); ! FLEXT_CADDMETHOD_(c,0,"dir",m_dir); ! #ifdef FLEXT_THREADS ! FLEXT_CADDATTR_VAR1(c,"detach",detach); ! FLEXT_CADDMETHOD_(c,0,"stop",m_stop); ! #endif ! ! FLEXT_CADDMETHOD_(c,0,"help",m_help); ! FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); ! FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); ! FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_); ! FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_); ! ! FLEXT_CADDMETHOD_(c,0,"set",m_set); ! ! FLEXT_CADDATTR_VAR1(c,"py",pymsg); ! FLEXT_CADDATTR_VAR1(c,"respond",respond); ! ! // init translation map ! for(const xlt *xi = xtdefs; xi->from; ++xi) xtable[xi->from] = xi->to; ! } ! ! pymeth::pymeth(int argc,const t_atom *argv) ! : funname(NULL) ! , function(NULL) ! , objects(NULL) ! { ! #ifdef FLEXT_THREADS ! FLEXT_ADDTIMER(stoptmr,tick); ! #endif ! ! PyThreadState *state = PyLockSys(); ! ! int inlets; ! if(argc && CanbeInt(*argv)) { ! inlets = GetAInt(*argv); ! if(inlets < 1) inlets = 1; ! argv++,argc--; ! } ! else inlets = 1; ! ! objects = new PyObject *[inlets]; ! for(int i = 0; i < inlets; ++i) { objects[i] = Py_None; Py_INCREF(Py_None); } ! ! if(inlets <= 0) InitProblem(); ! ! AddInAnything(1+(inlets < 0?1:inlets)); ! AddOutAnything(); ! ! Register(GetRegistry(REGNAME)); ! ! if(argc) { ! const t_symbol *funnm = GetASymbol(*argv); ! argv++,argc--; ! ! if(funnm) ! SetFunction(funnm); ! else ! PyErr_SetString(PyExc_ValueError,"Invalid function name"); ! } ! ! if(argc) args(argc,argv); ! ! Report(); ! ! PyUnlock(state); ! } ! ! pymeth::~pymeth() ! { ! if(objects) { ! for(int i = 0; i < CntIn()-1; ++i) Py_DECREF(objects[i]); ! delete[] objects; ! } ! ! PyThreadState *state = PyLockSys(); ! Unregister(GetRegistry(REGNAME)); ! Report(); ! PyUnlock(state); ! } ! ! void pymeth::Exit() ! { ! pybase::Exit(); ! flext_base::Exit(); ! } ! ! void pymeth::m_set(int argc,const t_atom *argv) ! { ! PyThreadState *state = PyLockSys(); ! ! // function name has precedence ! if(argc >= 2) { ! const char *sn = GetAString(*argv); ! ++argv,--argc; ! ! if(sn) { ! if(!module || !strcmp(sn,PyModule_GetName(module))) { ! ImportModule(sn); ! Register(GetRegistry(REGNAME)); ! } ! } ! else ! PyErr_SetString(PyExc_ValueError,"Invalid module name"); ! } ! ! if(argc) { ! const t_symbol *fn = GetASymbol(*argv); ! if(fn) ! SetFunction(fn); ! else ! PyErr_SetString(PyExc_ValueError,"Invalid function name"); ! } ! ! Report(); ! ! PyUnlock(state); ! } ! ! void pymeth::m_help() ! { ! post(""); ! post("%s %s - python method object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION); ! #ifdef FLEXT_DEBUG ! post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__); ! #endif ! ! post("Arguments: %s [method name] {args...}",thisName()); ! ! post("Inlet 1:messages to control the py object"); ! post(" 2:call python function with message as argument(s)"); ! post("Outlet: 1:return values from python function"); ! post("Methods:"); ! post("\thelp: shows this help"); ! post("\tbang: call script without arguments"); ! post("\tset [script name] [function name]: set (script and) function name"); ! post("\treload {args...}: reload python script"); ! post("\treload. : reload with former arguments"); ! post("\tdoc: display module doc string"); ! post("\tdoc+: display function doc string"); ! post("\tdir: dump module dictionary"); ! post("\tdir+: dump function dictionary"); ! #ifdef FLEXT_THREADS ! post("\tdetach 0/1/2: detach threads"); ! post("\tstop {wait time (ms)}: stop threads"); ! #endif ! post(""); ! } ! ! void pymeth::ResetFunction() ! { ! Py_XDECREF(function); ! function = NULL; ! ! if(funname && objects[0] != Py_None) { ! function = PyObject_GetAttrString(objects[0],(char *)GetString(funname)); // new reference ! if(!function) ! PyErr_SetString(PyExc_AttributeError,"Method not found"); ! } ! ! // exception could be set here ! } ! ! void pymeth::SetFunction(const t_symbol *func) ! { ! // look for method name in translation table ! XTable::iterator it = xtable.find(func); ! funname = it == xtable.end()?func:it->second; ! ! ResetFunction(); ! } ! ! ! void pymeth::LoadModule() ! { ! SetFunction(funname); ! } ! ! void pymeth::UnloadModule() ! { ! } ! ! void pymeth::Load() ! { ! ResetFunction(); ! } ! ! void pymeth::Unload() ! { ! SetFunction(NULL); ! } ! ! void pymeth::callpy(PyObject *fun,PyObject *args) ! { ! PyObject *ret = PyObject_CallObject(fun,args); ! if(ret) { ! OutObject(this,0,ret); // exception might be raised here ! Py_DECREF(ret); ! } ! } ! ! bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) ! { ! if(n == 0 && s != sym_bang) ! return flext_base::CbMethodResort(n,s,argc,argv); ! ! PyThreadState *state = PyLockSys(); ! ! bool ret = false; ! ! if(n >= 1) { ! // store args ! PyObject *&obj = objects[n-1]; ! Py_DECREF(obj); ! obj = MakePyArg(s,argc,argv); // steal reference ! ! if(n > 1) ret = true; // just store, don't trigger ! } ! ! if(!ret) { ! if(function) { ! PyObject *self = PyMethod_Self(function); ! PyErr_Clear(); ! if(!self || self->ob_type != objects[0]->ob_type) ! // type has changed, search for new method ! ResetFunction(); ! else if(self != objects[0]) { ! // type hasn't changed, but object has ! PyObject *f = function; ! function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0],PyMethod_GET_CLASS(f)); ! Py_DECREF(f); ! } ! } ! else ! ResetFunction(); ! ! if(function) { ! Py_INCREF(function); ! ! int inlets = CntIn()-1; ! PyObject *pargs = PyTuple_New(inlets-1); ! for(int i = 1; i < inlets; ++i) { ! Py_INCREF(objects[i]); ! PyTuple_SET_ITEM(pargs,i-1,objects[i]); ! } ! ! gencall(function,pargs); // references are stolen ! ret = true; ! } ! else ! PyErr_SetString(PyExc_RuntimeError,"No function set"); ! ! Report(); ! } ! ! PyUnlock(state); ! ! Respond(ret); ! ! return ret; ! } ! ! void pymeth::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) ! { ! ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); ! } --- 1,428 ---- ! /* ! ! 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 "pybase.h" ! #include <map> ! ! struct xlt { const t_symbol *from,*to; }; ! ! static const xlt xtdefs[] = { ! { flext::MakeSymbol("+"),flext::MakeSymbol("__add__") }, ! { flext::MakeSymbol("+="),flext::MakeSymbol("__iadd__") }, ! { flext::MakeSymbol("!+"),flext::MakeSymbol("__radd__") }, ! { flext::MakeSymbol("-"),flext::MakeSymbol("__sub__") }, ! { flext::MakeSymbol("-="),flext::MakeSymbol("__isub__") }, ! { flext::MakeSymbol("!-"),flext::MakeSymbol("__rsub__") }, ! { flext::MakeSymbol("*"),flext::MakeSymbol("__mul__") }, ! { flext::MakeSymbol("*="),flext::MakeSymbol("__imul__") }, ! { flext::MakeSymbol("!*"),flext::MakeSymbol("__rmul__") }, ! { flext::MakeSymbol("/"),flext::MakeSymbol("__div__") }, ! { flext::MakeSymbol("/="),flext::MakeSymbol("__idiv__") }, ! { flext::MakeSymbol("!/"),flext::MakeSymbol("__rdiv__") }, ! { flext::MakeSymbol("//"),flext::MakeSymbol("__floordiv__") }, ! { flext::MakeSymbol("//="),flext::MakeSymbol("__ifloordiv__") }, ! { flext::MakeSymbol("!//"),flext::MakeSymbol("__rfloordiv__") }, ! { flext::MakeSymbol("%"),flext::MakeSymbol("__mod__") }, ! { flext::MakeSymbol("%="),flext::MakeSymbol("__imod__") }, ! { flext::MakeSymbol("!%"),flext::MakeSymbol("__rmod__") }, ! { flext::MakeSymbol("**"),flext::MakeSymbol("__pow__") }, ! { flext::MakeSymbol("**="),flext::MakeSymbol("__ipow__") }, ! { flext::MakeSymbol("!**"),flext::MakeSymbol("__rpow__") }, ! { flext::MakeSymbol("&"),flext::MakeSymbol("__and__") }, ! { flext::MakeSymbol("&="),flext::MakeSymbol("__iand__") }, ! { flext::MakeSymbol("!&"),flext::MakeSymbol("__rand__") }, ! { flext::MakeSymbol("|"),flext::MakeSymbol("__or__") }, ! { flext::MakeSymbol("|="),flext::MakeSymbol("__ior__") }, ! { flext::MakeSymbol("!|"),flext::MakeSymbol("__ror__") }, ! { flext::MakeSymbol("^"),flext::MakeSymbol("__xor__") }, ! { flext::MakeSymbol("^="),flext::MakeSymbol("__ixor__") }, ! { flext::MakeSymbol("!^"),flext::MakeSymbol("__rxor__") }, ! { flext::MakeSymbol("<<"),flext::MakeSymbol("__lshift__") }, ! { flext::MakeSymbol("<<="),flext::MakeSymbol("__ilshift__") }, ! { flext::MakeSymbol("!<<"),flext::MakeSymbol("__rlshift__") }, ! { flext::MakeSymbol(">>"),flext::MakeSymbol("__rshift__") }, ! { flext::MakeSymbol(">>="),flext::MakeSymbol("__irshift__") }, ! { flext::MakeSymbol("!>>"),flext::MakeSymbol("__rrshift__") }, ! { flext::MakeSymbol("=="),flext::MakeSymbol("__eq__") }, ! { flext::MakeSymbol("!="),flext::MakeSymbol("__ne__") }, ! { flext::MakeSymbol("<"),flext::MakeSymbol("__lt__") }, ! { flext::MakeSymbol(">"),flext::MakeSymbol("__gt__") }, ! { flext::MakeSymbol("<="),flext::MakeSymbol("__le__") }, ! { flext::MakeSymbol(">="),flext::MakeSymbol("__ge__") }, ! { flext::MakeSymbol("!"),flext::MakeSymbol("__nonzero__") }, ! { flext::MakeSymbol("~"),flext::MakeSymbol("__invert__") }, ! { flext::MakeSymbol("[]"),flext::MakeSymbol("__getitem__") }, ! { flext::MakeSymbol("[]="),flext::MakeSymbol("__setitem__") }, ! { flext::MakeSymbol("[:]"),flext::MakeSymbol("__getslice__") }, ! { flext::MakeSymbol("[:]="),flext::MakeSymbol("__setslice__") }, ! ! { flext::MakeSymbol(".abs"),flext::MakeSymbol("__abs__") }, ! { flext::MakeSymbol(".neg"),flext::MakeSymbol("__neg__") }, ! { flext::MakeSymbol(".pos"),flext::MakeSymbol("__pos__") }, ! { flext::MakeSymbol(".divmod"),flext::MakeSymbol("__divmod__") }, ! ! { flext::MakeSymbol(".int"),flext::MakeSymbol("__int__") }, ! { flext::MakeSymbol(".long"),flext::MakeSymbol("__long__") }, ! { flext::MakeSymbol(".float"),flext::MakeSymbol("__float__") }, ! { flext::MakeSymbol(".complex"),flext::MakeSymbol("__complex__") }, ! { flext::MakeSymbol(".str"),flext::MakeSymbol("__str__") }, ! { flext::MakeSymbol(".coerce"),flext::MakeSymbol("__coerce__") }, ! ! { flext::MakeSymbol(".doc"),flext::MakeSymbol("__doc__") }, ! { flext::MakeSymbol(".repr"),flext::MakeSymbol("__repr__") }, ! ! { flext::MakeSymbol(".len"),flext::MakeSymbol("__len__") }, ! { flext::MakeSymbol(".in"),flext::MakeSymbol("__contains") }, ! ! { NULL,NULL } // sentinel ! }; ! ! typedef std::map<const t_symbol *,const t_symbol *> XTable; ! static XTable xtable; ! ! ! class pymeth ! : public pybase ! , public flext_base ! { ! FLEXT_HEADER_S(pymeth,flext_base,Setup) ! ! public: ! pymeth(int argc,const t_atom *argv); ! ~pymeth(); ! ! protected: ! virtual void Exit(); ! ! virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv); ! ! void m_help(); ! ! void m_reload() { Reload(); } ! void m_reload_(int argc,const t_atom *argv) { args(argc,argv); Reload(); } ! void m_set(int argc,const t_atom *argv); ! void m_dir_() { m__dir(function); } ! void m_doc_() { m__doc(function); } ! ! const t_symbol *funname; ! PyObject *function; ! ! virtual void LoadModule(); ! virtual void UnloadModule(); ! ! virtual void Load(); ! virtual void Unload(); ! ! void SetFunction(const t_symbol *func); ! void ResetFunction(); ! ! virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv); ! ! PyObject **objects; ! ! private: ! ! virtual void callpy(PyObject *fun,PyObject *args); ! ! static void Setup(t_classid c); ! ! FLEXT_CALLBACK(m_help) ! FLEXT_CALLBACK(m_reload) ! FLEXT_CALLBACK_V(m_reload_) ! FLEXT_CALLBACK_V(m_set) ! FLEXT_CALLBACK(m_dir_) ! FLEXT_CALLBACK(m_doc_) ! ! // callbacks ! FLEXT_ATTRVAR_I(detach) ! FLEXT_ATTRVAR_B(pymsg) ! FLEXT_ATTRVAR_B(respond) ! ! FLEXT_CALLBACK_V(m_stop) ! FLEXT_CALLBACK(m_dir) ! FLEXT_CALLGET_V(mg_dir) ! FLEXT_CALLBACK(m_doc) ! ! #ifdef FLEXT_THREADS ! FLEXT_CALLBACK_T(tick) ! #endif ! }; ! ! FLEXT_LIB_V("pym",pymeth) ! ! ! void pymeth::Setup(t_classid c) ! { ! FLEXT_CADDMETHOD_(c,0,"doc",m_doc); ! FLEXT_CADDMETHOD_(c,0,"dir",m_dir); ! #ifdef FLEXT_THREADS ! FLEXT_CADDATTR_VAR1(c,"detach",detach); ! FLEXT_CADDMETHOD_(c,0,"stop",m_stop); ! #endif ! ! FLEXT_CADDMETHOD_(c,0,"help",m_help); ! FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); ! FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); ! FLEXT_CADDMETHOD_(c,0,"doc+",m_doc_); ! FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_); ! ! FLEXT_CADDMETHOD_(c,0,"set",m_set); ! ! FLEXT_CADDATTR_VAR1(c,"py",pymsg); ! FLEXT_CADDATTR_VAR1(c,"respond",respond); ! ! // init translation map ! for(const xlt *xi = xtdefs; xi->from; ++xi) xtable[xi->from] = xi->to; ! } ! ! pymeth::pymeth(int argc,const t_atom *argv) ! : funname(NULL) ! , function(NULL) ! , objects(NULL) ! { ! #ifdef FLEXT_THREADS ! FLEXT_ADDTIMER(stoptmr,tick); ! #endif ! ! ThrState state = PyLockSys(); ! ! int inlets; ! if(argc && CanbeInt(*argv)) { ! inlets = GetAInt(*argv); ! if(inlets < 1) inlets = 1; ! argv++,argc--; ! } ! else inlets = 1; ! ! objects = new PyObject *[inlets]; ! for(int i = 0; i < inlets; ++i) { objects[i] = Py_None; Py_INCREF(Py_None); } ! ! if(inlets <= 0) InitProblem(); ! ! AddInAnything(1+(inlets < 0?1:inlets)); ! AddOutAnything(); ! ! Register(GetRegistry(REGNAME)); ! ! if(argc) { ! const t_symbol *funnm = GetASymbol(*argv); ! argv++,argc--; ! ! if(funnm) ! SetFunction(funnm); ! else ! PyErr_SetString(PyExc_ValueError,"Invalid function name"); ! } ! ! if(argc) args(argc,argv); ! ! Report(); ! ! PyUnlock(state); ! } ! ! pymeth::~pymeth() ! { ! if(objects) { ! for(int i = 0; i < CntIn()-1; ++i) Py_DECREF(objects[i]); ! delete[] objects; ! } ! ! ThrState state = PyLockSys(); ! Unregister(GetRegistry(REGNAME)); ! Report(); ! PyUnlock(state); ! } ! ! void pymeth::Exit() ! { ! pybase::Exit(); ! flext_base::Exit(); ! } ! ! void pymeth::m_set(int argc,const t_atom *argv) ! { ! ThrState state = PyLockSys(); ! ! // function name has precedence ! if(argc >= 2) { ! const char *sn = GetAString(*argv); ! ++argv,--argc; ! ! if(sn) { ! if(!module || !strcmp(sn,PyModule_GetName(module))) { ! ImportModule(sn); ! Register(GetRegistry(REGNAME)); ! } ! } ! else ! PyErr_SetString(PyExc_ValueError,"Invalid module name"); ! } ! ! if(argc) { ! const t_symbol *fn = GetASymbol(*argv); ! if(fn) ! SetFunction(fn); ! else ! PyErr_SetString(PyExc_ValueError,"Invalid function name"); ! } ! ! Report(); ! ! PyUnlock(state); ! } ! ! void pymeth::m_help() ! { ! post(""); ! post("%s %s - python method object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION); ! #ifdef FLEXT_DEBUG ! post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__); ! #endif ! ! post("Arguments: %s [method name] {args...}",thisName()); ! ! post("Inlet 1:messages to control the py object"); ! post(" 2:call python function with message as argument(s)"); ! post("Outlet: 1:return values from python function"); ! post("Methods:"); ! post("\thelp: shows this help"); ! post("\tbang: call script without arguments"); ! post("\tset [script name] [function name]: set (script and) function name"); ! post("\treload {args...}: reload python script"); ! post("\treload. : reload with former arguments"); ! post("\tdoc: display module doc string"); ! post("\tdoc+: display function doc string"); ! post("\tdir: dump module dictionary"); ! post("\tdir+: dump function dictionary"); ! #ifdef FLEXT_THREADS ! post("\tdetach 0/1/2: detach threads"); ! post("\tstop {wait time (ms)}: stop threads"); ! #endif ! post(""); ! } ! ! void pymeth::ResetFunction() ! { ! Py_XDECREF(function); ! function = NULL; ! ! if(funname && objects[0] != Py_None) { ! function = PyObject_GetAttrString(objects[0],(char *)GetString(funname)); // new reference ! if(!function) ! PyErr_SetString(PyExc_AttributeError,"Method not found"); ! } ! ! // exception could be set here ! } ! ! void pymeth::SetFunction(const t_symbol *func) ! { ! // look for method name in translation table ! XTable::iterator it = xtable.find(func); ! funname = it == xtable.end()?func:it->second; ! ! ResetFunction(); ! } ! ! ! void pymeth::LoadModule() ! { ! SetFunction(funname); ! } ! ! void pymeth::UnloadModule() ! { ! } ! ! void pymeth::Load() ! { ! ResetFunction(); ! } ! ! void pymeth::Unload() ! { ! SetFunction(NULL); ! } ! ! void pymeth::callpy(PyObject *fun,PyObject *args) ! { ! PyObject *ret = PyObject_CallObject(fun,args); ! if(ret) { ! OutObject(this,0,ret); // exception might be raised here ! Py_DECREF(ret); ! } ! } ! ! bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) ! { ! if(n == 0 && s != sym_bang) ! return flext_base::CbMethodResort(n,s,argc,argv); ! ! ThrState state = PyLockSys(); ! ! bool ret = false; ! ! if(n >= 1) { ! // store args ! PyObject *&obj = objects[n-1]; ! Py_DECREF(obj); ! obj = MakePyArg(s,argc,argv); // steal reference ! ! if(n > 1) ret = true; // just store, don't trigger ! } ! ! if(!ret) { ! if(function) { ! PyObject *self = PyMethod_Self(function); ! PyErr_Clear(); ! if(!self || self->ob_type != objects[0]->ob_type) ! // type has changed, search for new method ! ResetFunction(); ! else if(self != objects[0]) { ! // type hasn't changed, but object has ! PyObject *f = function; ! function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0],PyMethod_GET_CLASS(f)); ! Py_DECREF(f); ! } ! } ! else ! ResetFunction(); ! ! if(function) { ! Py_INCREF(function); ! ! int inlets = CntIn()-1; ! PyObject *pargs = PyTuple_New(inlets-1); ! for(int i = 1; i < inlets; ++i) { ! Py_INCREF(objects[i]); ! PyTuple_SET_ITEM(pargs,i-1,objects[i]); ! } ! ! gencall(function,pargs); // references are stolen ! ret = true; ! } ! else ! PyErr_SetString(PyExc_RuntimeError,"No function set"); ! ! Report(); ! } ! ! PyUnlock(state); ! ! Respond(ret); ! ! return ret; ! } ! ! void pymeth::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) ! { ! ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); ! }
Index: pybundle.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pybundle.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pybundle.cpp 12 Dec 2005 13:55:28 -0000 1.1 --- pybundle.cpp 7 Mar 2007 13:40:14 -0000 1.2 *************** *** 1,232 **** ! /* ! ! 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 "pyprefix.h" ! #include "pybundle.h" ! #include "pyext.h" ! ! static PyObject *bundle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ! { ! pyBundle *self = (pyBundle *)pyBundle_Type.tp_alloc(&pyBundle_Type, 0); ! if(self) self->bundle = flext::MsgNew(); ! return (PyObject *)self; ! } ! ! static int bundle_init(PyObject *self, PyObject *args, PyObject *kwds) ! { ! FLEXT_ASSERT(pyBundle_Check(self)); ! ! int len = PySequence_Length(args); ! if(len) { ! PyErr_SetString(PyExc_TypeError,"no arguments expected"); ! return -1; ! } ! ! return 0; ! } ! ! static void bundle_dealloc(PyObject *obj) ! { ! pyBundle *self = (pyBundle *)obj; ! if(self->bundle) flext::MsgFree(self->bundle); ! obj->ob_type->tp_free(obj); ! } ! ! static PyObject *bundle_send(PyObject *obj) ! { ! pyBundle *self = (pyBundle *)obj; ! if(self->bundle) { ! flext::ToOutMsg(self->bundle); ! self->bundle = NULL; ! ! Py_INCREF(obj); ! return obj; ! } ! else { ! PyErr_SetString(PyExc_RuntimeError,"already sent"); ! return NULL; ! } ! } ! ! static PyObject *bundle_repr(PyObject *self) ! { ! FLEXT_ASSERT(pyBundle_Check(self)); ! return (PyObject *)PyString_FromFormat("<Bundle %p>",pyBundle_AS_BUNDLE(self)); ! } ! ! static PyObject *bundle_str(PyObject *self) ! { ! return bundle_repr(self); ! } ! ! static PyObject *bundle_richcompare(PyObject *a,PyObject *b,int cmp) ! { ! if(pyBundle_Check(a) && pyBundle_Check(b)) { ! const flext::MsgBundle *abnd = pyBundle_AS_BUNDLE(a); ! const flext::MsgBundle *bbnd = pyBundle_AS_BUNDLE(b); ! bool ret; ! switch(cmp) { ! case Py_LT: ret = abnd < bbnd; break; ! case Py_LE: ret = abnd <= bbnd; break; ! case Py_EQ: ret = abnd == bbnd; break; ! case Py_NE: ret = abnd != bbnd; break; ! case Py_GT: ret = abnd > bbnd; break; ! case Py_GE: ret = abnd >= bbnd; break; ! } ! return PyBool_FromLong(ret); ! } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; ! } ! ! static long bundle_hash(PyObject *self) ! { ! FLEXT_ASSERT(pyBundle_Check(self)); ! return (long)pyBundle_AS_BUNDLE(self); ! } ! ! ! static PyObject *bundle_append(PyObject *self,PyObject *args) ! { ! flext::MsgBundle *b = pyBundle_AS_BUNDLE(self); ! if(b) { ! int sz = PyTuple_GET_SIZE(args),offs = 0; ! PyObject *tg,*outl; ! pyext *ext = NULL; ! const t_symbol *recv; ! int o; ! ! if(sz > 2 && ! (tg = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(tg) && ! (outl = PyTuple_GET_ITEM(args,1)) != NULL && PyInt_Check(outl) ! ) { ! // Sending to outlet ! ext = pyext::GetThis(tg); ! o = PyInt_AS_LONG(outl); ! ! if(o < 1 || o > ext->Outlets()) { ! PyErr_SetString(PyExc_ValueError,"Outlet index out of range"); ! return NULL; ! } ! ! offs += 2; ! } ! else if(sz > 1 && ! (tg = PyTuple_GET_ITEM(args,0)) != NULL && (recv = pyObject_AsSymbol(tg)) != NULL ! ) { ! // Sending to receiver ! offs++; ! } ! else { ! // not recognized ! PyErr_SetString(PyExc_SyntaxError,"Unrecognized arguments"); ! return NULL; ! } ! ! PyObject *val; ! if(sz-offs == 1) { ! val = PyTuple_GET_ITEM(args,offs); // borrow reference ! Py_INCREF(val); ! } ! else ! val = PyTuple_GetSlice(args,offs,sz); // new ref ! ! flext::AtomListStatic<16> lst; ! const t_symbol *sym = pybase::GetPyArgs(lst,val); ! Py_DECREF(val); ! ! if(sym) { ! if(ext) { ! FLEXT_ASSERT(outl); ! ext->MsgAddAnything(b,o-1,sym,lst.Count(),lst.Atoms()); ! } ! else { ! FLEXT_ASSERT(sym); ! if(!flext::MsgForward(b,recv,sym,lst.Count(),lst.Atoms())) { ! PyErr_SetString(PyExc_ValueError,"Receiver not found"); ! return NULL; ! } ! } ! ! Py_INCREF(Py_None); ! return Py_None; ! } ! else { ! FLEXT_ASSERT(PyErr_Occurred()); ! return NULL; ! } ! ! Py_INCREF(self); ! return self; ! } ! else { ! PyErr_SetString(PyExc_RuntimeError,"Invalid bundle"); ! return NULL; ! } ! } ! ! static PyMethodDef bundle_methods[] = { ! {"append", (PyCFunction)bundle_append,METH_VARARGS,"Append message to bundle"}, ! {"send", (PyCFunction)bundle_send,METH_NOARGS,"Send bundle"}, ! {NULL} /* Sentinel */ ! }; ! ! ! ! PyTypeObject pyBundle_Type = { ! PyObject_HEAD_INIT(NULL) ! 0, /*ob_size*/ ! "Bundle", /*tp_name*/ ! sizeof(pyBundle), /*tp_basicsize*/ ! 0, /*tp_itemsize*/ ! bundle_dealloc, /*tp_dealloc*/ ! 0, /*tp_print*/ ! 0, /*tp_getattr*/ ! 0, /*tp_setattr*/ ! 0, /*tp_compare*/ ! bundle_repr, /*tp_repr*/ ! 0, /*tp_as_number*/ ! 0, /*tp_as_sequence*/ ! 0, /*tp_as_mapping*/ ! bundle_hash, /*tp_hash */ ! 0, /*tp_call*/ ! bundle_str, /*tp_str*/ ! 0, /*tp_getattro*/ ! 0, /*tp_setattro*/ ! 0, /*tp_as_buffer*/ ! Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ ! "Bundle objects", /* tp_doc */ ! 0, /* tp_traverse */ ! 0, /* tp_clear */ ! bundle_richcompare, /* tp_richcompare */ ! 0, /* tp_weaklistoffset */ ! 0, /* tp_iter */ ! 0, /* tp_iternext */ ! bundle_methods, /* tp_methods */ ! 0, /* tp_members */ ! 0, /* tp_getset */ ! 0, /* tp_base */ ! 0, /* tp_dict */ ! 0, /* tp_descr_get */ ! 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! bundle_init, /* tp_init */ ! 0, /* tp_alloc */ ! bundle_new, /* tp_new */ ! }; ! ! ! void initbundle() ! { ! if(PyType_Ready(&pyBundle_Type) < 0) ! FLEXT_ASSERT(false); ! else ! Py_INCREF(&pyBundle_Type); ! } --- 1,232 ---- ! /* ! ! 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 "pyprefix.h" ! #include "pybundle.h" ! #include "pyext.h" ! ! static PyObject *bundle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ! { ! pyBundle *self = (pyBundle *)pyBundle_Type.tp_alloc(&pyBundle_Type, 0); ! if(self) self->bundle = flext::MsgNew(); ! return (PyObject *)self; ! } ! ! static int bundle_init(PyObject *self, PyObject *args, PyObject *kwds) ! { ! FLEXT_ASSERT(pyBundle_Check(self)); ! ! int len = PySequence_Length(args); ! if(len) { ! PyErr_SetString(PyExc_TypeError,"no arguments expected"); ! return -1; ! } ! ! return 0; ! } ! ! static void bundle_dealloc(PyObject *obj) ! { ! pyBundle *self = (pyBundle *)obj; ! if(self->bundle) flext::MsgFree(self->bundle); ! obj->ob_type->tp_free(obj); ! } ! ! static PyObject *bundle_send(PyObject *obj) ! { ! pyBundle *self = (pyBundle *)obj; ! if(self->bundle) { ! flext::ToOutMsg(self->bundle); ! self->bundle = NULL; ! ! Py_INCREF(obj); ! return obj; ! } ! else { ! PyErr_SetString(PyExc_RuntimeError,"already sent"); ! return NULL; ! } ! } ! ! static PyObject *bundle_repr(PyObject *self) ! { ! FLEXT_ASSERT(pyBundle_Check(self)); ! return (PyObject *)PyString_FromFormat("<Bundle %p>",pyBundle_AS_BUNDLE(self)); ! } ! ! static PyObject *bundle_str(PyObject *self) ! { ! return bundle_repr(self); ! } ! ! static PyObject *bundle_richcompare(PyObject *a,PyObject *b,int cmp) ! { ! if(pyBundle_Check(a) && pyBundle_Check(b)) { ! const flext::MsgBundle *abnd = pyBundle_AS_BUNDLE(a); ! const flext::MsgBundle *bbnd = pyBundle_AS_BUNDLE(b); ! bool ret; ! switch(cmp) { ! case Py_LT: ret = abnd < bbnd; break; ! case Py_LE: ret = abnd <= bbnd; break; ! case Py_EQ: ret = abnd == bbnd; break; ! case Py_NE: ret = abnd != bbnd; break; ! case Py_GT: ret = abnd > bbnd; break; ! case Py_GE: ret = abnd >= bbnd; break; ! } ! return PyBool_FromLong(ret); ! } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; ! } ! ! static long bundle_hash(PyObject *self) ! { ! FLEXT_ASSERT(pyBundle_Check(self)); ! return (long)pyBundle_AS_BUNDLE(self); ! } ! ! ! static PyObject *bundle_append(PyObject *self,PyObject *args) ! { ! flext::MsgBundle *b = pyBundle_AS_BUNDLE(self); ! if(b) { ! int sz = PyTuple_GET_SIZE(args),offs = 0; ! PyObject *tg,*outl; ! pyext *ext = NULL; ! const t_symbol *recv; ! int o; ! ! if(sz > 2 && ! (tg = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(tg) && ! (outl = PyTuple_GET_ITEM(args,1)) != NULL && PyInt_Check(outl) ! ) { ! // Sending to outlet ! ext = pyext::GetThis(tg); ! o = PyInt_AS_LONG(outl); ! ! if(o < 1 || o > ext->Outlets()) { ! PyErr_SetString(PyExc_ValueError,"Outlet index out of range"); ! return NULL; ! } ! ! offs += 2; ! } ! else if(sz > 1 && ! (tg = PyTuple_GET_ITEM(args,0)) != NULL && (recv = pyObject_AsSymbol(tg)) != NULL ! ) { ! // Sending to receiver ! offs++; ! } ! else { ! // not recognized ! PyErr_SetString(PyExc_SyntaxError,"Unrecognized arguments"); ! return NULL; ! } ! ! PyObject *val; ! if(sz-offs == 1) { ! val = PyTuple_GET_ITEM(args,offs); // borrow reference ! Py_INCREF(val); ! } ! else ! val = PyTuple_GetSlice(args,offs,sz); // new ref ! ! flext::AtomListStatic<16> lst; ! const t_symbol *sym = pybase::GetPyArgs(lst,val); ! Py_DECREF(val); ! ! if(sym) { ! if(ext) { ! FLEXT_ASSERT(outl); ! ext->MsgAddAnything(b,o-1,sym,lst.Count(),lst.Atoms()); ! } ! else { ! FLEXT_ASSERT(sym); ! if(!flext::MsgForward(b,recv,sym,lst.Count(),lst.Atoms())) { ! PyErr_SetString(PyExc_ValueError,"Receiver not found"); ! return NULL; ! } ! } ! ! Py_INCREF(Py_None); ! return Py_None; ! } ! else { ! FLEXT_ASSERT(PyErr_Occurred()); ! return NULL; ! } ! ! Py_INCREF(self); ! return self; ! } ! else { ! PyErr_SetString(PyExc_RuntimeError,"Invalid bundle"); ! return NULL; ! } ! } ! ! static PyMethodDef bundle_methods[] = { ! {"append", (PyCFunction)bundle_append,METH_VARARGS,"Append message to bundle"}, ! {"send", (PyCFunction)bundle_send,METH_NOARGS,"Send bundle"}, ! {NULL} /* Sentinel */ ! }; ! ! ! ! PyTypeObject pyBundle_Type = { ! PyObject_HEAD_INIT(NULL) ! 0, /*ob_size*/ ! "Bundle", /*tp_name*/ ! sizeof(pyBundle), /*tp_basicsize*/ ! 0, /*tp_itemsize*/ ! bundle_dealloc, /*tp_dealloc*/ ! 0, /*tp_print*/ ! 0, /*tp_getattr*/ ! 0, /*tp_setattr*/ ! 0, /*tp_compare*/ ! bundle_repr, /*tp_repr*/ ! 0, /*tp_as_number*/ ! 0, /*tp_as_sequence*/ ! 0, /*tp_as_mapping*/ ! bundle_hash, /*tp_hash */ ! 0, /*tp_call*/ ! bundle_str, /*tp_str*/ ! 0, /*tp_getattro*/ ! 0, /*tp_setattro*/ ! 0, /*tp_as_buffer*/ ! Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ ! "Bundle objects", /* tp_doc */ ! 0, /* tp_traverse */ ! 0, /* tp_clear */ ! bundle_richcompare, /* tp_richcompare */ ! 0, /* tp_weaklistoffset */ ! 0, /* tp_iter */ ! 0, /* tp_iternext */ ! bundle_methods, /* tp_methods */ ! 0, /* tp_members */ ! 0, /* tp_getset */ ! 0, /* tp_base */ ! 0, /* tp_dict */ ! 0, /* tp_descr_get */ ! 0, /* tp_descr_set */ ! 0, /* tp_dictoffset */ ! bundle_init, /* tp_init */ ! 0, /* tp_alloc */ ! bundle_new, /* tp_new */ ! }; ! ! ! void initbundle() ! { ! if(PyType_Ready(&pyBundle_Type) < 0) ! FLEXT_ASSERT(false); ! else ! Py_INCREF(&pyBundle_Type); ! }
Index: pybase.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pybase.h,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** pybase.h 3 Aug 2006 16:33:37 -0000 1.12 --- pybase.h 7 Mar 2007 13:40:14 -0000 1.13 *************** *** 1,228 **** ! /* ! ! py/pyext - python script object for PD and MaxMSP ! ! 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 __PYBASE_H ! #define __PYBASE_H ! ! #include "main.h" ! #include "pysymbol.h" ! #include "pybuffer.h" ! #include "pybundle.h" ! ! class pybase ! : public flext ! { ! public: ! pybase(); ! virtual ~pybase(); ! ! void Exit(); ! ! static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1); ! static PyObject *MakePyArg(const t_symbol *s,int argc,const t_atom *argv); ! static const t_symbol *GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0); ! static const t_symbol *GetPyAtom(AtomList &lst,PyObject *pValue); ! ! static void lib_setup(); ! ! protected: ! ! virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv) = 0; ! ! void m__dir(PyObject *obj); ! void m__doc(PyObject *obj); ! ! void m_dir() { m__dir(module); } ! void mg_dir(AtomList &lst) { m__dir(module); } ! void m_doc() { m__doc(dict); } ! ! std::string modname; // module name ! PyObject *module,*dict; // object module and associated dictionary ! ! static const char *py_doc; ! ! void GetDir(PyObject *obj,AtomList &lst); ! ! AtomList args; ! ! void AddCurrentPath(flext_base *o); ! void SetArgs(); ! ! bool OutObject(flext_base *ext,int o,PyObject *obj); ! ! // reload module and all connected objects ! void Reload(); ! ! bool ImportModule(const char *name); ! void UnimportModule(); ! bool ReloadModule(); ! ! // Get module registry ! PyObject *GetRegistry(const char *regname); ! // Set module registry ! void SetRegistry(const char *regname,PyObject *reg); ! ! // Register object ! void Register(PyObject *reg); ! // Unregister object ! void Unregister(PyObject *reg); ! ! virtual void LoadModule() = 0; ! virtual void UnloadModule() = 0; ! ! virtual void Load() = 0; ! virtual void Unload() = 0; ! ! void OpenEditor(); ! ! void Respond(bool b) ! { ! if(respond) { ! t_atom a; ! SetBool(a,b); ! DumpOut(sym_response,1,&a); ! } ! } ! ! void Report() { while(PyErr_Occurred()) PyErr_Print(); } ! ! static bool IsAnything(const t_symbol *s) { return s && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; } ! static bool IsAtom(const t_symbol *s) { return s == sym_float || s == sym_int || s == sym_symbol || s == sym_pointer; } ! ! // enum retval { nothing,atom,sequ }; ! ! // --- module stuff ----- ! ! static PyObject *module_obj,*module_dict; ! static PyObject *builtins_obj,*builtins_dict; ! static PyMethodDef func_tbl[]; ! ! static PyObject *py__doc__(PyObject *,PyObject *args); ! static PyObject *py_send(PyObject *,PyObject *args); ! #ifdef FLEXT_THREADS ! static PyObject *py_priority(PyObject *,PyObject *args); ! #endif ! ! static PyObject *py_arraysupport(PyObject *,PyObject *args); ! static PyObject *py_samplerate(PyObject *,PyObject *args); ! static PyObject *py_blocksize(PyObject *,PyObject *args); ! ! #if FLEXT_SYS == FLEXT_SYS_PD ! static PyObject *py_getvalue(PyObject *,PyObject *args); ! static PyObject *py_setvalue(PyObject *,PyObject *args); ! #endif ! ! static PyObject *py_list(PyObject *,PyObject *args); ! static PyObject *py_tuple(PyObject *,PyObject *args); ! ! // ----thread stuff ------------ ! ! virtual void m_stop(int argc,const t_atom *argv); ! ! bool respond; ! #ifdef FLEXT_THREADS ! int thrcount; ! bool shouldexit; ! int stoptick; ! Timer stoptmr; ! ! void tick(void *); ! #endif ! ! int detach; ! bool pymsg; ! ! bool gencall(PyObject *fun,PyObject *args); ! ! bool docall(PyObject *fun,PyObject *args) ! { ! callpy(fun,args); ! if(PyErr_Occurred()) { ! exchandle(); ! return false; ! } ! else ! return true; ! } ! ! virtual void callpy(PyObject *fun,PyObject *args) = 0; ! ! void exchandle(); ! ! static bool collect(); ! ! protected: ! ! #ifdef FLEXT_THREADS ! static void thrworker(thr_params *data); ! ! bool qucall(PyObject *fun,PyObject *args) ! { ! FifoEl *el = qufifo.New(); ! el->Set(this,fun,args); ! qufifo.Put(el); ! qucond.Signal(); ! return true; ! } ! ! static void quworker(thr_params *); ! void erasethreads(); ! ! static PyFifo qufifo; ! static ThrCond qucond; ! static PyThreadState *pythrsys; ! #endif ! ! static const t_symbol *sym_fint; // float or int symbol, depending on native number message type ! static const t_symbol *sym_response; ! ! static const t_symbol *getone(t_atom &at,PyObject *arg); ! static const t_symbol *getlist(t_atom *lst,PyObject *seq,int cnt,int offs = 0); ! ! public: ! ! static void AddToPath(const char *dir); ! ! #ifdef FLEXT_THREADS ! static PyThreadState *FindThreadState(); ! static void FreeThreadState(); ! ! // this is especially needed when one py/pyext object calls another one ! // we don't want the message to be queued, but otoh we have to avoid deadlock ! // (recursive calls can only happen in the system thread) ! static int lockcount; ! ! static PyThreadState *PyLock(PyThreadState *st = FindThreadState()) ! { ! if(!IsSystemThread() || !lockcount++) PyEval_AcquireLock(); ! return PyThreadState_Swap(st); ! } ! ! static PyThreadState *PyLockSys() ! { ! if(!lockcount++) PyEval_AcquireLock(); ! return PyThreadState_Swap(pythrsys); ! } ! ! static void PyUnlock(PyThreadState *st) ! { ! PyThreadState *old = PyThreadState_Swap(st); ! if(old != pythrsys || !--lockcount) PyEval_ReleaseLock(); ! } ! #else ! static PyThreadState *PyLock(PyThreadState * = NULL) { return NULL; } ! static PyThreadState *PyLockSys() { return NULL; } ! static void PyUnlock(PyThreadState *st) {} ! #endif ! ! static PyObject* StdOut_Write(PyObject* Self, PyObject* Args); ! }; ! ! #endif --- 1,251 ---- ! /* ! ! py/pyext - python script object for PD and MaxMSP ! ! Copyright (c)2002-2007 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 __PYBASE_H ! #define __PYBASE_H ! ! #include "main.h" ! #include "pysymbol.h" ! #include "pybuffer.h" ! #include "pybundle.h" ! ! #ifdef PY_USE_GIL ! typedef PyGILState_STATE ThrState; ! #else ! typedef PyThreadState *ThrState; ! #endif ! ! class pybase ! : public flext ! { ! public: ! pybase(); ! virtual ~pybase(); ! ! void Exit(); ! ! static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1); ! static PyObject *MakePyArg(const t_symbol *s,int argc,const t_atom *argv); ! static const t_symbol *GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0); ! static const t_symbol *GetPyAtom(AtomList &lst,PyObject *pValue); ! ! static void lib_setup(); ! ! protected: ! ! virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv) = 0; ! ! void m__dir(PyObject *obj); ! void m__doc(PyObject *obj); ! ! void m_dir() { m__dir(module); } ! void mg_dir(AtomList &lst) { m__dir(module); } ! void m_doc() { m__doc(dict); } ! ! std::string modname; // module name ! PyObject *module,*dict; // object module and associated dictionary ! ! static const char *py_doc; ! ! void GetDir(PyObject *obj,AtomList &lst); ! ! AtomList args; ! ! void AddCurrentPath(flext_base *o); ! void SetArgs(); ! ! bool OutObject(flext_base *ext,int o,PyObject *obj); ! ! // reload module and all connected objects ! void Reload(); ! ! bool ImportModule(const char *name); ! void UnimportModule(); ! bool ReloadModule(); ! ! // Get module registry ! PyObject *GetRegistry(const char *regname); ! // Set module registry ! void SetRegistry(const char *regname,PyObject *reg); ! ! // Register object ! void Register(PyObject *reg); ! // Unregister object ! void Unregister(PyObject *reg); ! ! virtual void LoadModule() = 0; ! virtual void UnloadModule() = 0; ! ! virtual void Load() = 0; ! virtual void Unload() = 0; ! ! void OpenEditor(); ! ! void Respond(bool b) ! { ! if(respond) { ! t_atom a; ! SetBool(a,b); ! DumpOut(sym_response,1,&a); ! } ! } ! ! void Report() { while(PyErr_Occurred()) PyErr_Print(); } ! ! static bool IsAnything(const t_symbol *s) { return s && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; } ! static bool IsAtom(const t_symbol *s) { return s == sym_float || s == sym_int || s == sym_symbol || s == sym_pointer; } ! ! // enum retval { nothing,atom,sequ }; ! ! // --- module stuff ----- ! ! static PyObject *module_obj,*module_dict; ! static PyObject *builtins_obj,*builtins_dict; ! static PyMethodDef func_tbl[]; ! ! static PyObject *py__doc__(PyObject *,PyObject *args); ! static PyObject *py_send(PyObject *,PyObject *args); ! #ifdef FLEXT_THREADS ! static PyObject *py_priority(PyObject *,PyObject *args); ! #endif ! ! static PyObject *py_arraysupport(PyObject *,PyObject *args); ! static PyObject *py_samplerate(PyObject *,PyObject *args); ! static PyObject *py_blocksize(PyObject *,PyObject *args); ! ! #if FLEXT_SYS == FLEXT_SYS_PD ! static PyObject *py_getvalue(PyObject *,PyObject *args); ! static PyObject *py_setvalue(PyObject *,PyObject *args); ! #endif ! ! static PyObject *py_list(PyObject *,PyObject *args); ! static PyObject *py_tuple(PyObject *,PyObject *args); ! ! // ----thread stuff ------------ ! ! virtual void m_stop(int argc,const t_atom *argv); ! ! bool respond; ! #ifdef FLEXT_THREADS ! int thrcount; ! bool shouldexit; ! int stoptick; ! Timer stoptmr; ! ! void tick(void *); ! #endif ! ! int detach; ! bool pymsg; ! ! bool gencall(PyObject *fun,PyObject *args); ! ! bool docall(PyObject *fun,PyObject *args) ! { ! callpy(fun,args); ! if(PyErr_Occurred()) { ! exchandle(); ! return false; ! } ! else ! return true; ! } ! ! virtual void callpy(PyObject *fun,PyObject *args) = 0; ! ! void exchandle(); ! ! static bool collect(); ! ! protected: ! ! #ifdef FLEXT_THREADS ! static void thrworker(thr_params *data); ! ! bool qucall(PyObject *fun,PyObject *args) ! { ! FifoEl *el = qufifo.New(); ! el->Set(this,fun,args); ! qufifo.Put(el); ! qucond.Signal(); ! return true; ! } ! ! static void quworker(thr_params *); ! static void pyworker(thr_params *); ! void erasethreads(); ! ! static PyFifo qufifo; ! static ThrCond qucond; ! ! #ifndef PY_USE_GIL ! static ThrState pythrsys; ! #endif ! #endif ! ! static const t_symbol *sym_fint; // float or int symbol, depending on native number message type ! static const t_symbol *sym_response; ! ! static const t_symbol *getone(t_atom &at,PyObject *arg); ! static const t_symbol *getlist(t_atom *lst,PyObject *seq,int cnt,int offs = 0); ! ! public: ! ! static void AddToPath(const char *dir); ! ! #ifdef FLEXT_THREADS ! // this is especially needed when one py/pyext object calls another one ! // we don't want the message to be queued, but otoh we have to avoid deadlock ! // (recursive calls can only happen in the system thread) ! static int lockcount; ! ! #ifdef PY_USE_GIL ! static inline ThrState FindThreadState() { return ThrState(); } ! ! static inline ThrState PyLock(ThrState = ThrState()) { return PyGILState_Ensure(); } ! static inline ThrState PyLockSys() { return PyLock(); } ! static inline void PyUnlock(ThrState st) { PyGILState_Release(st); } ! #else // PY_USE_GIL ! static ThrState FindThreadState(); ! static void FreeThreadState(); ! ! static ThrState PyLock(ThrState st = FindThreadState()) ! { ! if(!IsSystemThread() || !lockcount++) PyEval_AcquireLock(); ! return PyThreadState_Swap(st); ! } ! ! #if 1 ! static inline ThrState PyLockSys() { return PyLock(); } ! #else ! static ThrState PyLockSys() ! { ! if(!lockcount++) PyEval_AcquireLock(); ! return PyThreadState_Swap(pythrsys); ! } ! #endif ! ! static void PyUnlock(ThrState st) ! { ! ThrState old = PyThreadState_Swap(st); ! if(old != pythrsys || !--lockcount) PyEval_ReleaseLock(); ! } ! #endif // PY_USE_GIL ! ! #else // FLEXT_THREADS ! static inline ThrState PyLock(ThrState = NULL) { return NULL; } ! static inline ThrState PyLockSys() { return NULL; } ! static inline void PyUnlock(ThrState st) {} ! #endif ! ! static PyObject* StdOut_Write(PyObject* Self, PyObject* Args); ! }; ! ! #endif
Index: pybase.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pybase.cpp,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** pybase.cpp 19 Apr 2006 17:39:41 -0000 1.17 --- pybase.cpp 7 Mar 2007 13:40:14 -0000 1.18 *************** *** 1,881 **** ! /* ! ! py/pyext - python external object for PD and MaxMSP ! ! Copyright (c)2002-2006 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. ! ! */ ! [...1764 lines suppressed...] ! // Push back ! while(el = tmp.Get()) qufifo.Put(el); ! } ! #endif ! ! bool pybase::collect() ! { ! if(gcollect) { ! PyObject *ret = PyObject_CallObject(gcollect,NULL); ! if(ret) { ! #ifdef FLEXT_DEBUG ! int refs = PyInt_AsLong(ret); ! if(refs) post("py/pyext - Garbage collector reports %i unreachable objects",refs); ! #endif ! Py_DECREF(ret); ! return false; ! } ! } ! return true; ! }
Index: py.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/py.cpp,v retrieving revision 1.35 retrieving revision 1.36 diff -C2 -d -r1.35 -r1.36 *** py.cpp 23 Mar 2006 01:42:05 -0000 1.35 --- py.cpp 7 Mar 2007 13:40:14 -0000 1.36 *************** *** 3,7 **** 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. --- 3,7 ---- py/pyext - python script object for PD and Max/MSP
! Copyright (c)2002-2007 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. *************** *** 118,122 **** #endif
! PyThreadState *state = PyLockSys();
int inlets; --- 118,122 ---- #endif
! ThrState state = PyLockSys();
int inlets; *************** *** 194,198 **** }
! PyThreadState *state = PyLockSys(); Unregister(GetRegistry(REGNAME)); Report(); --- 194,198 ---- }
! ThrState state = PyLockSys(); Unregister(GetRegistry(REGNAME)); Report(); *************** *** 208,212 **** void pyobj::m_set(int argc,const t_atom *argv) { ! PyThreadState *state = PyLockSys();
// function name has precedence --- 208,212 ---- void pyobj::m_set(int argc,const t_atom *argv) { ! ThrState state = PyLockSys();
// function name has precedence *************** *** 242,246 **** { post(""); ! post("%s %s - python script object, (C)2002-2006 Thomas Grill",thisName(),PY__VERSION); #ifdef FLEXT_DEBUG post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__); --- 242,246 ---- { post(""); ! post("%s %s - python script object, (C)2002-2007 Thomas Grill",thisName(),PY__VERSION); #ifdef FLEXT_DEBUG post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__); *************** *** 347,351 **** return flext_base::CbMethodResort(n,s,argc,argv);
! PyThreadState *state = PyLockSys();
bool ret = false; --- 347,351 ---- return flext_base::CbMethodResort(n,s,argc,argv);
! ThrState state = PyLockSys();
bool ret = false;
Index: pysymbol.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pysymbol.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** pysymbol.h 26 Sep 2005 13:59:59 -0000 1.4 --- pysymbol.h 7 Mar 2007 13:40:14 -0000 1.5 *************** *** 1,54 **** ! /* ! ! 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 __PYSYMBOL_H ! #define __PYSYMBOL_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; ! } pySymbol; ! ! PY_EXPORT extern PyTypeObject pySymbol_Type; ! ! PY_EXPORT extern pySymbol *pySymbol__; ! PY_EXPORT extern pySymbol *pySymbol_bang; ! PY_EXPORT extern pySymbol *pySymbol_list; ! PY_EXPORT extern pySymbol *pySymbol_symbol; ! PY_EXPORT extern pySymbol *pySymbol_float; ! PY_EXPORT extern pySymbol *pySymbol_int; ! ! #define pySymbol_Check(op) PyObject_TypeCheck(op, &pySymbol_Type) #define pySymbol_CheckExact(op) ((op)->ob_type == &pySymbol_Type) --- 1,54 ---- ! /* ! ! 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 __PYSYMBOL_H ! #define __PYSYMBOL_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; ! } pySymbol; ! ! PY_EXPORT extern PyTypeObject pySymbol_Type; ! ! PY_EXPORT extern pySymbol *pySymbol__; ! PY_EXPORT extern pySymbol *pySymbol_bang; ! PY_EXPORT extern pySymbol *pySymbol_list; ! PY_EXPORT extern pySymbol *pySymbol_symbol; ! PY_EXPORT extern pySymbol *pySymbol_float; ! PY_EXPORT extern pySymbol *pySymbol_int; ! ! #define pySymbol_Check(op) PyObject_TypeCheck(op, &pySymbol_Type) #define pySymbol_CheckExact(op) ((op)->ob_type == &pySymbol_Type) *************** *** 67,92 **** }
! inline const t_symbol *pySymbol_AS_SYMBOL(PyObject *op) ! { ! return ((pySymbol *)op)->sym; ! } ! ! inline const t_symbol *pySymbol_AsSymbol(PyObject *op) ! { ! return pySymbol_Check(op)?pySymbol_AS_SYMBOL(op):NULL; ! } ! ! inline const char *pySymbol_AS_STRING(PyObject *op) ! { ! return flext::GetString(pySymbol_AS_SYMBOL(op)); ! } ! ! inline const t_symbol *pyObject_AsSymbol(PyObject *op) ! { ! if(PyString_Check(op)) ! return flext::MakeSymbol(PyString_AS_STRING(op)); ! else ! return pySymbol_AsSymbol(op); ! } ! ! #endif --- 67,92 ---- }
! inline const t_symbol *pySymbol_AS_SYMBOL(PyObject *op) ! { ! return ((pySymbol *)op)->sym; ! } ! ! inline const t_symbol *pySymbol_AsSymbol(PyObject *op) ! { ! return pySymbol_Check(op)?pySymbol_AS_SYMBOL(op):NULL; ! } ! ! inline const char *pySymbol_AS_STRING(PyObject *op) ! { ! return flext::GetString(pySymbol_AS_SYMBOL(op)); ! } ! ! inline const t_symbol *pyObject_AsSymbol(PyObject *op) ! { ! if(PyString_Check(op)) ! return flext::MakeSymbol(PyString_AS_STRING(op)); ! else ! return pySymbol_AsSymbol(op); ! } ! ! #endif