From ec67ac9af1c9a02130347c4ed6f32fa03f55eba2 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Thu, 10 Mar 2005 04:59:00 +0000 Subject: more buffer functionality (support sequence and number protocols) more examples preset sys.argv for module loading support for buffer objects (preliminary) svn path=/trunk/; revision=2615 --- externals/grill/py/pd/buffer-1.pd | 63 +++-- externals/grill/py/readme.txt | 5 +- externals/grill/py/scripts/buffer.py | 50 ++-- externals/grill/py/source/main.cpp | 32 ++- externals/grill/py/source/pybuffer.cpp | 496 ++++++++++++++++++++++++++++++--- 5 files changed, 552 insertions(+), 94 deletions(-) (limited to 'externals') diff --git a/externals/grill/py/pd/buffer-1.pd b/externals/grill/py/pd/buffer-1.pd index 2309ca30..ca799385 100644 --- a/externals/grill/py/pd/buffer-1.pd +++ b/externals/grill/py/pd/buffer-1.pd @@ -1,39 +1,40 @@ -#N canvas 123 58 692 472 12; +#N canvas 123 58 712 492 12; #X obj 37 240 print; #X obj 107 241 print A; #X msg 30 139 reload; #N canvas 0 0 450 300 graph1 0; #X array array1 100 float 3; -#A 0 0 0 0 0 0 0 0 0 0 0 0.0285713 0.042857 0.042857 0.042857 0.042857 -0.042857 0.0142857 0.0142857 0.0142857 -0.0285713 -0.0571427 -0.0999997 --0.171428 -0.185714 -0.199999 -0.271428 -0.342856 -0.385713 -0.385713 --0.385713 -0.385713 -0.385713 -0.385713 -0.385713 -0.385713 -0.357142 --0.357142 -0.357142 -0.335713 -0.314285 -0.299999 -0.285713 -0.271428 --0.257142 -0.242856 -0.228571 -0.214285 -0.185714 -0.157142 -0.128571 --0.0999997 -0.085714 -0.0714283 -0.042857 -0.0142857 0.0142857 0.042857 -0.0523808 0.0619046 0.0714283 0.114285 0.15 0.214285 0.257142 0.228571 -0.207142 0.185714 0.157142 0.085714 0.0142857 0.0142857 0.0142857 -0.0571427 --0.0571427 -0.0999997 -0.0999997 -0.0999997 -0.171428 -0.171428 -0.158646 --0.142105 -0.125564 -0.109022 -0.092481 -0.0759397 -0.0593984 -0.042857 --0.0175824 0.00769227 0.0329669 0.0582416 0.0835162 0.108791 0.134065 -0.15934 0.184615 0.209889 0.235164 0.260439 0.32857; +#A 0 0 0 0 0 0 0 0 0 0 0 0.00285713 0.00471427 0.00514284 0.00557141 +0.00599998 0.00642855 0.00228571 0.00242857 0.00257143 -0.00542855 +-0.0114285 -0.0209999 -0.0377142 -0.0427142 -0.0479998 -0.067857 -0.0891426 +-0.104143 -0.108 -0.111857 -0.115714 -0.119571 -0.123428 -0.127285 +-0.131142 -0.125 -0.128571 -0.132143 -0.127571 -0.122571 -0.12 -0.117142 +-0.114 -0.110571 -0.106857 -0.102857 -0.0985711 -0.0872856 -0.0754282 +-0.0629998 -0.0499999 -0.0437141 -0.0371427 -0.0227142 -0.00771428 +0.00785714 0.0239999 0.0298571 0.0359047 0.0421427 0.068571 0.0915 +0.132857 0.161999 0.146285 0.134642 0.122571 0.105285 0.0582855 0.00985713 +0.00999999 0.0101428 -0.0411427 -0.0417142 -0.0739998 -0.0749998 -0.0759998 +-0.132 -0.133714 -0.12533 -0.113684 -0.101707 -0.089398 -0.0767592 +-0.0637893 -0.0504886 -0.036857 -0.0152967 0.0067692 0.0293405 0.0524174 +0.0759997 0.100088 0.12468 0.14978 0.175384 0.201493 0.228109 0.25523 +0.325284; #X coords 0 1 99 -1 200 140 1; #X restore 421 156 graph; #N canvas 0 0 450 300 graph2 0; #X array array2 100 float 3; -#A 0 0 0 0 0 0 0 0.0285712 0.0428568 0.0571424 0.0999993 0.114285 0.128571 -0.142856 0.157142 0.171427 0.185713 0.199999 0.242855 0.257141 0.271426 -0.314283 0.342854 0.385711 0.421425 0.485711 0.557139 0.599995 0.671424 -0.680947 0.690471 0.699995 0.742852 0.752375 0.761899 0.771423 0.771423 -0.771423 0.81428 0.81428 0.81428 0.81428 0.828565 0.842851 0.842851 -0.842851 0.842851 0.842851 0.842851 0.864279 0.885708 0.885708 0.885708 -0.885708 0.876184 0.86666 0.857136 0.857136 0.857137 0.842851 0.828565 -0.81428 0.799994 0.785708 0.76428 0.742852 0.728566 0.71428 0.671424 -0.599995 0.428568 0.40714 -0.328569 -0.428569 -0.428569 -0.471425 -0.471425 --0.471425 -0.442854 -0.442854 -0.399997 -0.385712 -0.371426 -0.335712 --0.299998 -0.257141 -0.242856 -0.22857 -0.157142 -0.114285 -0.0857139 --0.0857139 -0.042857 -0.042857 0.028571 0.0571425 0.0571425 0.0999993 -0.128571 0.128571 0.128571; +#A 0 0 0 0 0 0 0 0.0285712 0.0428568 0.0571424 0.12857 0.171427 0.185712 +0.199998 0.242854 0.342853 0.342853 0.364281 0.41428 0.41428 0.357138 +0.314282 0.278568 0.314282 0.328567 0.342853 0.378567 0.41428 0.457137 +0.49285 0.528564 0.54285 0.557135 0.599992 0.614277 0.671419 0.671419 +0.599992 0.614276 0.59999 0.585705 0.571419 0.499991 0.482135 0.464278 +0.446421 0.428564 0.408564 0.388565 0.368565 0.348565 0.328566 0.305709 +0.282852 0.259995 0.237138 0.214282 0.194282 0.174282 0.154282 0.134283 +0.114283 0.0914263 0.0685695 0.0457127 0.0228559 8.84384e-007 0.0142864 +0.0285719 0.0428574 0.0571429 0.0714284 0.096428 0.121428 0.146427 +0.171427 0.181631 0.191835 0.202039 0.212243 0.222446 0.23265 0.242854 +0.25714 0.271425 0.285711 0.299996 0.314282 0.33571 0.357138 0.385709 +0.407138 0.428566 0.457137 0.457137 0.12857 0.514279 0.557135 0.604754 +0.652372 0.814274; #X coords 0 1 99 -1 200 140 1; #X restore 421 305 graph; #N canvas 0 0 450 300 graph3 0; @@ -41,16 +42,20 @@ #X coords 0 1 99 -1 200 140 1; #X restore 65 301 graph; #X obj 36 199 py buffer @detach 1; -#X msg 123 127 mul array3 array1 array2; -#X msg 123 149 add array3 array1 array2; +#X msg 192 127 mul array3 array1 array2; +#X msg 192 149 add array3 array1 array2; #X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 235 16 Python script objects \, (C)2003-2005 Thomas Grill; #X text 235 32 http://grrrr.org/ext; #X text 17 67 This demonstrates the usage of buffers. See the buffer.py script.; +#X msg 193 176 fadein array1; +#X msg 191 200 neg array2; #X connect 2 0 6 0; #X connect 6 0 0 0; #X connect 6 1 1 0; #X connect 7 0 6 1; #X connect 8 0 6 1; +#X connect 13 0 6 1; +#X connect 14 0 6 1; diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt index ff2266dd..60260706 100644 --- a/externals/grill/py/readme.txt +++ b/externals/grill/py/readme.txt @@ -83,7 +83,7 @@ Version history: - ADD: Python symbol type - ADD: _del method in pyext-derived class can be used to clean up things on exit - FIX: solved py->py messaging problem with lock count instead of message queuing -- ADD: numarray support for buffer handling +- ADD: buffer handling with optional numarray support (if present) 0.1.4: - ADD: better (and independent) handling of inlet and outlet count (as class variables or dynamically initialized in __init__) @@ -146,6 +146,9 @@ Version history: TODO list: +bugs: +- crashes with long Python printouts + general: - Documentation and better example patches - better error reporting for runtime errors diff --git a/externals/grill/py/scripts/buffer.py b/externals/grill/py/scripts/buffer.py index 4c81caab..19b6f5d3 100644 --- a/externals/grill/py/scripts/buffer.py +++ b/externals/grill/py/scripts/buffer.py @@ -7,12 +7,9 @@ """This is an example script for the py/pyext object's buffer support. -PD/Max buffers can be imported to and exported from numarray arrays. +PD/Max buffers can be mapped to numarray arrays. For numarray see http://numeric.scipy.org -It will probably once be replaced by Numeric - -- _import(buffer): copy contents from the buffer to a new numarray object -- _export(buffer,numarray): export contents of numarray object to the buffer +It will probably once be replaced by Numeric(3) """ import sys @@ -20,7 +17,7 @@ import sys try: import pyext except: - print "ERROR: This script must be loaded by the PD/Max pyext external" + print "ERROR: This script must be loaded by the PD/Max py/pyext external" try: from numarray import * @@ -28,19 +25,36 @@ except: print "Failed importing numarray module:",sys.exc_value def mul(*args): + # create buffer objects + # as long as these variables live the underlying buffers are locked c = pyext.Buffer(args[0]) - dst = c.array() - dst[:] = 0 - a = pyext.Buffer(args[1]).array() - b = pyext.Buffer(args[2]).array() - dst += a*b - c.dirty() + a = pyext.Buffer(args[1]) + b = pyext.Buffer(args[2]) + + # slicing causes numarrays (mapped to buffers) to be created + # note the c[:] - to assign contents you must assign to a slice of the buffer + c[:] = a[:]*b[:] def add(*args): c = pyext.Buffer(args[0]) - dst = c.array() - dst[:] = 0 - a = pyext.Buffer(args[1]).array() - b = pyext.Buffer(args[2]).array() - dst += a+b - c.dirty() + a = pyext.Buffer(args[1]) + b = pyext.Buffer(args[2]) + + # this is also possible, but is probably slower + # the + converts a into a numarray, the argument b is taken as a sequence + # depending on the implementation in numarray this may be as fast + # as above or not + c[:] = a+b + +def fadein(target): + a = pyext.Buffer(target) + # in place operations are ok + a *= arange(len(a),type=Float32)/len(a) + +def neg(target): + a = pyext.Buffer(target) + # in place transformation (see numarray ufuncs) + negative(a[:],a[:]) + # must mark buffer content as dirty to update graph + # (no explicit assignment occurred) + a.dirty() diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp index c24f998c..e32b9ba8 100644 --- a/externals/grill/py/source/main.cpp +++ b/externals/grill/py/source/main.cpp @@ -97,12 +97,30 @@ void py::lib_setup() pythrmap[GetThreadId()] = pythrmain; #endif + // sys.argv must be set to empty tuple + char *nothing = ""; + PySys_SetArgv(0,¬hing); + // register/initialize pyext module only once! module_obj = Py_InitModule(PYEXT_MODULE, func_tbl); module_dict = PyModule_GetDict(module_obj); // borrowed reference PyModule_AddStringConstant(module_obj,"__doc__",(char *)py_doc); + // redirect stdout + PyObject* py_out; + py_out = Py_InitModule("stdout", StdOut_Methods); + PySys_SetObject("stdout", py_out); + py_out = Py_InitModule("stderr", StdOut_Methods); + PySys_SetObject("stderr", py_out); + + // get garbage collector function + PyObject *gcobj = PyImport_ImportModule("gc"); + if(gcobj) { + gcollect = PyObject_GetAttrString(gcobj,"collect"); + Py_DECREF(gcobj); + } + // add symbol type initsymbol(); PyModule_AddObject(module_obj,"Symbol",(PyObject *)&pySymbol_Type); @@ -119,20 +137,6 @@ void py::lib_setup() initsamplebuffer(); PyModule_AddObject(module_obj,"Buffer",(PyObject *)&pySamplebuffer_Type); - // redirect stdout - PyObject* py_out; - py_out = Py_InitModule("stdout", StdOut_Methods); - PySys_SetObject("stdout", py_out); - py_out = Py_InitModule("stderr", StdOut_Methods); - PySys_SetObject("stderr", py_out); - - // get garbage collector function - PyObject *gcobj = PyImport_ImportModule("gc"); - if(gcobj) { - gcollect = PyObject_GetAttrString(gcobj,"collect"); - Py_DECREF(gcobj); - } - // ------------------------------------------------------------- FLEXT_SETUP(pyobj); diff --git a/externals/grill/py/source/pybuffer.cpp b/externals/grill/py/source/pybuffer.cpp index ed1b2749..96f2efae 100644 --- a/externals/grill/py/source/pybuffer.cpp +++ b/externals/grill/py/source/pybuffer.cpp @@ -101,31 +101,6 @@ static PyGetSetDef buffer_getseters[] = { {NULL} /* Sentinel */ }; -static PyObject *buffer_array(PyObject *obj) -{ - PyObject *ret; -#ifdef PY_NUMARRAY - if(nasupport) { - pySamplebuffer *self = (pySamplebuffer *)obj; - if(self->buf) { - maybelong shape[2]; - shape[0] = self->buf->Frames(); - shape[1] = self->buf->Channels(); - ret = (PyObject *)NA_NewAllFromBuffer(2,shape,numtype,(PyObject *)self,0,sizeof(t_sample *),NA_ByteOrder(),1,1); - } - else - Py_INCREF(ret = Py_None); - } - else { - PyErr_Format(PyExc_RuntimeError,"No numarray support"); - ret = NULL; - } -#else - Py_INCREF(ret = Py_None); -#endif - return ret; -} - static PyObject *buffer_dirty(PyObject *obj) { ((pySamplebuffer *)obj)->dirty = true; @@ -134,7 +109,6 @@ static PyObject *buffer_dirty(PyObject *obj) } static PyMethodDef buffer_methods[] = { - {"array", (PyCFunction)buffer_array,METH_NOARGS,"Return a numarray object"}, {"dirty", (PyCFunction)buffer_dirty,METH_NOARGS,"Mark buffer as dirty"}, {NULL} /* Sentinel */ }; @@ -170,13 +144,470 @@ static int buffer_charbuffer(PyObject *obj, int segment, const char **ptrptr) return b->Channels()*b->Frames()*sizeof(t_sample); } -static PyBufferProcs bufferprocs = { +static PyBufferProcs buffer_as_buffer = { buffer_readbuffer, buffer_writebuffer, buffer_segcount, buffer_charbuffer }; +static int buffer_length(pySamplebuffer *self) +{ + return self->buf?self->buf->Frames():0; +} + +static PyObject *buffer_item(pySamplebuffer *self, int i) +{ + PyObject *ret; + if(self->buf) { + if (i < 0 || i >= self->buf->Frames()) { + PyErr_SetString(PyExc_IndexError,"Index out of range"); + ret = NULL; + } + else { + if(self->buf->Channels() == 1) + ret = PyFloat_FromDouble(self->buf->Data()[i]); + else { + PyErr_SetString(PyExc_NotImplementedError,"Multiple channels not implemented yet"); + ret = NULL; + } + } + } + else + Py_INCREF(ret = Py_None); + return ret; +} + +static PyObject *buffer_slice(pySamplebuffer *self,int ilow = 0,int ihigh = 1<<(sizeof(int)*8-2)) +{ + PyObject *ret; +#ifdef PY_NUMARRAY + if(nasupport) { + if(self->buf) { + const int n = self->buf->Frames(); + const int c = self->buf->Channels(); + if(ilow < 0) ilow += n; + if(ilow >= n) ilow = n-1; + if(ihigh < 0) ihigh += n; + if(ihigh > n) ihigh = n; + + maybelong shape[2]; + shape[0] = n; + shape[1] = c; + PyObject *nobj = (PyObject *)NA_NewAllFromBuffer(c == 1?1:2,shape,numtype,(PyObject *)self,0,0,NA_ByteOrder(),1,1); + if(ilow != 0 || ihigh != n) { + ret = PySequence_GetSlice(nobj,ilow,ihigh); + Py_DECREF(nobj); + } + else + ret = nobj; + } + else + Py_INCREF(ret = Py_None); + } + else +#endif + { + PyErr_SetString(PyExc_RuntimeError,"No numarray support"); + ret = NULL; + } + return ret; +} + +static int buffer_ass_item(pySamplebuffer *self,int i,PyObject *v) +{ + int ret; + if(self->buf) { + if (i < 0 || i >= self->buf->Frames()) { + PyErr_Format(PyExc_IndexError,"Index out of range"); + ret = -1; + } + else { + if(self->buf->Channels() == 1) { + self->buf->Data()[i] = (t_sample)PyFloat_AsDouble(v); + if(PyErr_Occurred()) { + // cast to double failed + PyErr_SetString(PyExc_TypeError,"Value must be a numarray"); + ret = -1; + } + else { + self->dirty = true; + ret = 0; + } + } + else { + PyErr_SetString(PyExc_NotImplementedError,"Multiple channels not implemented yet"); + ret = -1; + } + } + } + else + ret = -1; + return ret; +} + +static int buffer_ass_slice(pySamplebuffer *self,int ilow,int ihigh,PyObject *value) +{ + int ret; +#ifdef PY_NUMARRAY + if(nasupport) { + if(!value) { + PyErr_SetString(PyExc_TypeError,"Object doesn't support item deletion"); + ret = -1; + } + else if(self->buf) { + const int n = self->buf->Frames(); + const int c = self->buf->Channels(); + if(ilow < 0) ilow += n; + if(ilow >= n) ilow = n-1; + if(ihigh < 0) ihigh += n; + if(ihigh > n) ihigh = n; + + PyArrayObject *out = NA_InputArray(value,numtype,NUM_C_ARRAY); + if(!out) { + PyErr_SetString(PyExc_TypeError,"Assigned object must be a numarray"); + ret = -1; + } + else if(out->nd != 1) { + PyErr_SetString(PyExc_NotImplementedError,"Multiple dimensions not supported yet"); + ret = -1; + } + else { + int dlen = ihigh-ilow; + int slen = out->dimensions[0]; + flext::CopySamples(self->buf->Data()+ilow,(t_sample *)NA_OFFSETDATA(out),slen < dlen?slen:dlen); + self->dirty = true; + ret = 0; + } + + Py_XDECREF(out); + } + else { + PyErr_SetString(PyExc_ValueError,"Buffer is not assigned"); + ret = -1; + } + } + else +#endif + { + PyErr_SetString(PyExc_RuntimeError,"No numarray support"); + ret = -1; + } + return ret; +} + +static PyObject *buffer_concat(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PySequence_Concat(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_repeat(pySamplebuffer *self,int rep) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PySequence_Repeat(nobj,rep); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + + +static PySequenceMethods buffer_as_seq = { + (inquiry)buffer_length, /* inquiry sq_length; /* __len__ */ + (binaryfunc)buffer_concat, /* __add__ */ + (intargfunc)buffer_repeat, /* __mul__ */ + (intargfunc)buffer_item, /* intargfunc sq_item; /* __getitem__ */ + (intintargfunc)buffer_slice, /* intintargfunc sq_slice; /* __getslice__ */ + (intobjargproc)buffer_ass_item, /* intobjargproc sq_ass_item; /* __setitem__ */ + (intintobjargproc)buffer_ass_slice, /* intintobjargproc sq_ass_slice; /* __setslice__ */ +}; + +static PyObject *buffer_iter(PyObject *obj) +{ + pySamplebuffer *self = (pySamplebuffer *)obj; + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *it = PyObject_GetIter(nobj); + Py_DECREF(nobj); + return it; + } + else + return NULL; +} + + +static PyObject *buffer_add(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Add(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_subtract(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Subtract(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_multiply(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Multiply(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_divide(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Divide(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_remainder(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Remainder(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_divmod(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Divmod(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_power(pySamplebuffer *self,PyObject *op1,PyObject *op2) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Power(nobj,op1,op2); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_negative(pySamplebuffer *self) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Negative(nobj); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_pos(pySamplebuffer *self) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Positive(nobj); + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_absolute(pySamplebuffer *self) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_Absolute(nobj); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static int buffer_coerce(pySamplebuffer **pm, PyObject **pw) +{ + if(pySamplebuffer_Check(*pw)) { + Py_INCREF(*pm); + Py_INCREF(*pw); + return 0; + } + else + return 1; +} + +static PyObject *buffer_inplace_add(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_InPlaceAdd(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_inplace_subtract(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_InPlaceSubtract(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_inplace_multiply(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_InPlaceMultiply(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_inplace_divide(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_InPlaceDivide(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_inplace_remainder(pySamplebuffer *self,PyObject *op) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_InPlaceRemainder(nobj,op); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + +static PyObject *buffer_inplace_power(pySamplebuffer *self,PyObject *op1,PyObject *op2) +{ + PyObject *nobj = buffer_slice(self); + if(nobj) { + PyObject *ret = PyNumber_InPlacePower(nobj,op1,op2); + if(ret == nobj) self->dirty = true; + Py_DECREF(nobj); + return ret; + } + else + return NULL; +} + + + +static PyNumberMethods buffer_as_number = { + (binaryfunc)buffer_add, /*nb_add*/ + (binaryfunc)buffer_subtract, /*nb_subtract*/ + (binaryfunc)buffer_multiply, /*nb_multiply*/ + (binaryfunc)buffer_divide, /*nb_divide*/ + (binaryfunc)buffer_remainder, /*nb_remainder*/ + (binaryfunc)buffer_divmod, /*nb_divmod*/ + (ternaryfunc)buffer_power, /*nb_power*/ + (unaryfunc)buffer_negative, + (unaryfunc)buffer_pos, /*nb_pos*/ + (unaryfunc)buffer_absolute, /* (unaryfunc)buffer_abs, */ + 0, //(inquiry)buffer_nonzero, /*nb_nonzero*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ + (coercion)buffer_coerce, /*nb_coerce*/ + 0, /*nb_int*/ + 0, /*nb_long*/ + 0, /*nb_float*/ + 0, /*nb_oct*/ + 0, /*nb_hex*/ + (binaryfunc)buffer_inplace_add, /* nb_inplace_add */ + (binaryfunc)buffer_inplace_subtract, /* nb_inplace_subtract */ + (binaryfunc)buffer_inplace_multiply, /* nb_inplace_multiply */ + (binaryfunc)buffer_inplace_divide, /* nb_inplace_divide */ + (binaryfunc)buffer_inplace_remainder, /* nb_inplace_remainder */ + (ternaryfunc)buffer_inplace_power, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ +// buffer_floor_div, /* nb_floor_divide */ +// buffer_div, /* nb_true_divide */ +// buffer_inplace_floor_div, /* nb_inplace_floor_divide */ +// buffer_inplace_div, /* nb_inplace_true_divide */ +}; + PyTypeObject pySamplebuffer_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ @@ -189,22 +620,22 @@ PyTypeObject pySamplebuffer_Type = { 0, /*tp_setattr*/ 0, /*tp_compare*/ buffer_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ + &buffer_as_number, /*tp_as_number*/ + &buffer_as_seq, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ buffer_hash, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ - &bufferprocs, /*tp_as_buffer*/ + &buffer_as_buffer, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ "Samplebuffer objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0 /*buffer_richcompare*/, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ + buffer_iter, /* tp_iter */ 0, /* tp_iternext */ buffer_methods, /* tp_methods */ 0, /* tp_members */ @@ -222,10 +653,11 @@ PyTypeObject pySamplebuffer_Type = { void initsamplebuffer() { #ifdef PY_NUMARRAY + PyErr_Clear(); import_libnumarray(); if(PyErr_Occurred()) // catch import error - PyErr_Clear(); + PyErr_Print(); else { // numarray support ok nasupport = true; -- cgit v1.2.1