aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/py/source/py.cpp
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2002-10-22 23:16:30 +0000
committerThomas Grill <xovo@users.sourceforge.net>2002-10-22 23:16:30 +0000
commitc2645dc4003b1391aba9b387a79a66cff1e63d3e (patch)
tree1ea6dccb8011a8ff64efb7c2ecf9a22caad860b3 /externals/grill/py/source/py.cpp
parentd62e56f4df9594f72ce501f5e19c974fd18e7295 (diff)
This commit was generated by cvs2svn to compensate for changes in r189,
which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=190
Diffstat (limited to 'externals/grill/py/source/py.cpp')
-rw-r--r--externals/grill/py/source/py.cpp327
1 files changed, 327 insertions, 0 deletions
diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp
new file mode 100644
index 00000000..83c5d9b5
--- /dev/null
+++ b/externals/grill/py/source/py.cpp
@@ -0,0 +1,327 @@
+/*
+
+py/pyext - python script object for PD and MaxMSP
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+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 pyobj:
+ public py
+{
+ FLEXT_HEADER(pyobj,py)
+
+public:
+ pyobj(I argc,t_atom *argv);
+ ~pyobj();
+
+protected:
+ BL m_method_(I n,const t_symbol *s,I argc,t_atom *argv);
+
+ V work(const t_symbol *s,I argc,t_atom *argv);
+
+ V m_bang() { work(sym_bang,0,NULL); }
+ V m_reload();
+ V m_reload_(I argc,t_atom *argv);
+ V m_set(I argc,t_atom *argv);
+ V m_doc_();
+
+ virtual V m_help();
+
+ // methods for python arguments
+ V callwork(const t_symbol *s,I argc,t_atom *argv);
+
+ V m_py_list(I argc,t_atom *argv) { callwork(sym_list,argc,argv); }
+ V m_py_float(I argc,t_atom *argv) { callwork(sym_float,argc,argv); }
+ V m_py_int(I argc,t_atom *argv) { callwork(sym_int,argc,argv); }
+ V m_py_any(const t_symbol *s,I argc,t_atom *argv) { callwork(s,argc,argv); }
+
+ const t_symbol *funname;
+ PyObject *function;
+
+ virtual V Reload();
+
+ V SetFunction(const C *func);
+ V ResetFunction();
+
+private:
+
+ FLEXT_CALLBACK(m_bang)
+ FLEXT_CALLBACK(m_reload)
+ FLEXT_CALLBACK_V(m_reload_)
+ FLEXT_CALLBACK_V(m_set)
+ FLEXT_CALLBACK(m_doc_)
+
+ FLEXT_CALLBACK_V(m_py_float)
+ FLEXT_CALLBACK_V(m_py_list)
+ FLEXT_CALLBACK_V(m_py_int)
+ FLEXT_CALLBACK_A(m_py_any)
+
+#ifdef FLEXT_THREADS
+ FLEXT_THREAD_A(work)
+#else
+ FLEXT_CALLBACK_A(work)
+#endif
+};
+
+FLEXT_LIB_V("py",pyobj)
+
+
+pyobj::pyobj(I argc,t_atom *argv):
+ function(NULL),funname(NULL)
+{
+ PY_LOCK
+
+ AddInAnything(2);
+ AddOutAnything();
+
+ FLEXT_ADDBANG(0,m_bang);
+ FLEXT_ADDMETHOD_(0,"reload",m_reload_);
+ FLEXT_ADDMETHOD_(0,"reload.",m_reload);
+ FLEXT_ADDMETHOD_(0,"set",m_set);
+ FLEXT_ADDMETHOD_(0,"doc",m_doc);
+ FLEXT_ADDMETHOD_(0,"doc+",m_doc_);
+#ifdef FLEXT_THREADS
+ FLEXT_ADDMETHOD_(0,"detach",m_detach);
+ FLEXT_ADDMETHOD_(0,"stop",m_stop);
+#endif
+
+ FLEXT_ADDMETHOD_(1,"float",m_py_float);
+ FLEXT_ADDMETHOD_(1,"int",m_py_int);
+ FLEXT_ADDMETHOD(1,m_py_list);
+ FLEXT_ADDMETHOD(1,m_py_any);
+
+ if(argc > 2)
+ SetArgs(argc-2,argv+2);
+ else
+ SetArgs(0,NULL);
+
+ // init script module
+ if(argc >= 1) {
+ C dir[1024];
+ GetModulePath(GetString(argv[0]),dir,sizeof(dir));
+ // set script path
+ AddToPath(dir);
+
+ if(!IsString(argv[0]))
+ post("%s - script name argument is invalid",thisName());
+ else
+ ImportModule(GetString(argv[0]));
+ }
+
+ Register("_py");
+
+ if(argc >= 2) {
+ // set function name
+ if(!IsString(argv[1]))
+ post("%s - function name argument is invalid",thisName());
+ else {
+ // Set function
+ SetFunction(GetString(argv[1]));
+ }
+ }
+
+ PY_UNLOCK
+}
+
+pyobj::~pyobj()
+{
+ PY_LOCK
+ Unregister("_py");
+ PY_UNLOCK
+}
+
+
+
+
+BL pyobj::m_method_(I n,const t_symbol *s,I argc,t_atom *argv)
+{
+ if(n == 1)
+ post("%s - no method for type %s",thisName(),GetString(s));
+ return false;
+}
+
+V pyobj::m_reload()
+{
+ PY_LOCK
+
+ Unregister("_py");
+
+ ReloadModule();
+ Reregister("_py");
+ Register("_py");
+ SetFunction(funname?GetString(funname):NULL);
+
+ PY_UNLOCK
+}
+
+V pyobj::m_reload_(I argc,t_atom *argv)
+{
+ PY_LOCK
+ SetArgs(argc,argv);
+ PY_UNLOCK
+
+ m_reload();
+}
+
+V pyobj::m_set(I argc,t_atom *argv)
+{
+ PY_LOCK
+
+ I ix = 0;
+ if(argc >= 2) {
+ if(!IsString(argv[ix])) {
+ post("%s - script name is not valid",thisName());
+ return;
+ }
+ const C *sn = GetString(argv[ix]);
+
+ if(!module || !strcmp(sn,PyModule_GetName(module))) {
+ ImportModule(sn);
+ Register("_py");
+ }
+
+ ++ix;
+ }
+
+ if(!IsString(argv[ix]))
+ post("%s - function name is not valid",thisName());
+ else
+ SetFunction(GetString(argv[ix]));
+
+ PY_UNLOCK
+}
+
+
+V pyobj::m_doc_()
+{
+ PY_LOCK
+
+ if(function) {
+ PyObject *docf = PyObject_GetAttrString(function,"__doc__"); // borrowed!!!
+ if(docf && PyString_Check(docf)) {
+ post("");
+ post(PyString_AsString(docf));
+ }
+ }
+
+ PY_UNLOCK
+}
+
+
+V pyobj::m_help()
+{
+ post("");
+ post("py %s - python script object, (C)2002 Thomas Grill",PY__VERSION);
+#ifdef _DEBUG
+ post("compiled on " __DATE__ " " __TIME__);
+#endif
+
+ post("Arguments: %s [script name] [function 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");
+#ifdef FLEXT_THREADS
+ post("\tdetach 0/1: detach threads");
+ post("\tstop {wait time (ms)}: stop threads");
+#endif
+ post("");
+}
+
+V pyobj::ResetFunction()
+{
+ if(!module || !dict)
+ {
+ post("%s - No module loaded",thisName());
+ function = NULL;
+ return;
+ }
+
+ function = funname?PyDict_GetItemString(dict,(C *)GetString(funname)):NULL; // borrowed!!!
+ if(!function) {
+ PyErr_Clear();
+ if(funname) post("%s - Function %s could not be found",thisName(),GetString(funname));
+ }
+ else if(!PyFunction_Check(function)) {
+ post("%s - Object %s is not a function",thisName(),GetString(funname));
+ function = NULL;
+ }
+}
+
+V pyobj::SetFunction(const C *func)
+{
+ if(func) {
+ funname = MakeSymbol(func);
+ ResetFunction();
+ }
+ else
+ function = NULL,funname = NULL;
+}
+
+
+V pyobj::Reload()
+{
+ ResetFunction();
+}
+
+
+V pyobj::work(const t_symbol *s,I argc,t_atom *argv)
+{
+ AtomList *rargs = NULL;
+
+ ++thrcount;
+ PY_LOCK
+
+ if(function) {
+ PyObject *pArgs = MakePyArgs(s,AtomList(argc,argv));
+ PyObject *pValue = PyObject_CallObject(function, pArgs);
+
+ rargs = GetPyArgs(pValue);
+ if(!rargs) PyErr_Print();
+
+ Py_XDECREF(pArgs);
+ Py_XDECREF(pValue);
+ }
+ else {
+ post("%s: no function defined",thisName());
+ }
+
+ PY_UNLOCK
+ --thrcount;
+
+ if(rargs) {
+ // call to outlet _outside_ the Mutex lock!
+ // otherwise (if not detached) deadlock will occur
+ ToOutList(0,*rargs);
+ delete rargs;
+ }
+}
+
+V pyobj::callwork(const t_symbol *s,I argc,t_atom *argv)
+{
+ if(detach) {
+ if(shouldexit)
+ post("%s - New threads can't be launched now!",thisName());
+ else
+ if(!FLEXT_CALLMETHOD_A(work,s,argc,argv))
+ post("%s - Failed to launch thread!",thisName());
+ }
+ else
+ work(s,argc,argv);
+}
+
+