[PD-cvs] externals/grill/py/source bound.cpp,1.12,1.13 clmeth.cpp,1.11,1.12 main.cpp,1.18,1.19 main.h,1.25,1.26 modmeth.cpp,1.12,1.13 py.cpp,1.15,1.16 pyargs.cpp,1.9,1.10 pyext.cpp,1.22,1.23 pyext.h,1.17,1.18 register.cpp,1.4,1.5

Thomas Grill xovo at users.sourceforge.net
Sun Jan 9 05:59:32 CET 2005


Update of /cvsroot/pure-data/externals/grill/py/source
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7214/source

Modified Files:
	bound.cpp clmeth.cpp main.cpp main.h modmeth.cpp py.cpp 
	pyargs.cpp pyext.cpp pyext.h register.cpp 
Log Message:
support for Python threads, at last
small fixes
merged in 20041229-newdetach branch.
renamed locking functions


Index: clmeth.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/clmeth.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -d -r1.11 -r1.12
*** clmeth.cpp	17 Dec 2004 05:04:29 -0000	1.11
--- clmeth.cpp	9 Jan 2005 04:59:30 -0000	1.12
***************
*** 3,7 ****
  py/pyext - python external object for PD and Max/MSP
  
! Copyright (c) 2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and Max/MSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 40,45 ****
  
  
! const C *pyext::pyext_doc =
! 	"py/pyext - python external object for PD and Max/MSP, (C)2002-2004 Thomas Grill\n"
  	"\n"
  	"This is the pyext base class. Available methods:\n"
--- 40,45 ----
  
  
! const char *pyext::pyext_doc =
! 	"py/pyext - python external object for PD and Max/MSP, (C)2002-2005 Thomas Grill\n"
  	"\n"
  	"This is the pyext base class. Available methods:\n"
***************
*** 82,86 ****
      }
  
! 	BL handled = false;
      if(PyString_Check(name)) {
  	    char* sname = PyString_AsString(name);
--- 82,86 ----
      }
  
! 	bool handled = false;
      if(PyString_Check(name)) {
  	    char* sname = PyString_AsString(name);
***************
*** 137,141 ****
  PyObject *pyext::pyext_outlet(PyObject *,PyObject *args)
  {
! 	BL ok = false;
  
      // should always be a tuple!
--- 137,141 ----
  PyObject *pyext::pyext_outlet(PyObject *,PyObject *args)
  {
! 	bool ok = false;
  
      // should always be a tuple!
***************
*** 151,158 ****
  		pyext *ext = GetThis(self);
  
! 		I sz = PyTuple_Size(args);
  		PyObject *val;
          
!         BL tp = 
              sz == 3 && 
              PySequence_Check(
--- 151,158 ----
  		pyext *ext = GetThis(self);
  
! 		int sz = PyTuple_Size(args);
  		PyObject *val;
          
!         bool tp = 
              sz == 3 && 
              PySequence_Check(
***************
*** 165,169 ****
  		AtomList *lst = GetPyArgs(val);
  		if(lst) {
! 			I o = PyInt_AsLong(outl);
  			if(o >= 1 && o <= ext->Outlets()) {
  				// by using the queue there is no immediate call of the next object
--- 165,169 ----
  		AtomList *lst = GetPyArgs(val);
  		if(lst) {
! 			int o = PyInt_AsLong(outl);
  			if(o >= 1 && o <= ext->Outlets()) {
  				// by using the queue there is no immediate call of the next object
***************
*** 226,230 ****
  	else {
  		pyext *ext = GetThis(self);
! 		I cnt = 0;
  		t_atom at;
  		if(val >= 0) flext::SetInt(at,val);
--- 226,230 ----
  	else {
  		pyext *ext = GetThis(self);
! 		int cnt = 0;
  		t_atom at;
  		if(val >= 0) flext::SetInt(at,val);
***************
*** 256,268 ****
      FLEXT_ASSERT(PyTuple_Check(args));
  
! 	BL ok = false;
  	PyObject *self = PyTuple_GetItem(args,0); // borrowed ref
  	if(self && PyInstance_Check(self)) {
  		pyext *ext = GetThis(self);
  
! 		I sz = PySequence_Size(args);
  		PyObject *val;
  
!         BL tp = 
              sz == 2 && 
              PySequence_Check(
--- 256,268 ----
      FLEXT_ASSERT(PyTuple_Check(args));
  
! 	bool ok = false;
  	PyObject *self = PyTuple_GetItem(args,0); // borrowed ref
  	if(self && PyInstance_Check(self)) {
  		pyext *ext = GetThis(self);
  
! 		int sz = PySequence_Size(args);
  		PyObject *val;
  
!         bool tp = 
              sz == 2 && 
              PySequence_Check(

Index: pyargs.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pyargs.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** pyargs.cpp	10 Nov 2004 03:31:34 -0000	1.9
--- pyargs.cpp	9 Jan 2005 04:59:30 -0000	1.10
***************
*** 3,7 ****
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c)2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 22,26 ****
      }
      // these following should never happen
!     else if(flext::IsFloat(at)) return PyFloat_FromDouble((D)flext::GetFloat(at));
  	else if(flext::IsInt(at)) return PyInt_FromLong(flext::GetInt(at));
    
--- 22,26 ----
      }
      // 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));
    
***************
*** 28,32 ****
  }
  
! PyObject *py::MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,I inlet,BL withself)
  {
  	PyObject *pArgs;
--- 28,32 ----
  }
  
! PyObject *py::MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet,bool withself)
  {
  	PyObject *pArgs;
***************
*** 41,48 ****
  */
      {
! 	    BL any = IsAnything(s);
  	    pArgs = PyTuple_New(argc+(any?1:0)+(inlet >= 0?1:0));
  
! 	    I pix = 0;
  
  	    if(inlet >= 0) {
--- 41,48 ----
  */
      {
! 	    bool any = IsAnything(s);
  	    pArgs = PyTuple_New(argc+(any?1:0)+(inlet >= 0?1:0));
  
! 	    int pix = 0;
  
  	    if(inlet >= 0) {
***************
*** 53,57 ****
  	    }
  
! 	    I ix;
  	    PyObject *tmp;
  	    if(!withself || argc < (any?1:2)) tmp = pArgs,ix = pix;
--- 53,57 ----
  	    }
  
! 	    int ix;
  	    PyObject *tmp;
  	    if(!withself || argc < (any?1:2)) tmp = pArgs,ix = pix;
***************
*** 65,69 ****
  	    }
  
! 	    for(I i = 0; i < argc; ++i) {
  		    PyObject *pValue = MakePyAtom(argv[i]);
  		    if(!pValue) {
--- 65,69 ----
  	    }
  
! 	    for(int i = 0; i < argc; ++i) {
  		    PyObject *pValue = MakePyAtom(argv[i]);
  		    if(!pValue) {
***************
*** 96,101 ****
  	// analyze return value or tuple
  
! 	I rargc = 0;
! 	BL ok = true;
  	retval tp = nothing;
  
--- 96,101 ----
  	// analyze return value or tuple
  
! 	int rargc = 0;
! 	bool ok = true;
  	retval tp = nothing;
  
***************
*** 117,121 ****
  	ret = new AtomList(rargc);
  
! 	for(I ix = 0; ix < rargc; ++ix) {
  		PyObject *arg;
  		if(tp == sequ)
--- 117,121 ----
  	ret = new AtomList(rargc);
  
! 	for(int ix = 0; ix < rargc; ++ix) {
  		PyObject *arg;
  		if(tp == sequ)
***************
*** 126,130 ****
  		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],(F)PyFloat_AsDouble(arg));
  		else if(PyString_Check(arg)) SetString((*ret)[ix],PyString_AsString(arg));
  		else if(ix == 0 && self && PyInstance_Check(arg)) {
--- 126,130 ----
  		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(PyString_Check(arg)) SetString((*ret)[ix],PyString_AsString(arg));
  		else if(ix == 0 && self && PyInstance_Check(arg)) {
***************
*** 136,140 ****
  			PyObject *tp = PyObject_Type(arg);
  			PyObject *stp = tp?PyObject_Str(tp):NULL;
! 			C *tmp = "";
  			if(stp) tmp = PyString_AsString(stp);
  			post("py/pyext: Could not convert argument %s",tmp);
--- 136,140 ----
  			PyObject *tp = PyObject_Type(arg);
  			PyObject *stp = tp?PyObject_Str(tp):NULL;
! 			char *tmp = "";
  			if(stp) tmp = PyString_AsString(stp);
  			post("py/pyext: Could not convert argument %s",tmp);

Index: main.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/main.cpp,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** main.cpp	10 Nov 2004 03:31:34 -0000	1.18
--- main.cpp	9 Jan 2005 04:59:30 -0000	1.19
***************
*** 3,7 ****
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c)2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 56,66 ****
  
  
! V py::lib_setup()
  {
  	post("");
! 	post("py/pyext %s - python script objects, (C)2002-2004 Thomas Grill",PY__VERSION);
  #ifdef FLEXT_DEBUG
  	post("DEBUG version compiled on %s %s",__DATE__,__TIME__);
  #endif
      post("");
  
--- 56,71 ----
  
  
! void py::lib_setup()
  {
  	post("");
! 	post("--------------------------------------");
! 	post("py/pyext %s - python script objects",PY__VERSION);
! 	post("      (C)2002-2005 Thomas Grill");
!     post("         http://grrrr.org/ext");
  #ifdef FLEXT_DEBUG
+     post("");
  	post("DEBUG version compiled on %s %s",__DATE__,__TIME__);
  #endif
+ 	post("--------------------------------------");
      post("");
  
***************
*** 91,99 ****
  	module_dict = PyModule_GetDict(module_obj); // borrowed reference
  
! 	PyModule_AddStringConstant(module_obj,"__doc__",(C *)py_doc);
  
  	// redirect stdout
! 	PyObject* py_out = Py_InitModule("stdout", StdOut_Methods);
  	PySys_SetObject("stdout", py_out);
  
  #ifdef FLEXT_THREADS
--- 96,107 ----
  	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);
  
  #ifdef FLEXT_THREADS
***************
*** 117,137 ****
  py::py(): 
  	module(NULL),
! 	detach(false),shouldexit(false),thrcount(0),
  	stoptick(0)
  {
! 	PY_LOCK
  	Py_INCREF(module_obj);
! 	PY_UNLOCK
  
      FLEXT_ADDTIMER(stoptmr,tick);
  }
  
  py::~py()
  {
! 	if(thrcount) {
! 		shouldexit = true;
! 
  		// Wait for a certain time
! 		for(int i = 0; i < (PY_STOP_WAIT/PY_STOP_TICK) && thrcount; ++i) Sleep((F)(PY_STOP_TICK/1000.));
  
  		// Wait forever
--- 125,151 ----
  py::py(): 
  	module(NULL),
! 	detach(0),shouldexit(false),thrcount(0),
  	stoptick(0)
  {
! //    interpreter = PyInterpreterState_New();
! 
!     PyThreadState *state = PyLock();
  	Py_INCREF(module_obj);
! 	PyUnlock(state);
  
      FLEXT_ADDTIMER(stoptmr,tick);
+ 
+     // launch thread worker
+     FLEXT_CALLMETHOD(threadworker);
  }
  
  py::~py()
  {
!     shouldexit = true;
!     qucond.Signal();
!     
!     if(thrcount) {
  		// Wait for a certain time
! 		for(int i = 0; i < (PY_STOP_WAIT/PY_STOP_TICK) && thrcount; ++i) Sleep((float)(PY_STOP_TICK/1000.));
  
  		// Wait forever
***************
*** 142,145 ****
--- 156,165 ----
  		
     	Py_XDECREF(module_obj);
+ /*
+     PyEval_AcquireLock();
+     PyInterpreterState_Clear(interpreter);
+     PyInterpreterState_Delete(interpreter);
+     PyEval_ReleaseLock();
+ */
  }
  
***************
*** 148,152 ****
  {
      if(obj) {
!         PY_LOCK
      
          PyObject *pvar  = PyObject_Dir(obj);
--- 168,172 ----
  {
      if(obj) {
!         PyThreadState *state = PyLock();
      
          PyObject *pvar  = PyObject_Dir(obj);
***************
*** 163,167 ****
          }
  
!         PY_UNLOCK
      }
  }
--- 183,187 ----
          }
  
!         PyUnlock(state);
      }
  }
***************
*** 175,182 ****
  }
  
! V py::m__doc(PyObject *obj)
  {
      if(obj) {
!         PY_LOCK
  
  		PyObject *docf = PyDict_GetItemString(obj,"__doc__"); // borrowed!!!
--- 195,202 ----
  }
  
! void py::m__doc(PyObject *obj)
  {
      if(obj) {
!         PyThreadState *state = PyLock();
  
  		PyObject *docf = PyDict_GetItemString(obj,"__doc__"); // borrowed!!!
***************
*** 207,221 ****
  		}
  
!         PY_UNLOCK
  	}
  }
  
  
! V py::SetArgs(I argc,const t_atom *argv)
  {
  	// script arguments
! 	C **sargv = new C *[argc+1];
  	for(int i = 0; i <= argc; ++i) {
! 		sargv[i] = new C[256];
  		if(!i) 
  			strcpy(sargv[i],thisName());
--- 227,241 ----
  		}
  
!         PyUnlock(state);
  	}
  }
  
  
! void py::SetArgs(int argc,const t_atom *argv)
  {
  	// script arguments
! 	char **sargv = new char *[argc+1];
  	for(int i = 0; i <= argc; ++i) {
! 		sargv[i] = new char[256];
  		if(!i) 
  			strcpy(sargv[i],thisName());
***************
*** 231,239 ****
  }
  
! V py::ImportModule(const C *name)
  {
  	if(!name) return;
  
! 	module = PyImport_ImportModule((C *)name);  // increases module_obj ref count by one
  	if (!module) {
  
--- 251,259 ----
  }
  
! void py::ImportModule(const char *name)
  {
  	if(!name) return;
  
! 	module = PyImport_ImportModule((char *)name);  // increases module_obj ref count by one
  	if (!module) {
  
***************
*** 245,249 ****
  }
  
! V py::UnimportModule()
  {
  	if(!module) return;
--- 265,269 ----
  }
  
! void py::UnimportModule()
  {
  	if(!module) return;
***************
*** 261,265 ****
  }
  
! V py::ReloadModule()
  {
  	if(module) {
--- 281,285 ----
  }
  
! void py::ReloadModule()
  {
  	if(module) {
***************
*** 280,290 ****
  }
  
! V py::GetModulePath(const C *mod,C *dir,I len)
  {
  #if FLEXT_SYS == FLEXT_SYS_PD
  	// uarghh... pd doesn't show its path for extra modules
  
! 	C *name;
! 	I fd = open_via_path("",mod,".py",dir,&name,len,0);
  	if(fd > 0) close(fd);
  	else name = NULL;
--- 300,310 ----
  }
  
! void py::GetModulePath(const char *mod,char *dir,int len)
  {
  #if FLEXT_SYS == FLEXT_SYS_PD
  	// uarghh... pd doesn't show its path for extra modules
  
! 	char *name;
! 	int fd = open_via_path("",mod,".py",dir,&name,len,0);
  	if(fd > 0) close(fd);
  	else name = NULL;
***************
*** 296,303 ****
      short path;
      long type;
!     char smod[256];
      strcat(strcpy(smod,mod),".py");
!     if(!locatefile_extended(smod,&path,&type,&type,-1))
          path_topathname(path,NULL,dir);
      else 
          // not found
--- 316,338 ----
      short path;
      long type;
!     char smod[1024];
      strcat(strcpy(smod,mod),".py");
!     if(!locatefile_extended(smod,&path,&type,&type,-1)) {
! #if FLEXT_OS == FLEXT_OS_WIN
          path_topathname(path,NULL,dir);
+ #else
+         // convert pathname to unix style
+         path_topathname(path,NULL,smod);
+         char *colon = strchr(smod,':');
+         if(colon) {
+             *colon = 0;
+             strcpy(dir,"/Volumes/");
+             strcat(dir,smod);
+             strcat(dir,colon+1);
+         }
+         else
+             strcpy(dir,smod);
+ #endif
+     }
      else 
          // not found
***************
*** 308,312 ****
  }
  
! V py::AddToPath(const C *dir)
  {
  	if(dir && *dir) {
--- 343,347 ----
  }
  
! void py::AddToPath(const char *dir)
  {
  	if(dir && *dir) {
***************
*** 327,330 ****
--- 362,378 ----
  }
  
+ static const t_symbol *sym_response = flext::MakeSymbol("response");
+ 
+ void py::Respond(bool b) 
+ { 
+     if(respond) { 
+         t_atom a; 
+         SetBool(a,b); 
+         ToOutAnything(GetOutAttr(),sym_response,1,&a); 
+     } 
+ }
+ 
+ 
+ 
  static PyObject *output = NULL;
  
***************
*** 369,370 ****
--- 417,542 ----
      return Py_None;
  }
+ 
+ 
+ class work_data
+ {
+ public:
+     work_data(PyObject *f,PyObject *a): fun(f),args(a) {}
+     ~work_data() { Py_DECREF(fun); Py_DECREF(args); }
+ 
+     PyObject *fun,*args;
+ };
+ 
+ bool py::gencall(PyObject *pmeth,PyObject *pargs)
+ {
+ 	bool ret = false;
+ 
+     // Now call method
+     switch(detach) {
+         case 0:
+             ret = callpy(pmeth,pargs);
+         	Py_DECREF(pargs);
+         	Py_DECREF(pmeth);
+             break;
+         case 1:
+             // put call into queue
+             ret = qucall(pmeth,pargs);
+             break;
+         case 2:
+             // each call a new thread
+             if(!shouldexit) {
+ 			    ret = FLEXT_CALLMETHOD_X(work_wrapper,new work_data(pmeth,pargs));
+ 			    if(!ret) post("%s - Failed to launch thread!",thisName());
+ 		    }
+             break;
+         default:
+             FLEXT_ASSERT(false);
+     }
+     return ret;
+ }
+ 
+ void py::work_wrapper(void *data)
+ {
+     FLEXT_ASSERT(data);
+ 
+ 	++thrcount;
+ 
+     PyThreadState *state = PyLock();
+ 
+     // call worker
+ 	work_data *w = (work_data *)data;
+ 	callpy(w->fun,w->args);
+ 	delete w;
+ 
+     PyUnlock(state);
+ 
+     --thrcount;
+ }
+ 
+ bool py::qucall(PyObject *fun,PyObject *args)
+ {
+     if(qufifo.Push(fun,args)) {
+         qucond.Signal();
+         return true;
+     }
+     else
+         return false;
+ }
+ 
+ void py::threadworker()
+ {
+     PyObject *fun,*args;
+     PyThreadState *state;
+ 
+     while(!shouldexit) {
+         state = PyLock();
+         while(qufifo.Pop(fun,args)) {
+             callpy(fun,args);
+             Py_XDECREF(fun);
+             Py_XDECREF(args);
+         }
+         PyUnlock(state);
+         qucond.Wait();
+     }
+ 
+     state = PyLock();
+     // unref remaining Python objects
+     while(qufifo.Pop(fun,args)) {
+         Py_XDECREF(fun);
+         Py_XDECREF(args);
+     }
+     PyUnlock(state);
+ }
+ 
+ Fifo::~Fifo()
+ {
+     FifoEl *el = head;
+     while(el) {
+         FifoEl *n = el->nxt;
+         delete el;
+         el = n;
+     }
+ }
+ 
+ bool Fifo::Push(PyObject *f,PyObject *a)
+ {
+     FifoEl *el = new FifoEl;
+     el->fun = f;
+     el->args = a;
+     if(tail) tail->nxt = el;
+     else head = el;
+     tail = el;
+     return true;
+ }
+ 
+ bool Fifo::Pop(PyObject *&f,PyObject *&a)
+ {
+     if(!head) return false;
+     FifoEl *el = head;
+     head = el->nxt;
+     f = el->fun;
+     a = el->args;
+     if(tail == el) tail = NULL;
+     delete el;
+     return true;
+ }

Index: pyext.h
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** pyext.h	10 Nov 2004 03:31:34 -0000	1.17
--- pyext.h	9 Jan 2005 04:59:30 -0000	1.18
***************
*** 3,7 ****
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c)2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 20,24 ****
  
  public:
! 	pyext(I argc,const t_atom *argv);
  	~pyext();
  
--- 20,24 ----
  
  public:
! 	pyext(int argc,const t_atom *argv);
  	~pyext();
  
***************
*** 39,82 ****
  	static PyObject *pyext_isthreaded(PyObject *,PyObject *);
  
! 	I Inlets() const { return inlets; }
! 	I Outlets() const { return outlets; }
  
  protected:
! 	virtual BL m_method_(I n,const t_symbol *s,I argc,const t_atom *argv);
  
! 	BL work(I n,const t_symbol *s,I argc,const t_atom *argv); 
  
! 	V m_reload();
! 	V m_reload_(I argc,const t_atom *argv);
!     V ms_args(const AtomList &a) { m_reload_(a.Count(),a.Atoms()); }
!     V m_dir_() { m__dir(pyobj); }
!     V mg_dir_(AtomList &lst) { GetDir(pyobj,lst); }
!     V m_doc_() { m__doc(((PyInstanceObject *)pyobj)->in_class->cl_dict); }
! 	virtual V m_help();
  
! 	V m_get(const t_symbol *s);
! 	V m_set(I argc,const t_atom *argv);
  
  	const t_symbol *methname;
  	PyObject *pyobj;
! 	I inlets,outlets;
  
  private:
! 	static V Setup(t_classid);
  
  	static pyext *GetThis(PyObject *self);
  	void SetThis();
  
! 	V ClearBinding();
! 	BL MakeInstance();
! 	BL DoInit();
  
  	AtomList args;
  
! 	virtual V Reload();
  
  	static PyObject *class_obj,*class_dict;
  	static PyMethodDef attr_tbl[],meth_tbl[];
! 	static const C *pyext_doc;
  
  	// -------- bind stuff ------------------
--- 39,82 ----
  	static PyObject *pyext_isthreaded(PyObject *,PyObject *);
  
! 	int Inlets() const { return inlets; }
! 	int Outlets() const { return outlets; }
  
  protected:
! 	virtual bool m_method_(int n,const t_symbol *s,int argc,const t_atom *argv);
  
! 	bool work(int n,const t_symbol *s,int argc,const t_atom *argv); 
  
! 	void m_reload();
! 	void m_reload_(int argc,const t_atom *argv);
!     void ms_args(const AtomList &a) { m_reload_(a.Count(),a.Atoms()); }
!     void m_dir_() { m__dir(pyobj); }
!     void mg_dir_(AtomList &lst) { GetDir(pyobj,lst); }
!     void m_doc_() { m__doc(((PyInstanceObject *)pyobj)->in_class->cl_dict); }
! 	virtual void m_help();
  
! 	void m_get(const t_symbol *s);
! 	void m_set(int argc,const t_atom *argv);
  
  	const t_symbol *methname;
  	PyObject *pyobj;
! 	int inlets,outlets;
  
  private:
! 	static void Setup(t_classid);
  
  	static pyext *GetThis(PyObject *self);
  	void SetThis();
  
! 	void ClearBinding();
! 	bool MakeInstance();
! 	bool DoInit();
  
  	AtomList args;
  
! 	virtual void Reload();
  
  	static PyObject *class_obj,*class_dict;
  	static PyMethodDef attr_tbl[],meth_tbl[];
! 	static const char *pyext_doc;
  
  	// -------- bind stuff ------------------
***************
*** 86,107 ****
  	// ---------------------------
  
! 	PyObject *call(const C *meth,I inlet,const t_symbol *s,I argc,const t_atom *argv);
! 
! 	V work_wrapper(void *data); 
! 	BL callwork(I n,const t_symbol *s,I argc,const t_atom *argv); 
! 
! 	class work_data:
! 		public flext::AtomAnything
! 	{
! 	public:
! 		work_data(I _n,const t_symbol *_s,I _argc,const t_atom *_argv): n(_n),AtomAnything(_s,_argc,_argv) {}
! 		I n;
! 	};
  
! #ifdef FLEXT_THREADS
! 	FLEXT_THREAD_X(work_wrapper)
! #else
! 	FLEXT_CALLBACK_X(work_wrapper)
! #endif
  
  	PyThreadState *pythr;
--- 86,93 ----
  	// ---------------------------
  
! 	bool call(const char *meth,int inlet,const t_symbol *s,int argc,const t_atom *argv);
  
!     virtual bool callpy(PyObject *fun,PyObject *args);
!     static bool stcallpy(PyObject *fun,PyObject *args);
  
  	PyThreadState *pythr;

Index: modmeth.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/modmeth.cpp,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** modmeth.cpp	10 Nov 2004 03:31:34 -0000	1.12
--- modmeth.cpp	9 Jan 2005 04:59:30 -0000	1.13
***************
*** 3,7 ****
  py/pyext - python external object for PD and Max/MSP
  
! Copyright (c) 2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and Max/MSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 22,27 ****
  	{ "_samplerate", py::py_samplerate, METH_NOARGS,"Get system sample rate" },
  	{ "_blocksize", py::py_blocksize, METH_NOARGS,"Get system block size" },
- 	{ "_inchannels", py::py_inchannels, METH_NOARGS,"Get number of audio in channels" },
- 	{ "_outchannels", py::py_outchannels, METH_NOARGS,"Get number of audio out channels" },
  
  #if FLEXT_SYS == FLEXT_SYS_PD
--- 22,25 ----
***************
*** 33,38 ****
  };
  
! const C *py::py_doc =
! 	"py/pyext - python external object for PD and Max/MSP, (C)2002-2004 Thomas Grill\n"
  	"\n"
  	"This is the pyext module. Available function:\n"
--- 31,36 ----
  };
  
! const char *py::py_doc =
! 	"py/pyext - python external object for PD and Max/MSP, (C)2002-2005 Thomas Grill\n"
  	"\n"
  	"This is the pyext module. Available function:\n"
***************
*** 43,48 ****
  	"_samplerate(): Get system sample rate\n"
  	"_blocksize(): Get current blocksize\n"
- 	"_inchannels(): Get number of audio in channels\n"
- 	"_outchannels(): Get number of audio out channels\n"
      "_getvalue(name): Get value of a 'value' object\n"
      "_setvalue(name,float): Set value of a 'value' object\n"
--- 41,44 ----
***************
*** 51,55 ****
  
  
! V py::tick(V *)
  {
  	Lock();
--- 47,51 ----
  
  
! void py::tick(void *)
  {
  	Lock();
***************
*** 74,86 ****
  }
  
! V py::m_stop(int argc,const t_atom *argv)
  {
  	if(thrcount) {
  		Lock();
  
! 		I wait = PY_STOP_WAIT;
  		if(argc >= 1 && CanbeInt(argv[0])) wait = GetAInt(argv[0]);
  
! 		I ticks = wait/PY_STOP_TICK;
  		if(stoptick) {
  			// already stopping
--- 70,82 ----
  }
  
! void py::m_stop(int argc,const t_atom *argv)
  {
  	if(thrcount) {
  		Lock();
  
! 		int wait = PY_STOP_WAIT;
  		if(argc >= 1 && CanbeInt(argv[0])) wait = GetAInt(argv[0]);
  
! 		int ticks = wait/PY_STOP_TICK;
  		if(stoptick) {
  			// already stopping
***************
*** 107,136 ****
  }
  
- PyObject *py::py_inchannels(PyObject *self,PyObject *args)
- {
- #if FLEXT_SYS == FLEXT_SYS_PD
- 	I ch = sys_get_inchannels();
- #elif FLEXT_SYS == FLEXT_SYS_MAX
- 	I ch = sys_getch(); // not working
- #else
- #pragma message("Not implemented!")
- 	ch = 0;
- #endif
- 	return PyLong_FromLong(ch);
- }
- 
- PyObject *py::py_outchannels(PyObject *self,PyObject *args)
- {
- #if FLEXT_SYS == FLEXT_SYS_PD
- 	I ch = sys_get_outchannels();
- #elif FLEXT_SYS == FLEXT_SYS_MAX
- 	I ch = sys_getch(); // not working
- #else
- #pragma message("Not implemented!")
- 	ch = 0;
- #endif
- 	return PyLong_FromLong(ch);
- }
- 
  PyObject *py::py_send(PyObject *,PyObject *args)
  {
--- 103,106 ----

Index: bound.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/bound.cpp,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** bound.cpp	10 Nov 2004 03:31:34 -0000	1.12
--- bound.cpp	9 Jan 2005 04:59:30 -0000	1.13
***************
*** 3,7 ****
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c) 2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 22,30 ****
  };
  
! bool pyext::boundmeth(flext_base *,t_symbol *sym,int argc,t_atom *argv,void *data)
  {
      bounddata *obj = (bounddata *)data;
  
! 	PY_LOCK
  
  	PyObject *args = MakePyArgs(sym,argc,argv,-1,obj->self != NULL);
--- 22,31 ----
  };
  
! bool pyext::boundmeth(flext_base *th,t_symbol *sym,int argc,t_atom *argv,void *data)
  {
      bounddata *obj = (bounddata *)data;
+     py *pyth = static_cast<py *>(th);
  
! 	PyThreadState *state = pyth->PyLock();
  
  	PyObject *args = MakePyArgs(sym,argc,argv,-1,obj->self != NULL);
***************
*** 41,45 ****
      Py_XDECREF(args);
  
! 	PY_UNLOCK
      return true;
  }
--- 42,46 ----
      Py_XDECREF(args);
  
! 	pyth->PyUnlock(state);
      return true;
  }
***************
*** 48,52 ****
  {
      PyObject *self,*meth;
! 	C *name;
      if(!PyArg_ParseTuple(args, "OsO:pyext_bind", &self,&name,&meth))
  		post("py/pyext - Wrong arguments!");
--- 49,53 ----
  {
      PyObject *self,*meth;
! 	char *name;
      if(!PyArg_ParseTuple(args, "OsO:pyext_bind", &self,&name,&meth))
  		post("py/pyext - Wrong arguments!");
***************
*** 92,96 ****
  {
      PyObject *self,*meth;
! 	C *name;
      if(!PyArg_ParseTuple(args, "OsO:pyext_bind", &self,&name,&meth))
  		post("py/pyext - Wrong arguments!");
--- 93,97 ----
  {
      PyObject *self,*meth;
! 	char *name;
      if(!PyArg_ParseTuple(args, "OsO:pyext_bind", &self,&name,&meth))
  		post("py/pyext - Wrong arguments!");
***************
*** 128,132 ****
  
  
! V pyext::ClearBinding()
  {
      // in case the object couldn't be constructed...
--- 129,133 ----
  
  
! void pyext::ClearBinding()
  {
      // in case the object couldn't be constructed...

Index: register.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/register.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** register.cpp	10 Nov 2004 03:31:34 -0000	1.4
--- register.cpp	9 Jan 2005 04:59:30 -0000	1.5
***************
*** 3,7 ****
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c) 2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python external object for PD and MaxMSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 12,27 ****
  
  
! V py::Register(const C *regnm)
  {
  	if(module) {
  		// add this to module registry
  
! 		PyObject *reg = PyDict_GetItemString(dict,(C *)regnm); // borrowed!!!
  		PyObject *add = Py_BuildValue("[i]",(long)this);
  		if(!reg || !PyList_Check(reg)) {
! 			if(PyDict_SetItemString(dict,(C *)regnm,add)) {
  				post("%s - Could not set registry",thisName());
  			}
- 			// Py_XDECREF(reg);
  		}
  		else {
--- 12,26 ----
  
  
! void py::Register(const char *regnm)
  {
  	if(module) {
  		// add this to module registry
  
! 		PyObject *reg = PyDict_GetItemString(dict,(char *)regnm); // borrowed!!!
  		PyObject *add = Py_BuildValue("[i]",(long)this);
  		if(!reg || !PyList_Check(reg)) {
! 			if(PyDict_SetItemString(dict,(char *)regnm,add)) {
  				post("%s - Could not set registry",thisName());
  			}
  		}
  		else {
***************
*** 29,48 ****
  		}
  	}
- 
  }
  
! V py::Unregister(const C *regnm)
  {
  	if(module) {
  		// remove this from module registry
  		
! 		PyObject *reg = PyDict_GetItemString(dict,(C *)regnm); // borrowed!!!
  		PyObject *add = Py_BuildValue("i",(int)this);
  		if(!reg || !PySequence_Check(reg)) 
! 			post("%s - Registry not found!?",thisName());
  		else {
! 			I ix = PySequence_Index(reg,add);
  			if(ix < 0) {
! 				post("%s - This object not found in registry?!",thisName());
  			}
  			else {	
--- 28,46 ----
  		}
  	}
  }
  
! void py::Unregister(const char *regnm)
  {
  	if(module) {
  		// remove this from module registry
  		
! 		PyObject *reg = PyDict_GetItemString(dict,(char *)regnm); // borrowed!!!
  		PyObject *add = Py_BuildValue("i",(int)this);
  		if(!reg || !PySequence_Check(reg)) 
! 			post("%s - Internal error: Registry not found!?",thisName());
  		else {
! 			int ix = PySequence_Index(reg,add);
  			if(ix < 0) {
!                 post("%s - Internal error: object not found in registry?!",thisName());
  			}
  			else {	
***************
*** 52,73 ****
  		Py_DECREF(add);
  	}
- 
  }
  
! V py::Reregister(const C *regnm)
  {
  	if(module) {
  		// remove this from module registry
  		
! 		PyObject *reg = PyDict_GetItemString(dict,(C *)regnm); // borrowed!!!
  
  		if(!reg || !PySequence_Check(reg)) 
! 			post("%s - Registry not found!?",thisName());
  		else {
! 			I cnt = PySequence_Size(reg);
! 			for(I i = 0; i < cnt; ++i) {
  				PyObject *it = PySequence_GetItem(reg,i); // new reference
  				if(!it || !PyInt_Check(it)) {
! 					post("%s - Corrupt registry?!",thisName());
  				}
  				else {
--- 50,70 ----
  		Py_DECREF(add);
  	}
  }
  
! void py::Reregister(const char *regnm)
  {
  	if(module) {
  		// remove this from module registry
  		
! 		PyObject *reg = PyDict_GetItemString(dict,(char *)regnm); // borrowed!!!
  
  		if(!reg || !PySequence_Check(reg)) 
! 			post("%s - Internal error: Registry not found!?",thisName());
  		else {
! 			int cnt = PySequence_Size(reg);
! 			for(int i = 0; i < cnt; ++i) {
  				PyObject *it = PySequence_GetItem(reg,i); // new reference
  				if(!it || !PyInt_Check(it)) {
!                     post("%s - Internal error: Corrupt registry?!",thisName());
  				}
  				else {
***************
*** 82,88 ****
  		}
  	}
- 
  }
- 
- 
- 
--- 79,81 ----

Index: main.h
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/main.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -C2 -d -r1.25 -r1.26
*** main.h	17 Dec 2004 05:04:29 -0000	1.25
--- main.h	9 Jan 2005 04:59:30 -0000	1.26
***************
*** 3,7 ****
  py/pyext - python script object for PD and MaxMSP
  
! Copyright (c)2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python script object for PD and MaxMSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 25,30 ****
  #endif
  
! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 408)
! #error You need at least flext version 0.4.8
  #endif
  
--- 25,30 ----
  #endif
  
! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500)
! #error You need at least flext version 0.5.0
  #endif
  
***************
*** 39,52 ****
  
  
  
! #define I int
! #define C char
! #define V void
! #define BL bool
! #define F float
! #define D double
  
  
! #include "main.h"
  
  class py:
--- 39,64 ----
  
  
+ class Fifo
+ {
+ protected:
+     struct FifoEl {
+         PyObject *fun;
+         PyObject *args;
+         FifoEl *nxt;
+     };
+ public:
+     Fifo(): head(NULL),tail(NULL) {}
+     ~Fifo();
  
!     bool Push(PyObject *f,PyObject *a);
!     bool Pop(PyObject *&f,PyObject *&a);
!     
! protected:
!     FifoEl *head,*tail;
! };
  
  
! PyThreadState *FindThreadState();
! void FreeThreadState();
  
  class py:
***************
*** 58,98 ****
  	py();
  	~py();
! 	static V lib_setup();
  
! 	static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,I inlet = -1,BL withself = false);
  	static AtomList *GetPyArgs(PyObject *pValue,PyObject **self = NULL);
  
  protected:
  
!     V m__dir(PyObject *obj);
! 	V m__doc(PyObject *obj);
  
!     V m_dir() { m__dir(module); }
!     V mg_dir(AtomList &lst) { m__dir(module); }
!     V m_doc() { m__doc(dict); }
  
  	PyObject *module,*dict; // inherited user class module and associated dictionary
  
! 	static const C *py_doc;
  
!     V GetDir(PyObject *obj,AtomList &lst);
  
! 	V GetModulePath(const C *mod,C *dir,I len);
! 	V AddToPath(const C *dir);
! 	V SetArgs(I argc,const t_atom *argv);
! 	V ImportModule(const C *name);
! 	V UnimportModule();
! 	V ReloadModule();
  
! 	V Register(const C *reg);
! 	V Unregister(const C *reg);
! 	V Reregister(const C *reg);
! 	virtual V Reload() = 0;
  
!     V Respond(BL b) { if(respond) { t_atom a[1]; SetBool(a[0],b); ToOutAnything(GetOutAttr(),MakeSymbol("response"),1,a); } }
  
! 	static BL IsAnything(const t_symbol *s) { return s && s != sym_bang && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; }
  
! 	enum retval { nothing,atom,sequ /*,tuple,list*/ };
  
  	// --- module stuff -----
--- 70,110 ----
  	py();
  	~py();
! 	static void lib_setup();
  
! 	static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1,bool withself = false);
  	static AtomList *GetPyArgs(PyObject *pValue,PyObject **self = NULL);
  
  protected:
  
!     void m__dir(PyObject *obj);
! 	void m__doc(PyObject *obj);
  
!     void m_dir() { m__dir(module); }
!     void mg_dir(AtomList &lst) { m__dir(module); }
!     void m_doc() { m__doc(dict); }
  
  	PyObject *module,*dict; // inherited user class module and associated dictionary
  
! 	static const char *py_doc;
  
!     void GetDir(PyObject *obj,AtomList &lst);
  
! 	void GetModulePath(const char *mod,char *dir,int len);
! 	void AddToPath(const char *dir);
! 	void SetArgs(int argc,const t_atom *argv);
! 	void ImportModule(const char *name);
! 	void UnimportModule();
! 	void ReloadModule();
  
! 	void Register(const char *reg);
! 	void Unregister(const char *reg);
! 	void Reregister(const char *reg);
! 	virtual void Reload() = 0;
  
!     void Respond(bool b);
  
! 	static bool IsAnything(const t_symbol *s) { return s && s != sym_bang && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; }
  
! 	enum retval { nothing,atom,sequ };
  
  	// --- module stuff -----
***************
*** 109,114 ****
  	static PyObject *py_samplerate(PyObject *,PyObject *args);
  	static PyObject *py_blocksize(PyObject *,PyObject *args);
! 	static PyObject *py_inchannels(PyObject *,PyObject *args);
! 	static PyObject *py_outchannels(PyObject *,PyObject *args);
  #if FLEXT_SYS == FLEXT_SYS_PD
  	static PyObject *py_getvalue(PyObject *,PyObject *args);
--- 121,125 ----
  	static PyObject *py_samplerate(PyObject *,PyObject *args);
  	static PyObject *py_blocksize(PyObject *,PyObject *args);
! 
  #if FLEXT_SYS == FLEXT_SYS_PD
  	static PyObject *py_getvalue(PyObject *,PyObject *args);
***************
*** 118,129 ****
  	// ----thread stuff ------------
  
! 	virtual V m_stop(int argc,const t_atom *argv);
  
! 	BL detach,shouldexit,respond;
! 	I thrcount;
! 	I stoptick;
      Timer stoptmr;
  
! 	V tick(V *);
  
  public:
--- 129,160 ----
  	// ----thread stuff ------------
  
! 	virtual void m_stop(int argc,const t_atom *argv);
  
! 	bool shouldexit,respond;
! 	int thrcount;
! 	int stoptick;
      Timer stoptmr;
+     int detach;
  
! 	void tick(void *);
!     
!     bool gencall(PyObject *fun,PyObject *args);
!     virtual bool callpy(PyObject *fun,PyObject *args) = 0;
! 
! private:
! //    PyInterpreterState *interpreter;
! 
!     bool qucall(PyObject *fun,PyObject *args);
!     void threadworker();
!     Fifo qufifo;
!     ThrCond qucond;
! 
! 	void work_wrapper(void *data); 
! 
! #ifdef FLEXT_THREADS
! 	FLEXT_THREAD_X(work_wrapper)
! #else
! 	FLEXT_CALLBACK_X(work_wrapper)
! #endif
  
  public:
***************
*** 131,139 ****
  #ifdef FLEXT_THREADS
  	ThrMutex mutex;
! 	inline V Lock() { mutex.Unlock(); }
! 	inline V Unlock() { mutex.Unlock(); }
  #else
! 	inline V Lock() {}
! 	inline V Unlock() {}
  #endif
  
--- 162,185 ----
  #ifdef FLEXT_THREADS
  	ThrMutex mutex;
! 	inline void Lock() { mutex.Unlock(); }
! 	inline void Unlock() { mutex.Unlock(); }
! 
! 	inline PyThreadState *PyLock() 
!     { 
!         PyEval_AcquireLock();
! 	    return PyThreadState_Swap(FindThreadState());
!     }
! 
! 	inline void PyUnlock(PyThreadState *st) 
!     {
!         PyThreadState_Swap(st);
!         PyEval_ReleaseLock();
!     }
  #else
! 	inline void Lock() {}
! 	inline void Unlock() {}
! 
! 	inline PyThreadState *PyLock() { return NULL; }
! 	inline void PyUnlock(PyThreadState *st) {}
  #endif
  
***************
*** 143,147 ****
  	// callbacks
  
! 	FLEXT_ATTRVAR_B(detach)
  	FLEXT_ATTRVAR_B(respond)
  	FLEXT_CALLBACK_V(m_stop)
--- 189,193 ----
  	// callbacks
  
! 	FLEXT_ATTRVAR_I(detach)
  	FLEXT_ATTRVAR_B(respond)
  	FLEXT_CALLBACK_V(m_stop)
***************
*** 150,175 ****
  	FLEXT_CALLBACK(m_doc)
      FLEXT_CALLBACK_T(tick)
- };
  
! #ifdef FLEXT_THREADS
! 
! PyThreadState *FindThreadState();
! void FreeThreadState();
! 
! #define PY_LOCK \
! 	{ \
!     PyEval_AcquireLock(); \
! 	PyThreadState *__st = FindThreadState(); \
! 	PyThreadState *__oldst = PyThreadState_Swap(__st);
! 
! #define PY_UNLOCK \
!     PyThreadState_Swap(__oldst); \
!     PyEval_ReleaseLock(); \
!     }
! 
! #else
! #define PY_LOCK 
! #define PY_UNLOCK 
! #endif
  
  #endif
--- 196,202 ----
  	FLEXT_CALLBACK(m_doc)
      FLEXT_CALLBACK_T(tick)
  
!     FLEXT_THREAD(threadworker)
! };
  
  #endif

Index: pyext.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -C2 -d -r1.22 -r1.23
*** pyext.cpp	10 Nov 2004 03:31:34 -0000	1.22
--- pyext.cpp	9 Jan 2005 04:59:30 -0000	1.23
***************
*** 3,7 ****
  py/pyext - python script object for PD and Max/MSP
  
! Copyright (c)2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python script object for PD and Max/MSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 14,20 ****
  FLEXT_LIB_V("pyext pyext. pyx pyx.",pyext)
  
! V pyext::Setup(t_classid c)
  {
! 	FLEXT_CADDMETHOD_(c,0,"reload.",m_reload);
  	FLEXT_CADDMETHOD_(c,0,"reload",m_reload_);
  	FLEXT_CADDMETHOD_(c,0,"dir",m_dir);
--- 14,25 ----
  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,"reload.",m_reload);
  	FLEXT_CADDMETHOD_(c,0,"reload",m_reload_);
  	FLEXT_CADDMETHOD_(c,0,"dir",m_dir);
***************
*** 36,40 ****
    	FLEXT_CADDATTR_VAR1(c,"respond",respond);
  
- 
  	// ----------------------------------------------------
  
--- 41,44 ----
***************
*** 113,117 ****
  PyObject *pyext::class_dict = NULL;
  
! pyext::pyext(I argc,const t_atom *argv):
  	pyobj(NULL),pythr(NULL),
  	inlets(-1),outlets(-1),
--- 117,121 ----
  PyObject *pyext::class_dict = NULL;
  
! pyext::pyext(int argc,const t_atom *argv):
  	pyobj(NULL),pythr(NULL),
  	inlets(-1),outlets(-1),
***************
*** 128,132 ****
      const t_atom *clname = NULL;
  
!     PY_LOCK
  
  	// init script module
--- 132,136 ----
      const t_atom *clname = NULL;
  
!     PyThreadState *state = PyLock();
  
  	// init script module
***************
*** 239,243 ****
          inlets = outlets = 0;
  
! 	PY_UNLOCK
  	
      if(inlets < 0 || outlets < 0)
--- 243,247 ----
          inlets = outlets = 0;
  
! 	PyUnlock(state);
  	
      if(inlets < 0 || outlets < 0)
***************
*** 254,258 ****
  pyext::~pyext()
  {
! 	PY_LOCK
  
  	ClearBinding();
--- 258,262 ----
  pyext::~pyext()
  {
! 	PyThreadState *state = PyLock();
  
  	ClearBinding();
***************
*** 266,273 ****
  	UnimportModule();
  
! 	PY_UNLOCK
  }
  
! BL pyext::DoInit()
  {
      SetThis();
--- 270,277 ----
  	UnimportModule();
  
! 	PyUnlock(state);
  }
  
! bool pyext::DoInit()
  {
      SetThis();
***************
*** 294,303 ****
  }
  
! BL pyext::MakeInstance()
  {
  	// pyobj should already have been decref'd / cleared before getting here!!
  	
  	if(module && methname) {
! 		PyObject *pref = PyObject_GetAttrString(module,const_cast<C *>(GetString(methname)));  
  		if(!pref) 
  			PyErr_Print();
--- 298,307 ----
  }
  
! bool pyext::MakeInstance()
  {
  	// pyobj should already have been decref'd / cleared before getting here!!
  	
  	if(module && methname) {
! 		PyObject *pref = PyObject_GetAttrString(module,const_cast<char *>(GetString(methname)));  
  		if(!pref) 
  			PyErr_Print();
***************
*** 320,324 ****
  }
  
! V pyext::Reload()
  {
  	ClearBinding();
--- 324,328 ----
  }
  
! void pyext::Reload()
  {
  	ClearBinding();
***************
*** 334,340 ****
  
  
! V pyext::m_reload()
  {
! 	PY_LOCK
  
  	Unregister("_pyext"); // self
--- 338,344 ----
  
  
! void pyext::m_reload()
  {
! 	PyThreadState *state = PyLock();
  
  	Unregister("_pyext"); // self
***************
*** 347,354 ****
      SetThis();
  
! 	PY_UNLOCK
  }
  
! V pyext::m_reload_(I argc,const t_atom *argv)
  {
  	args(argc,argv);
--- 351,358 ----
      SetThis();
  
! 	PyUnlock(state);
  }
  
! void pyext::m_reload_(int argc,const t_atom *argv)
  {
  	args(argc,argv);
***************
*** 358,362 ****
  void pyext::m_get(const t_symbol *s)
  {
!     PY_LOCK
  
  	PyObject *pvar  = PyObject_GetAttrString(pyobj,const_cast<char *>(GetString(s))); /* fetch bound method */
--- 362,366 ----
  void pyext::m_get(const t_symbol *s)
  {
!     PyThreadState *state = PyLock();
  
  	PyObject *pvar  = PyObject_GetAttrString(pyobj,const_cast<char *>(GetString(s))); /* fetch bound method */
***************
*** 369,373 ****
          if(lst) {
              // dump value to attribute outlet
!             AtomAnything out("get",lst->Count()+1);
              SetSymbol(out[0],s);
              out.Set(lst->Count(),lst->Atoms(),1);
--- 373,377 ----
          if(lst) {
              // dump value to attribute outlet
!             AtomAnything out(sym_get,lst->Count()+1);
              SetSymbol(out[0],s);
              out.Set(lst->Count(),lst->Atoms(),1);
***************
*** 381,390 ****
      }
  
!     PY_UNLOCK
  }
  
  void pyext::m_set(int argc,const t_atom *argv)
  {
!     PY_LOCK
  
      if(argc < 2 || !IsString(argv[0]))
--- 385,394 ----
      }
  
!     PyUnlock(state);
  }
  
  void pyext::m_set(int argc,const t_atom *argv)
  {
!     PyThreadState *state = PyLock();
  
      if(argc < 2 || !IsString(argv[0]))
***************
*** 418,430 ****
      }
  
!     PY_UNLOCK
  }
  
  
! BL pyext::m_method_(I n,const t_symbol *s,I argc,const t_atom *argv)
  {
!     BL ret = false;
  	if(pyobj && n >= 1)
! 		ret = callwork(n,s,argc,argv);
      else
  		post("%s - no method for type '%s' into inlet %i",thisName(),GetString(s),n);
--- 422,434 ----
      }
  
!     PyUnlock(state);
  }
  
  
! bool pyext::m_method_(int n,const t_symbol *s,int argc,const t_atom *argv)
  {
!     bool ret = false;
  	if(pyobj && n >= 1)
! 		ret = work(n,s,argc,argv);
      else
  		post("%s - no method for type '%s' into inlet %i",thisName(),GetString(s),n);
***************
*** 433,440 ****
  
  
! V pyext::m_help()
  {
  	post("");
! 	post("%s %s - python class object, (C)2002-2004 Thomas Grill",thisName(),PY__VERSION);
  #ifdef FLEXT_DEBUG
  	post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
--- 437,444 ----
  
  
! void pyext::m_help()
  {
  	post("");
! 	post("%s %s - python class object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION);
  #ifdef FLEXT_DEBUG
  	post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
***************
*** 461,469 ****
  }
  
! PyObject *pyext::call(const C *meth,I inlet,const t_symbol *s,I argc,const t_atom *argv) 
  {
! 	PyObject *ret = NULL;
  
! 	PyObject *pmeth  = PyObject_GetAttrString(pyobj,const_cast<char *>(meth)); /* fetch bound method */
  	if(pmeth == NULL) {
  		PyErr_Clear(); // no method found
--- 465,489 ----
  }
  
! bool pyext::callpy(PyObject *fun,PyObject *args)
  {
!     PyObject *ret = PyObject_Call(fun,args,NULL);
!     if(ret == NULL) {
!         // function not found resp. arguments not matching
!         PyErr_Print();
!         return false;
!     }
!     else {
! 		if(!PyObject_Not(ret)) post("pyext - returned value is ignored");
! 		Py_DECREF(ret);
!         return true;
!     }
! } 
  
! 
! 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<char *>(meth)); /* fetch bound method */
  	if(pmeth == NULL) {
  		PyErr_Clear(); // no method found
***************
*** 471,555 ****
  	else {
  		PyObject *pargs = MakePyArgs(s,argc,argv,inlet?inlet:-1,true);
! 		if(!pargs)
  			PyErr_Print();
! 		else {
! 			ret = PyEval_CallObject(pmeth, pargs); 
! 			if (ret == NULL) // function not found resp. arguments not matching
! 				PyErr_Print();
! 
! 			Py_DECREF(pargs);
! 		}
! 		Py_DECREF(pmeth);
! 	}
! 
! 	return ret;
! }
! 
! V pyext::work_wrapper(V *data)
! {
! 	++thrcount;
! #ifdef FLEXT_DEBUG
! 	if(!data) 
! 		post("%s - no data!",thisName());
! 	else
! #endif
! 	{
! #ifdef FLEXT_THREADS
!         // --- make new Python thread ---
!         // get the global lock
!         PyEval_AcquireLock();
!         // create a thread state object for this thread
!         PyThreadState *newthr = FindThreadState();
!         // free the lock
!         PyEval_ReleaseLock();
! #endif
!         {
!             // call worker
! 		    work_data *w = (work_data *)data;
! 		    work(w->n,w->Header(),w->Count(),w->Atoms());
! 		    delete w;
          }
! 
! #ifdef FLEXT_THREADS
!         // --- delete Python thread ---
!         // grab the lock
!         PyEval_AcquireLock();
!         // swap my thread state out of the interpreter
!         PyThreadState_Swap(NULL);
!         // delete mapped thread state
!         FreeThreadState();
!         // release the lock
!         PyEval_ReleaseLock();
!         // -----------------------------
! #endif
! 	}
! 	--thrcount;
! }
! 
! BL pyext::callwork(I n,const t_symbol *s,I argc,const t_atom *argv)
! {
!     BL ret = true,ok = false;
!     if(detach) {
! 		if(shouldexit)
! 			post("%s - Stopping.... new threads can't be launched now!",thisName());
! 		else {
! 			ret = FLEXT_CALLMETHOD_X(work_wrapper,new work_data(n,s,argc,argv));
! 			if(!ret) post("%s - Failed to launch thread!",thisName());
! 		}
  	}
!     else
! 		ret = ok = work(n,s,argc,argv);
!     Respond(ok);
!     return ret;
  }
  
! BL pyext::work(I n,const t_symbol *s,I argc,const t_atom *argv)
  {
! 	BL retv = false;
  
! 	PY_LOCK
  
! 	PyObject *ret = NULL;
! 	char *str = new char[strlen(GetString(s))+10];
  
  	{
--- 491,512 ----
  	else {
  		PyObject *pargs = MakePyArgs(s,argc,argv,inlet?inlet:-1,true);
!         if(!pargs) {
  			PyErr_Print();
!     		Py_DECREF(pmeth);
          }
! 		else 
!             ret = gencall(pmeth,pargs);
  	}
! 	return ret;
  }
  
! bool pyext::work(int n,const t_symbol *s,int argc,const t_atom *argv)
  {
! 	bool ret = false;
  
!     PyThreadState *state = PyLock();
  
!     // should be enough...
! 	char str[256];
  
  	{
***************
*** 564,568 ****
  		if(s == sym_bang && !argc) {
  			t_atom argv;
! 			SetString(argv,"");
  			ret = call(str,0,s,1,&argv);
  		}
--- 521,525 ----
  		if(s == sym_bang && !argc) {
  			t_atom argv;
! 			SetSymbol(argv,sym__);
  			ret = call(str,0,s,1,&argv);
  		}
***************
*** 577,588 ****
  	if(!ret) {
  		// try anything at any inlet
! 		strcpy(str,"_anything_");
  		if(s == sym_bang && !argc) {
  			t_atom argv;
! 			SetString(argv,"");
! 			ret = call(str,n,s,1,&argv);
  		}
  		else
! 			ret = call(str,n,s,argc,argv);
  	}
  
--- 534,545 ----
  	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);
  	}
  
***************
*** 591,604 ****
  		post("%s - no matching method found for '%s' into inlet %i",thisName(),GetString(s),n);
  
! 	if(str) delete[] str;
! 
! 	if(ret) {
! 		if(!PyObject_Not(ret)) post("%s - returned value is ignored",thisName());
! 		Py_DECREF(ret);
! 		retv = true;
! 	}
! 
! 	PY_UNLOCK
  
! 	return retv;
  }
--- 548,554 ----
  		post("%s - no matching method found for '%s' into inlet %i",thisName(),GetString(s),n);
  
! 	PyUnlock(state);
  
!     Respond(ret);
! 	return ret;
  }

Index: py.cpp
===================================================================
RCS file: /cvsroot/pure-data/externals/grill/py/source/py.cpp,v
retrieving revision 1.15
retrieving revision 1.16
diff -C2 -d -r1.15 -r1.16
*** py.cpp	10 Nov 2004 03:31:34 -0000	1.15
--- py.cpp	9 Jan 2005 04:59:30 -0000	1.16
***************
*** 3,7 ****
  py/pyext - python script object for PD and Max/MSP
  
! Copyright (c)2002-2004 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
--- 3,7 ----
  py/pyext - python script object for PD and Max/MSP
  
! Copyright (c)2002-2005 Thomas Grill (gr at grrrr.org)
  For information on usage and redistribution, and for a DISCLAIMER OF ALL
  WARRANTIES, see the file, "license.txt," in this distribution.  
***************
*** 18,55 ****
  
  public:
! 	pyobj(I argc,const t_atom *argv);
  	~pyobj();
  
  protected:
! 	BL m_method_(I n,const t_symbol *s,I argc,const t_atom *argv);
  
! 	BL work(const t_symbol *s,I argc,const t_atom *argv); 
  
! 	V m_bang() { callwork(sym_bang,0,NULL); }
! 	V m_reload();
! 	V m_reload_(I argc,const t_atom *argv);
! 	V m_set(I argc,const t_atom *argv);
!     V m_dir_() { m__dir(function); }
!     V m_doc_() { m__doc(function); }
  
! 	virtual V m_help();
  
  	// methods for python arguments
! 	V callwork(const t_symbol *s,I argc,const t_atom *argv);
  	
! 	V m_py_list(I argc,const t_atom *argv) { callwork(sym_list,argc,argv); }
! 	V m_py_float(I argc,const t_atom *argv) { callwork(sym_float,argc,argv); }
! 	V m_py_int(I argc,const t_atom *argv) { callwork(sym_int,argc,argv); }
! 	V m_py_any(const t_symbol *s,I argc,const t_atom *argv) { callwork(s,argc,argv); }
  
  	const t_symbol *funname;
  	PyObject *function;
  
! 	virtual V Reload();
  
! 	V SetFunction(const C *func);
! 	V ResetFunction();
  
  private:
  	static void Setup(t_classid c);
  
--- 18,58 ----
  
  public:
! 	pyobj(int argc,const t_atom *argv);
  	~pyobj();
  
  protected:
! 	bool m_method_(int n,const t_symbol *s,int argc,const t_atom *argv);
  
! 	bool work(const t_symbol *s,int argc,const t_atom *argv); 
  
! 	void m_bang() { callwork(sym_bang,0,NULL); }
! 	void m_reload();
! 	void m_reload_(int argc,const t_atom *argv);
! 	void m_set(int argc,const t_atom *argv);
!     void m_dir_() { m__dir(function); }
!     void m_doc_() { m__doc(function); }
  
! 	virtual void m_help();
  
  	// methods for python arguments
! 	void callwork(const t_symbol *s,int argc,const t_atom *argv);
  	
! 	void m_py_list(int argc,const t_atom *argv) { callwork(sym_list,argc,argv); }
! 	void m_py_float(int argc,const t_atom *argv) { callwork(sym_float,argc,argv); }
! 	void m_py_int(int argc,const t_atom *argv) { callwork(sym_int,argc,argv); }
! 	void m_py_any(const t_symbol *s,int argc,const t_atom *argv) { callwork(s,argc,argv); }
  
  	const t_symbol *funname;
  	PyObject *function;
  
! 	virtual void Reload();
  
! 	void SetFunction(const char *func);
! 	void ResetFunction();
  
  private:
+ 
+     virtual bool callpy(PyObject *fun,PyObject *args);
+ 
  	static void Setup(t_classid c);
  
***************
*** 99,106 ****
  }
  
! pyobj::pyobj(I argc,const t_atom *argv):
  	function(NULL),funname(NULL)
  { 
! 	PY_LOCK
  
  	AddInAnything(2);  
--- 102,109 ----
  }
  
! pyobj::pyobj(int argc,const t_atom *argv):
  	function(NULL),funname(NULL)
  { 
! 	PyThreadState *state = PyLock();
  
  	AddInAnything(2);  
***************
*** 117,121 ****
  			post("%s - script name argument is invalid",thisName());
          else {
! 		    C dir[1024];
  		    GetModulePath(GetString(argv[0]),dir,sizeof(dir));
  		    // set script path
--- 120,124 ----
  			post("%s - script name argument is invalid",thisName());
          else {
! 		    char dir[1024];
  		    GetModulePath(GetString(argv[0]),dir,sizeof(dir));
  		    // set script path
***************
*** 128,137 ****
  			AddToPath(GetString(canvas_getcurrentdir()));
  #elif FLEXT_SYS == FLEXT_SYS_MAX 
! #if FLEXT_OS == FLEXT_OS_WIN
! #else
  			short path = patcher_myvol(thisCanvas());
  			path_topathname(path,NULL,dir); 
  			AddToPath(dir);       
! #endif
  #else 
  	        #pragma message("Adding current dir to path is not implemented")
--- 131,139 ----
  			AddToPath(GetString(canvas_getcurrentdir()));
  #elif FLEXT_SYS == FLEXT_SYS_MAX 
! /*
  			short path = patcher_myvol(thisCanvas());
  			path_topathname(path,NULL,dir); 
  			AddToPath(dir);       
! */
  #else 
  	        #pragma message("Adding current dir to path is not implemented")
***************
*** 154,165 ****
  	}
  
! 	PY_UNLOCK
  }
  
  pyobj::~pyobj() 
  {
! 	PY_LOCK
  	Unregister("_py");
! 	PY_UNLOCK
  }
  
--- 156,167 ----
  	}
  
! 	PyUnlock(state);
  }
  
  pyobj::~pyobj() 
  {
! 	PyThreadState *state = PyLock();
  	Unregister("_py");
! 	PyUnlock(state);
  }
  
***************
*** 167,171 ****
  
  
! BL pyobj::m_method_(I n,const t_symbol *s,I argc,const t_atom *argv)
  {
  	if(n == 1)
--- 169,173 ----
  
  
! bool pyobj::m_method_(int n,const t_symbol *s,int argc,const t_atom *argv)
  {
  	if(n == 1)
***************
*** 174,180 ****
  }
  
! V pyobj::m_reload()
  {
! 	PY_LOCK
  
  	Unregister("_py");
--- 176,182 ----
  }
  
! void pyobj::m_reload()
  {
! 	PyThreadState *state = PyLock();
  
  	Unregister("_py");
***************
*** 185,205 ****
  	SetFunction(funname?GetString(funname):NULL);
  
! 	PY_UNLOCK
  }
  
! V pyobj::m_reload_(I argc,const t_atom *argv)
  {
! 	PY_LOCK
  	SetArgs(argc,argv);
! 	PY_UNLOCK
  
  	m_reload();
  }
  
! V pyobj::m_set(I argc,const t_atom *argv)
  {
! 	PY_LOCK
  
! 	I ix = 0;
  	if(argc >= 2) {
  		if(!IsString(argv[ix])) {
--- 187,207 ----
  	SetFunction(funname?GetString(funname):NULL);
  
! 	PyUnlock(state);
  }
  
! void pyobj::m_reload_(int argc,const t_atom *argv)
  {
! 	PyThreadState *state = PyLock();
  	SetArgs(argc,argv);
! 	PyUnlock(state);
  
  	m_reload();
  }
  
! void pyobj::m_set(int argc,const t_atom *argv)
  {
! 	PyThreadState *state = PyLock();
  
! 	int ix = 0;
  	if(argc >= 2) {
  		if(!IsString(argv[ix])) {
***************
*** 207,211 ****
  			return;
  		}
! 		const C *sn = GetString(argv[ix]);
  
  		if(!module || !strcmp(sn,PyModule_GetName(module))) {
--- 209,213 ----
  			return;
  		}
! 		const char *sn = GetString(argv[ix]);
  
  		if(!module || !strcmp(sn,PyModule_GetName(module))) {
***************
*** 222,232 ****
  		SetFunction(GetString(argv[ix]));
  
! 	PY_UNLOCK
  }
  
! V pyobj::m_help()
  {
  	post("");
! 	post("%s %s - python script object, (C)2002-2004 Thomas Grill",thisName(),PY__VERSION);
  #ifdef FLEXT_DEBUG
  	post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
--- 224,234 ----
  		SetFunction(GetString(argv[ix]));
  
! 	PyUnlock(state);
  }
  
! void pyobj::m_help()
  {
  	post("");
! 	post("%s %s - python script object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION);
  #ifdef FLEXT_DEBUG
  	post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__);
***************
*** 249,253 ****
  	post("\tdir+: dump function dictionary");
  #ifdef FLEXT_THREADS
! 	post("\tdetach 0/1: detach threads");
  	post("\tstop {wait time (ms)}: stop threads");
  #endif
--- 251,255 ----
  	post("\tdir+: dump function dictionary");
  #ifdef FLEXT_THREADS
! 	post("\tdetach 0/1/2: detach threads");
  	post("\tstop {wait time (ms)}: stop threads");
  #endif
***************
*** 255,259 ****
  }
  
! V pyobj::ResetFunction()
  {
  	if(!module || !dict) 
--- 257,261 ----
  }
  
! void pyobj::ResetFunction()
  {
  	if(!module || !dict) 
***************
*** 264,268 ****
  	}
  
! 	function = funname?PyDict_GetItemString(dict,(C *)GetString(funname)):NULL; // borrowed!!!
  	if(!function) {
  		PyErr_Clear();
--- 266,270 ----
  	}
  
! 	function = funname?PyDict_GetItemString(dict,(char *)GetString(funname)):NULL; // borrowed!!!
  	if(!function) {
  		PyErr_Clear();
***************
*** 275,279 ****
  }
  
! V pyobj::SetFunction(const C *func)
  {
  	if(func) {
--- 277,281 ----
  }
  
! void pyobj::SetFunction(const char *func)
  {
  	if(func) {
***************
*** 286,314 ****
  
  
! V pyobj::Reload()
  {
  	ResetFunction();
  }
  
! 
! BL pyobj::work(const t_symbol *s,I argc,const t_atom *argv)
  {
! 	AtomList *rargs = NULL;
!     BL ret;
! 
! 	++thrcount;
! 	PY_LOCK
  
  	if(function) {
! 		PyObject *pArgs = MakePyArgs(s,argc,argv);
! 		PyObject *pValue = PyObject_CallObject(function, pArgs);
! 
! 		rargs = GetPyArgs(pValue);
! 		if(!rargs) PyErr_Print();
  
! 		Py_XDECREF(pArgs);
! 		Py_XDECREF(pValue);
!         ret = true;
! 	}
  	else {
  		post("%s: no function defined",thisName());
--- 288,332 ----
  
  
! void pyobj::Reload()
  {
  	ResetFunction();
  }
  
! bool pyobj::callpy(PyObject *fun,PyObject *args)
  {
!     PyObject *ret = PyObject_Call(fun,args,NULL); 
!     if(ret == NULL) {
!         // function not found resp. arguments not matching
!         PyErr_Print();
!         return false;
!     }
!     else {
!         AtomList *rargs = GetPyArgs(ret);
! 		if(!rargs) 
!             PyErr_Print();
!         else {
!             // call to outlet _outside_ the Mutex lock!
!             // otherwise (if not detached) deadlock will occur
!             if(rargs->Count()) ToOutList(0,*rargs);
!             delete rargs;
!         }
!         Py_DECREF(ret);
!         return true;
!     }
! } 
  
+ void pyobj::callwork(const t_symbol *s,int argc,const t_atom *argv)
+ {
+     bool ret = false;
+  
  	if(function) {
!         PyThreadState *state = PyLock();
!     
! 		PyObject *pargs = MakePyArgs(s,argc,argv);
!         Py_INCREF(function);
!         ret = gencall(function,pargs);
  
!         PyUnlock(state);
!     }
  	else {
  		post("%s: no function defined",thisName());
***************
*** 316,347 ****
  	}
  
- 	PY_UNLOCK
- 	--thrcount;
- 
- 	if(rargs) {
- 		// call to outlet _outside_ the Mutex lock!
- 		// otherwise (if not detached) deadlock will occur
-  		if(rargs->Count()) ToOutList(0,*rargs);
- 		delete rargs;
- 	}
- 
-     return ret;
- }
- 
- V pyobj::callwork(const t_symbol *s,I argc,const t_atom *argv)
- {
-     BL ret = false;
- 	if(detach) {
- 		if(shouldexit)
- 			post("%s - New threads can't be launched now!",thisName());
- 		else {
- 			ret = FLEXT_CALLMETHOD_A(work,s,argc,argv);
- 			if(!ret) post("%s - Failed to launch thread!",thisName());
-         }
- 	}
-     else
- 		ret = work(s,argc,argv);
      Respond(ret);
  }
- 
- 
--- 334,337 ----





More information about the Pd-cvs mailing list