From 0ed7a8b68dd73e2b0473b8127aeca99f3bac9061 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Wed, 1 Apr 2009 21:13:09 +0000 Subject: cleaned up grill externals - replaced with svn:externals to svn.grrrr.org/ext/trunk/ svn path=/trunk/; revision=10951 --- externals/grill/py/source/pyext.cpp | 662 ------------------------------------ 1 file changed, 662 deletions(-) delete mode 100644 externals/grill/py/source/pyext.cpp (limited to 'externals/grill/py/source/pyext.cpp') diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp deleted file mode 100644 index b2b7baca..00000000 --- a/externals/grill/py/source/pyext.cpp +++ /dev/null @@ -1,662 +0,0 @@ -/* -py/pyext - python script object for PD and Max/MSP - -Copyright (c)2002-2008 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. - -$LastChangedRevision: 26 $ -$LastChangedDate: 2008-01-03 17:20:03 +0100 (Thu, 03 Jan 2008) $ -$LastChangedBy: thomas $ -*/ - -#include "pyext.h" -#include - - -FLEXT_LIB_V("pyext pyext. pyx pyx.",pyext) - - -static const t_symbol *sym_get; - -void pyext::Setup(t_classid c) -{ - sym_get = flext::MakeSymbol("get"); - - 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_CADDATTR_GET(c,"dir+",mg_dir_); - - FLEXT_CADDATTR_VAR(c,"args",initargs,ms_initargs); - - FLEXT_CADDMETHOD_(c,0,"get",m_get); - FLEXT_CADDMETHOD_(c,0,"set",m_set); - - FLEXT_CADDMETHOD_(c,0,"edit",CbClick); - - FLEXT_CADDATTR_VAR1(c,"py",pymsg); - FLEXT_CADDATTR_VAR1(c,"respond",respond); - - // ---------------------------------------------------- - - // register/initialize pyext base class along with module - class_dict = PyDict_New(); - PyObject *className = PyString_FromString(PYEXT_CLASS); - PyMethodDef *def; - - // add setattr/getattr to class - for(def = attr_tbl; def->ml_name; def++) { - PyObject *func = PyCFunction_New(def, NULL); - PyDict_SetItemString(class_dict, def->ml_name, func); - Py_DECREF(func); - } - - class_obj = PyClass_New(NULL, class_dict, className); - Py_DECREF(className); - - // add methods to class - for (def = meth_tbl; def->ml_name != NULL; def++) { - PyObject *func = PyCFunction_New(def, NULL); - PyObject *method = PyMethod_New(func, NULL, class_obj); // increases class_obj ref count by 1 - PyDict_SetItemString(class_dict, def->ml_name, method); - Py_DECREF(func); - Py_DECREF(method); - } - -#if PY_VERSION_HEX >= 0x02020000 - // not absolutely necessary, existent in python 2.2 upwards - // make pyext functions available in class scope - PyDict_Merge(class_dict,module_dict,0); -#endif - // after merge so that it's not in class_dict as well... - PyDict_SetItemString(module_dict, PYEXT_CLASS,class_obj); // increases class_obj ref count by 1 - - PyDict_SetItemString(class_dict,"__doc__",PyString_FromString(pyext_doc)); -} - -pyext *pyext::GetThis(PyObject *self) -{ - PyObject *th = PyObject_GetAttrString(self,"_this"); - if(th) { - pyext *ret = static_cast(PyLong_AsVoidPtr(th)); - Py_DECREF(th); - return ret; - } - else { - PyErr_Clear(); - return NULL; - } -} - -void pyext::SetThis() -{ - // remember the this pointer - PyObject *th = PyLong_FromVoidPtr(this); - PyObject_SetAttrString(pyobj,"_this",th); // ref is taken -} - -void pyext::ClearThis() -{ - int ret = PyObject_DelAttrString(pyobj,"_this"); - FLEXT_ASSERT(ret != -1); -} - -PyObject *pyext::class_obj = NULL; -PyObject *pyext::class_dict = NULL; - -pyext::pyext(int argc,const t_atom *argv,bool sig): - methname(NULL), - pyobj(NULL), - inlets(-1),outlets(-1), - siginlets(0),sigoutlets(0) -#ifndef PY_USE_GIL - ,pythr(NULL) -#endif -{ -#ifdef FLEXT_THREADS - FLEXT_ADDTIMER(stoptmr,tick); -#endif - - if(argc >= 2 && CanbeInt(argv[0]) && CanbeInt(argv[1])) { - inlets = GetAInt(argv[0]); - outlets = GetAInt(argv[1]); - argv += 2,argc -= 2; - } - - if(sig && argc >= 2 && CanbeInt(argv[0]) && CanbeInt(argv[1])) { - siginlets = GetAInt(argv[0]); - sigoutlets = GetAInt(argv[1]); - argv += 2,argc -= 2; - } - - const t_symbol *clname = NULL; - - // check if the object name is pyext. , pyx. or similar - bool dotted = strrchr(thisName(),'.') != NULL; - - ThrState state = PyLockSys(); - - // init script module - if(argc) { - AddCurrentPath(this); - - const t_symbol *scr = GetASymbol(*argv); - argv++,argc--; - - if(scr) { - char modnm[64]; - strcpy(modnm,GetString(scr)); - - if(!dotted) { - char *pt = strrchr(modnm,'.'); // search for last dot - if(pt && *pt) { - clname = MakeSymbol(pt+1); - *pt = 0; - } - } - - ImportModule(modnm); - } - else - PyErr_SetString(PyExc_ValueError,"Invalid module name"); - - // check for alias creation names - if(dotted) clname = scr; - } - - Register(GetRegistry(REGNAME)); - - if(argc || clname) { - if(!clname) { - clname = GetASymbol(*argv); - argv++,argc--; - } - - if(clname) - methname = clname; - else - PyErr_SetString(PyExc_ValueError,"Invalid class name"); - } - - if(argc) initargs(argc,argv); - - Report(); - - PyUnlock(state); -} - -bool pyext::Init() -{ - ThrState state = PyLockSys(); - - if(methname) { - MakeInstance(); - if(pyobj) InitInOut(inlets,outlets); - } - else - inlets = outlets = 0; - - if(inlets < 0) inlets = 0; - if(outlets < 0) outlets = 0; - - AddInSignal(siginlets); - AddInAnything((siginlets?0:1)+inlets); - AddOutSignal(sigoutlets); - AddOutAnything(outlets); - - Report(); - PyUnlock(state); - - return pyobj && flext_dsp::Init(); -} - -bool pyext::Finalize() -{ - bool ok = true; - ThrState state = PyLockSys(); - - PyObject *init = PyObject_GetAttrString(pyobj,"_init"); // get ref - if(init) { - if(PyMethod_Check(init)) { - PyObject *res = PyObject_CallObject(init,NULL); - if(!res) { - // exception is set - ok = false; - // we want to know why __init__ failed... - PyErr_Print(); - } - else - Py_DECREF(res); - } - Py_DECREF(init); - } - else - // __init__ has not been found - don't care - PyErr_Clear(); - - PyUnlock(state); - return ok && flext_dsp::Finalize(); -} - -void pyext::Exit() -{ - pybase::Exit(); // exit threads - - ThrState state = PyLockSys(); - DoExit(); - - Unregister(GetRegistry(REGNAME)); - UnimportModule(); - - Report(); - PyUnlock(state); - - flext_dsp::Exit(); -} - -bool pyext::DoInit() -{ - // call init now, after _this has been set, which is - // important for eventual callbacks from __init__ to c - PyObject *pargs = MakePyArgs(NULL,initargs.Count(),initargs.Atoms()); - if(pargs) { - bool ok = true; - - SetThis(); - - PyObject *init = PyObject_GetAttrString(pyobj,"__init__"); // get ref - if(init) { - if(PyMethod_Check(init)) { - PyObject *res = PyObject_CallObject(init,pargs); - if(!res) { - // exception is set - ok = false; - // we want to know why __init__ failed... - PyErr_Print(); - } - else - Py_DECREF(res); - } - Py_DECREF(init); - } - else - // __init__ has not been found - don't care - PyErr_Clear(); - - Py_DECREF(pargs); - return ok; - } - else - return false; -} - -void pyext::DoExit() -{ - ClearBinding(); - - bool gcrun = false; - if(pyobj) { - // try to run del to clean up the class instance - PyObject *objdel = PyObject_GetAttrString(pyobj,"_del"); - if(objdel) { - PyObject *ret = PyObject_CallObject(objdel,NULL); - if(ret) - Py_DECREF(ret); - else - PyErr_Print(); - Py_DECREF(objdel); - } - else - // _del has not been found - don't care - PyErr_Clear(); - - ClearThis(); - - gcrun = pyobj->ob_refcnt > 1; - Py_DECREF(pyobj); // opposite of SetClssMeth - } - - if(gcrun && !collect()) { - post("%s - Unloading: Object is still referenced",thisName()); - } -} - -bool pyext::InitInOut(int &inl,int &outl) -{ - if(inl >= 0) { - // set number of inlets - int ret = PyObject_SetAttrString(pyobj,"_inlets",PyInt_FromLong(inl)); - FLEXT_ASSERT(!ret); - } - if(outl >= 0) { - // set number of outlets - int ret = PyObject_SetAttrString(pyobj,"_outlets",PyInt_FromLong(outl)); - FLEXT_ASSERT(!ret); - } - - // __init__ can override the number of inlets and outlets - if(!DoInit()) // call __init__ constructor - return false; - - if(inl < 0) { - // get number of inlets - inl = inlets; - PyObject *res = PyObject_GetAttrString(pyobj,"_inlets"); // get ref - if(res) { - if(PyCallable_Check(res)) { - PyObject *fres = PyEval_CallObject(res,NULL); - Py_DECREF(res); - res = fres; - } - if(PyInt_Check(res)) - inl = PyInt_AS_LONG(res); - Py_DECREF(res); - } - else - PyErr_Clear(); - } - if(outl < 0) { - // get number of outlets - outl = outlets; - PyObject *res = PyObject_GetAttrString(pyobj,"_outlets"); // get ref - if(res) { - if(PyCallable_Check(res)) { - PyObject *fres = PyEval_CallObject(res,NULL); - Py_DECREF(res); - res = fres; - } - if(PyInt_Check(res)) - outl = PyInt_AS_LONG(res); - Py_DECREF(res); - } - else - PyErr_Clear(); - } - - return true; -} - -bool pyext::MakeInstance() -{ - // pyobj should already have been decref'd / cleared before getting here!! - - if(module && methname) { - PyObject *pref = PyObject_GetAttrString(module,const_cast(GetString(methname))); - if(!pref) - PyErr_Print(); - else { - if(PyClass_Check(pref)) { - // make instance, but don't call __init__ - pyobj = PyInstance_NewRaw(pref,NULL); - - if(!pyobj) PyErr_Print(); - } - else - post("%s - Type of \"%s\" is unhandled!",thisName(),GetString(methname)); - - Py_DECREF(pref); - } - return true; - } - else - return false; -} - -void pyext::LoadModule() -{ -} - -void pyext::UnloadModule() -{ -} - -void pyext::Load() -{ - FLEXT_ASSERT(!pyobj); - - bool ok = MakeInstance(); - - if(ok) { - int inl = -1,outl = -1; - ok = InitInOut(inl,outl); - - if((inl >= 0 && inl != inlets) || (outl >= 0 && outl != outlets)) - post("%s - Inlet and outlet count can't be changed by reload",thisName()); - } - -// return ok; -} - -void pyext::Unload() -{ - DoExit(); - pyobj = NULL; -} - -void pyext::m_get(const t_symbol *s) -{ - ThrState state = PyLockSys(); - - PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast(GetString(s))); /* fetch bound method */ - if(pvar) { - flext::AtomListStatic<16> lst; - const t_symbol *sym = GetPyArgs(lst,pvar,1); - if(sym) { - FLEXT_ASSERT(!IsAnything(sym)); - // dump value to attribute outlet - SetSymbol(lst[0],s); - ToOutAnything(GetOutAttr(),sym_get,lst.Count(),lst.Atoms()); - } - - Py_DECREF(pvar); - } - - Report(); - - PyUnlock(state); -} - -void pyext::m_set(int argc,const t_atom *argv) -{ - ThrState state = PyLockSys(); - - if(argc < 2 || !IsString(argv[0])) - post("%s - Syntax: set varname arguments...",thisName()); - else if(*GetString(argv[0]) == '_') - post("%s - set: variables with leading _ are reserved and can't be set",thisName()); - else { - char *ch = const_cast(GetString(argv[0])); - if(PyObject_HasAttrString(pyobj,ch)) { - PyObject *pval = MakePyArgs(NULL,argc-1,argv+1); - if(pval) { - if(PySequence_Size(pval) == 1) { - // reduce lists of one element to element itself - - PyObject *val1 = PySequence_GetItem(pval,0); // new reference - Py_DECREF(pval); - pval = val1; - } - - PyObject_SetAttrString(pyobj,ch,pval); - Py_DECREF(pval); - } - } - } - - Report(); - - PyUnlock(state); -} - - -bool pyext::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) -{ - if(!n) - return flext_dsp::CbMethodResort(n,s,argc,argv); - - return pyobj && work(n,s,argc,argv); -} - - -void pyext::m_help() -{ - post(""); - post("%s %s - python class object, (C)2002-2008 Thomas Grill",thisName(),PY__VERSION); -#ifdef FLEXT_DEBUG - post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__); -#endif - - post("Arguments: %s {inlets outlets} [script name] [class name] {args...}",thisName()); - - post("Inlet 1: messages to control the pyext object"); - post(" 2...: python inlets"); - post("Outlets: python outlets"); - post("Methods:"); - post("\thelp: shows this help"); - post("\treload {args...}: reload python script"); - post("\treload. : reload with former arguments"); - post("\tdoc: display module doc string"); - post("\tdoc+: display class doc string"); - post("\tdir: dump module dictionary"); - post("\tdir+: dump class dictionary"); -#ifdef FLEXT_THREADS - post("\tdetach 0/1: detach threads"); - post("\tstop {wait time (ms)}: stop threads"); -#endif - post(""); -} - -void pyext::callpy(PyObject *fun,PyObject *args) -{ - PyObject *ret = PyObject_CallObject(fun,args); - if(ret) { - // function worked fine - if(!PyObject_Not(ret)) post("pyext - returned value is ignored"); - Py_DECREF(ret); - } -} - - -bool pyext::call(const char *meth,int inlet,const t_symbol *s,int argc,const t_atom *argv) -{ - bool ret = false; - - PyObject *pmeth = PyObject_GetAttrString(pyobj,const_cast(meth)); /* fetch bound method */ - if(pmeth == NULL) { - PyErr_Clear(); // no method found - } - else { - PyObject *pargs = MakePyArgs(s,argc,argv,inlet?inlet:-1); //,true); - if(!pargs) { - PyErr_Print(); - Py_DECREF(pmeth); - } - else { - gencall(pmeth,pargs); - ret = true; - } - } - return ret; -} - -bool pyext::work(int n,const t_symbol *s,int argc,const t_atom *argv) -{ - bool ret = false; - - ThrState state = PyLock(); - - // should be enough... - char str[256]; - - // offset inlet index by signal inlets - // \note first one is shared with messages! - if(siginlets) n += siginlets-1; - - // try tag/inlet - if(!ret) { - sprintf(str,"%s_%i",GetString(s),n); - ret = call(str,0,NULL,argc,argv); - } - - if(!ret && argc == 1) { - if(s == sym_float) { - // try truncated float - t_atom at; SetInt(at,GetAInt(argv[0])); - sprintf(str,"int_%i",n); - ret = call(str,0,NULL,1,&at); - } - else if(s == sym_int) { - // try floating int - t_atom at; SetFloat(at,GetAFloat(argv[0])); - sprintf(str,"float_%i",n); - ret = call(str,0,NULL,1,&at); - } - } - - // try anything/inlet - if(!ret) { - sprintf(str,"_anything_%i",n); - ret = call(str,0,s,argc,argv); - } - - // try tag at any inlet - if(!ret) { - sprintf(str,"%s_",GetString(s)); - ret = call(str,n,NULL,argc,argv); - } - - if(!ret && argc == 1) { - if(s == sym_float) { - // try truncated float at any inlet - t_atom at; SetInt(at,GetAInt(argv[0])); - ret = call("int_",0,NULL,1,&at); - } - else if(s == sym_int) { - // try floating int at any inlet - t_atom at; SetFloat(at,GetAFloat(argv[0])); - ret = call("float_",0,NULL,1,&at); - } - } - - if(!ret) { - // try anything at any inlet - const char *str1 = "_anything_"; - if(s == sym_bang && !argc) { - t_atom argv; - SetSymbol(argv,sym__); - ret = call(str1,n,s,1,&argv); - } - else - ret = call(str1,n,s,argc,argv); - } - - if(!ret) - // no matching python method found - post("%s - no matching method found for '%s' into inlet %i",thisName(),GetString(s),n); - - PyUnlock(state); - - Respond(ret); - return ret; -} - -PyObject *pyext::GetSig(int ix,bool in) { return NULL; } - -void pyext::CbClick() { pybase::OpenEditor(); } -bool pyext::CbDsp() { return false; } - -void pyext::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) -{ - ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); -} -- cgit v1.2.1