diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2005-03-13 04:59:47 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2005-03-13 04:59:47 +0000 |
commit | 3ce0fb7e8ad57909fadcd4072817d69bc54e3a66 (patch) | |
tree | f4d4478420cc9f34bf26835f2edc5bd03f95a86b /externals/grill/py/source/pydsp.cpp | |
parent | 0e0bfeecb60ffa25d997830553685482c666b7ba (diff) |
pydsp: share dsp buffer objects at inplace operation
DSP support for py/pyext: new objects pyext~,pyx~,pyext.~,pyx.~
new base class for py and pyext classes
preset sys.argv for module loading
support for buffer objects (preliminary)
py: bang in left inlet now really triggers without arguments
fixes for detached operation and single-threaded version
little restructuring
adjust pd and py files for correct argument passing
more optimizations
update for new flext callback naming
use lock count instead of message queuing to avoid py->py messaging deadlock
pyext: fix for inlet count
svn path=/trunk/; revision=2624
Diffstat (limited to 'externals/grill/py/source/pydsp.cpp')
-rw-r--r-- | externals/grill/py/source/pydsp.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/externals/grill/py/source/pydsp.cpp b/externals/grill/py/source/pydsp.cpp new file mode 100644 index 00000000..b1f50c0d --- /dev/null +++ b/externals/grill/py/source/pydsp.cpp @@ -0,0 +1,179 @@ +/*
+
+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 "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(bool update = false);
+ 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)
+ {
+ NewBuffers();
+
+ dspfun = PyObject_GetAttrString(pyobj,"_dsp"); // get ref
+ if(dspfun && !PyMethod_Check(dspfun)) {
+ Py_DECREF(dspfun);
+ dspfun = NULL;
+ }
+ sigfun = PyObject_GetAttrString(pyobj,"_signal"); // get ref
+ if(sigfun && !PyMethod_Check(sigfun)) {
+ Py_DECREF(sigfun);
+ sigfun = NULL;
+ }
+ }
+ return true;
+}
+
+void pydsp::DoExit()
+{
+ if(dspfun) { Py_DECREF(dspfun); dspfun = NULL; }
+ if(sigfun) { Py_DECREF(sigfun); sigfun = NULL; }
+
+ FreeBuffers();
+}
+
+PyObject *NAFromBuffer(PyObject *buf,int c,int n);
+
+void pydsp::NewBuffers(bool update)
+{
+ int i,n = Blocksize();
+ const int ins = CntInSig(),outs = CntOutSig();
+ t_sample *const *insigs = InSig();
+ t_sample *const *outsigs = OutSig();
+
+ if(!buffers) {
+ int cnt = ins+outs;
+ if(cnt) {
+ buffers = new PyObject *[cnt];
+ memset(buffers,0,cnt*sizeof(*buffers));
+ }
+ }
+
+ for(i = 0; i < ins; ++i) {
+ if(update) Py_XDECREF(buffers[i]);
+ PyObject *b = PyBuffer_FromReadWriteMemory(insigs[i],n*sizeof(t_sample));
+ buffers[i] = NAFromBuffer(b,1,n);
+ Py_DECREF(b);
+ }
+ for(i = 0; i < outs; ++i) {
+ if(update) 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] = NAFromBuffer(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(CntInSig() || CntOutSig())
+ {
+ NewBuffers(true);
+
+ if(dspfun) {
+ PyThreadState *state = PyLock();
+// Py_INCREF(emptytuple);
+ PyObject *ret = PyObject_Call(dspfun,emptytuple,NULL);
+// Py_DECREF(emptytuple);
+ if(ret)
+ Py_DECREF(ret);
+ else {
+#ifdef FLEXT_DEBUG
+ PyErr_Print();
+#else
+ PyErr_Clear();
+#endif
+ }
+ PyUnlock(state);
+ }
+ return true;
+ }
+ else
+ // switch on dsp only if there are signal inlets or outlets
+ return false;
+}
+
+void pydsp::CbSignal()
+{
+ if(sigfun) {
+ PyThreadState *state = PyLock();
+// Py_INCREF(emptytuple);
+ PyObject *ret = PyObject_Call(sigfun,emptytuple,NULL);
+// Py_DECREF(emptytuple);
+
+ if(ret)
+ Py_DECREF(ret);
+ else {
+#ifdef FLEXT_DEBUG
+ PyErr_Print();
+#else
+ PyErr_Clear();
+#endif
+ }
+ PyUnlock(state);
+ }
+ else
+ flext_dsp::CbSignal();
+}
+
+PyObject *pydsp::GetSig(int ix,bool in)
+{
+ PyObject *r = buffers[in?ix:CntInSig()+ix];
+ Py_XINCREF(r);
+ return r;
+}
+
|