/* py/pyext - python external 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. */ #include "main.h" static PyObject *MakePyAtom(const t_atom &at) { if(flext::IsSymbol(at)) return pySymbol_FromSymbol(flext::GetSymbol(at)); else if(flext::CanbeInt(at) || flext::CanbeFloat(at)) { // if a number can be an integer... let at be an integer! int ival = flext::GetAInt(at); double fval = flext::GetAFloat(at); return (double)ival == fval?PyInt_FromLong(ival):PyFloat_FromDouble(fval); } // else if(flext::IsPointer(at)) return NULL; // not handled /* // these following should never happen else if(flext::IsFloat(at)) return PyFloat_FromDouble((double)flext::GetFloat(at)); else if(flext::IsInt(at)) return PyInt_FromLong(flext::GetInt(at)); */ return NULL; } PyObject *py::MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet,bool withself) { PyObject *pArgs; /* if(!s && args.Count() == 1) { pArgs = MakePyAtom(args[0]); if(!pArgs) post("py/pyext: cannot convert argument(s)"); } else */ { bool any = IsAnything(s); pArgs = PyTuple_New(argc+(any?1:0)+(inlet >= 0?1:0)); int pix = 0; if(inlet >= 0) PyTuple_SetItem(pArgs, pix++, PyInt_FromLong(inlet)); int ix; PyObject *tmp; // if(!withself || argc < (any?1:2)) tmp = pArgs,ix = pix; // else // tmp = PyTuple_New(argc+(any?1:0)),ix = 0; if(any) PyTuple_SET_ITEM(tmp, ix++, pySymbol_FromSymbol(s)); for(int i = 0; i < argc; ++i) { PyObject *pValue = MakePyAtom(argv[i]); if(!pValue) { post("py/pyext: cannot convert argument %i",any?i+1:i); continue; } /* pValue reference stolen here: */ PyTuple_SET_ITEM(tmp, ix++, pValue); } if(tmp != pArgs) { PyTuple_SET_ITEM(pArgs, pix++, tmp); #if PY_VERSION_HEX >= 0x02020000 _PyTuple_Resize(&pArgs,pix); #else _PyTuple_Resize(&pArgs,pix,0); #endif } } return pArgs; } flext::AtomList *py::GetPyArgs(PyObject *pValue,PyObject **self) { if(pValue == NULL) return NULL; AtomList *ret = NULL; // analyze return value or tuple int rargc = 0; bool ok = true; retval tp = nothing; if(PyString_Check(pValue)) { rargc = 1; tp = atom; } else if(PySequence_Check(pValue)) { rargc = PySequence_Size(pValue); tp = sequ; } else if(pValue == Py_None) Py_DECREF(pValue); else { rargc = 1; tp = atom; } ret = new AtomList(rargc); for(int ix = 0; ix < rargc; ++ix) { PyObject *arg; if(tp == sequ) arg = PySequence_GetItem(pValue,ix); // new reference else arg = pValue; if(PyInt_Check(arg)) SetInt((*ret)[ix],PyInt_AsLong(arg)); else if(PyLong_Check(arg)) SetInt((*ret)[ix],PyLong_AsLong(arg)); else if(PyFloat_Check(arg)) SetFloat((*ret)[ix],(float)PyFloat_AsDouble(arg)); else if(pySymbol_Check(arg)) SetSymbol((*ret)[ix],pySymbol_AS_SYMBOL(arg)); else if(PyString_Check(arg)) SetString((*ret)[ix],PyString_AS_STRING(arg)); else if(ix == 0 && self && PyInstance_Check(arg)) { // assumed to be self ... that should be checked _somehow_ !!! Py_INCREF(arg); *self = arg; } else { PyObject *tp = PyObject_Type(arg); PyObject *stp = tp?PyObject_Str(tp):NULL; char *tmp = ""; if(stp) tmp = PyString_AS_STRING(stp); post("py/pyext: Could not convert argument %s",tmp); Py_XDECREF(stp); Py_XDECREF(tp); ok = false; } if(tp == sequ) Py_DECREF(arg); } if(!ok) { delete ret; ret = NULL; } return ret; }