py/0000755000175000017500000000000013104443402011733 5ustar zmoelnigzmoelnigpy/.gitignore0000644000175000017500000000040713104443402013724 0ustar zmoelnigzmoelnig# Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Fortran module files *.mod # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app config.txt .DS_Store py/scripts/0000755000175000017500000000000013104443402013422 5ustar zmoelnigzmoelnigpy/scripts/pak.py0000644000175000017500000000053613104443402014553 0ustar zmoelnigzmoelnigimport pyext class pak(pyext._class): def __init__(self,n): # n should be type-checked self._inlets = n self._outlets = 1 # initialize list self.lst = [0 for x in range(n)] def _anything_(self,n,arg): # arg should be type-checked! self.lst[n-1] = arg self._outlet(1,self.lst) py/scripts/tcltk.py0000644000175000017500000000453113104443402015120 0ustar zmoelnigzmoelnig# py/pyext - python script objects for PD and MaxMSP # # Copyright (c) 2002-2003 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. # """This is an example script for showing a nonsense tcl/tk application.""" try: import pyext except: print "ERROR: This script must be loaded by the PD/Max pyext external" from Tkinter import * import random class Application(Frame): """This is the TK application class""" # Button pressed def say_hi(self): self.extcl._outlet(1,"hi there, everyone!") # Mouse motion over canvas def evfunc(self, ev): x = random.uniform(-3,3) y = random.uniform(-3,3) self.mcanv.move('group',x,y) # Create interface stuff def createWidgets(self): self.hi = Button(self) self.hi["text"] = "Hi!" self.hi["fg"] = "red" self.hi["command"] = self.say_hi self.hi.pack({"side": "left"}) self.mcanv = Canvas(self) self.mcanv.pack({"side": "left"}) self.mcanv.bind("", self.evfunc) self.mcanv.create_rectangle(50,50,200,200) r = self.mcanv.create_rectangle(50,50,200,200) self.mcanv.addtag_withtag('group',r) for i in xrange(500): x = random.uniform(50,200) y = random.uniform(50,200) l = self.mcanv.create_line(x,y,x+1,y) self.mcanv.addtag_withtag('group',l) # Constructor def __init__(self,cl): self.extcl = cl Frame.__init__(self) self.pack() self.createWidgets() pass # derive class from pyext._class class myapp(pyext._class): """This class demonstrates how a TCL/TK can be openened from within a pyext external""" # how many inlets and outlets? _inlets = 1 _outlets = 1 # Constructor def __init__(self): # detach bang method self._detach(1) def bang_1(self): self._priority(-3) # display the tcl/tk dialog app = Application(self) app.mainloop() py/scripts/sig.py0000644000175000017500000000475713104443402014573 0ustar zmoelnigzmoelnig# py/pyext - python script objects for PD and MaxMSP # # Copyright (c) 2002-2017 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. # """This is an example script for the py/pyext signal support. For numarray see http://numeric.scipy.org It will probably once be replaced by Numeric(3) """ try: import pyext except: print "ERROR: This script must be loaded by the PD/Max py/pyext external" try: import psyco psyco.full() print "Using JIT compilation" except: # don't care pass import sys,math try: import numpy as N except: print "Failed importing numpy module:",sys.exc_value class gain(pyext._class): """Just a simple gain stage""" def __init__(self): self.gain = 0 def _signal(self): # Multiply input vector by gain and copy to output try: self._outvec(0)[:] = self._invec(0)*self.gain except: pass class gain2(pyext._class): """More optimized version""" def __init__(self): self.gain = 0 def _dsp(self): if not self._arraysupport(): print "No DSP support" return False # cache vectors in this scope self.invec = self._invec(0) self.outvec = self._outvec(0) # initialize _signal method here for optimized version if self.invec is self.outvec: self._signal = self.signal1 else: self._signal = self.signal2 return True def signal1(self): # Multiply signal vector in place self.outvec *= self.gain def signal2(self): # Multiply input vector by gain and copy to output self.outvec[:] = self.invec*self.gain class pan(pyext._class): """Stereo panning""" def __init__(self): self.float_1(0.5) def float_1(self,pos): """pos ranges from 0 to 1""" x = pos*math.pi/2 self.fl = math.cos(x) self.fr = math.sin(x) def _dsp(self): # if _dsp is present it must return True to enable DSP return pyext._arraysupport() def _signal(self): # Multiply input vector by gain and copy to output iv = self._invec(0) # first process right output channel because left one could be # identical to input # we could also test with 'self._outvec(1)[:] is iv' self._outvec(1)[:] = iv*self.fr self._outvec(0)[:] = iv*self.fl py/scripts/threads.py0000644000175000017500000000256313104443402015434 0ustar zmoelnigzmoelnig# py/pyext - python script objects for PD and MaxMSP # # Copyright (c) 2002-2003 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. # """This is an example script for the py/pyext object's threading functionality. For threading support pyext exposes several function and variables - _detach([0/1]): by enabling thread detaching, threads will run in their own threads - _priority(prio+-): you can raise or lower the priority of the current thread - _stop({wait time in ms}): stop all running threads (you can additionally specify a wait time in ms) - _shouldexit: this is a flag which indicates that the running thread should terminate """ try: import pyext except: print "ERROR: This script must be loaded by the PD/Max pyext external" from time import sleep ################################################################# class ex1(pyext._class): """This is a simple class with one method looping over time.""" # number of inlets and outlets _inlets=2 _outlets=2 sltime=0.1 # sleep time loops=20 # loops to iterate # method for bang to any inlet def bang_(self,n): for i in xrange(self.loops): # if _shouldexit is true, the thread ought to stop if self._shouldexit: print "BREAK" break self._outlet(n,i) sleep(self.sltime) py/scripts/buffer.py0000644000175000017500000000357513104443402015257 0ustar zmoelnigzmoelnig# py/pyext - python script objects for PD and MaxMSP # # Copyright (c) 2002-2012 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. # """This is an example script for the py/pyext object's buffer support. Pd/Max buffers can be mapped to Python arrays. Currently, there are three implementations: Numeric, numarray and numpy (for all of them see http://numeric.scipy.org) """ import sys try: import pyext except: print "ERROR: This script must be loaded by the PD/Max py/pyext external" try: # numpy is assumed here... numeric and numarray are considered deprecated import numpy as N except: print "Failed importing numpy 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]) a = pyext.Buffer(args[1]) b = pyext.Buffer(args[2]) commonlen = min(len(a),len(b),len(c)) # slicing causes Python arrays (mapped to buffers) to be created # note the c[:] - to assign contents you must assign to a slice of the buffer c[:commonlen] = a[:commonlen]*b[:commonlen] def add(*args): c = pyext.Buffer(args[0]) a = pyext.Buffer(args[1]) b = pyext.Buffer(args[2]) commonlen = min(len(a),len(b),len(c)) # explicit casting to arrays is also possible c[:commonlen] = N.array(a[:commonlen],dtype=N.float32) + N.array(b[:commonlen],dtype=N.float32) def fadein(target): a = pyext.Buffer(target) # in place operations are ok a *= N.arange(len(a),dtype=N.float32)/len(a) def neg(target): a = pyext.Buffer(target) # in place transformation (see Python array ufuncs) N.negative(a[:],a[:]) # must mark buffer content as dirty to update graph # (no explicit assignment occurred) a.dirty() py/scripts/simple.py0000644000175000017500000001250113104443402015264 0ustar zmoelnigzmoelnig# py/pyext - python script objects for PD and MaxMSP # # Copyright (c) 2002-2007 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. # """This is an example script for the py/pyext object's basic functionality. pyext Usage: - Import pyext - Inherit your class from pyext._class - Specfiy the number of inlets and outlets: Use the class members (variables) _inlets and _outlets If not given they default to 1 You can also use class methods with the same names to return the respective number - Constructors/Destructors You can specify an __init__ constructor and/or an __del__ destructor. The constructor will be called with the object's arguments e.g. if your PD or MaxMSP object looks like [pyext script class arg1 arg2 arg3] then the __init__(self,*args) function will be called with a tuple argument args = (arg1,arg2,arg3) With this syntax, you will have to give at least one argument. By defining the constructor as __init__(self,*args) you can also initialize the class without arguments. - Methods called by pyext The general format is 'tag_inlet(self,arg)' resp. 'tag_inlet(self,*args)': tag is the PD or MaxMSP message header.. either bang, float, list etc. inlet is the inlet (starting from 1) from which messages are received. args is a tuple which corresponds to the content of the message. args can be omitted. The inlet index can be omitted. The method name then has the format 'tag_(self,inlet,args)'. Here, the inlet index is a additional parameter to the method You can also set up methods which react on any message. These have the special forms _anything_inlet(self,*args) or _anything_(self,inlet,*args) Please see below for examples. Any return values are ignored - use _outlet (see below). Generally, you should avoid method_, method_xx forms for your non-pyext class methods. Identifiers (variables and functions) with leading underscores are reserved for pyext. - Send messages to outlets: Use the inherited _outlet method. You can either use the form self._outlet(outlet,arg1,arg2,arg3,arg4) ... where all args are atoms (no sequence types!) or self._outlet(outlet,arg) ... where arg is a sequence containing only atoms Do not use _outlet inside __init__, since the outlets have not been created at that time. - Use pyext functions and methods: See the __doc__ strings of the pyext module and the pyext._class base class. """ try: import pyext except: print "ERROR: This script must be loaded by the PD/Max pyext external" ################################################################# class ex1(pyext._class): """Example of a simple class which receives messages and prints to the console""" # number of inlets and outlets _inlets=3 _outlets=0 # methods for first inlet def bang_1(self): print "Bang into first inlet" def int_1(self,f): print "Integer",f,"into first inlet" def float_1(self,f): print "Float",f,"into first inlet" def list_1(self,*s): print "List",s,"into first inlet" # methods for second inlet def hey_2(self): print "Tag 'hey' into second inlet" def ho_2(self): print "Tag 'ho' into second inlet" def lets_2(self): print "Tag 'lets' into second inlet" def go_2(self): print "Tag 'go' into second inlet" def _anything_2(self,*args): print "Some other message into second inlet:",args # methods for third inlet def onearg_3(self,a): print "Tag 'onearg' into third inlet:",a def twoargs_3(self,*a): if len(a) == 2: print "Tag 'twoargs' into third inlet:",a[0],a[1] else: print "Tag 'twoargs': wrong number of arguments" def threeargs_3(self,*a): if len(a) == 3: print "Tag 'threeargs' into third inlet",a[0],a[1],a[2] else: print "Tag 'threeargs': wrong number of arguments" def varargs_3(self,*args): # with *args there can be arguments or not print "Tag 'varargs' into third inlet",args ################################################################# class ex2(pyext._class): """Example of a simple class which receives messages and writes to outlets""" # number of inlets and outlets _inlets=3 _outlets=2 # methods for all inlets def hello_(self,n): print "Tag 'hello' into inlet",n def _anything_(self,n,*args): print "Message into inlet",n,":",args # methods for first inlet def float_1(self,f): self._outlet(2,f) # methods for second inlet def float_2(self,f): self._outlet(1,f) ################################################################# # helper function - determine whether argument is a numeric type def isNumber(value): import types if type(value) in (types.FloatType, types.IntType, types.LongType): return 1 else: return 0 class ex3(pyext._class): """Example of a simple class doing a typical number addition It uses a constructor and a class member as temporary storage. """ # number of inlets and outlets _inlets=2 _outlets=1 # temporary storage tmp=0 # constructor def __init__(self,*args): if len(args) == 1: if isNumber(args[0]): self.tmp = args[0] else: print "ex3: __init__ has superfluous arguments" # methods def float_1(self,f): self._outlet(1,self.tmp+f) def float_2(self,f): self.tmp = f # handlers for MaxMSP int type def int_1(self,f): self.float_1(f) def int_2(self,f): self.float_2(f) py/scripts/script.py0000644000175000017500000000173313104443402015304 0ustar zmoelnigzmoelnig# py/pyext - python script objects 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. # """Several functions to show the py script functionality""" import sys print "Script initialized" try: print "Script arguments: ",sys.argv except: print def numargs(*args): # variable argument list """Return the number of arguments""" return len(args) def strlen(arg): """Return the string length""" # we must convert to string first (it's a symbol type most likely) return len(str(arg)) def strcat(*args): """Concatenate several symbols""" return reduce(lambda a,b: a+str(b), args,"") def addall(*args): # variable argument list """Add a couple of numbers""" return reduce(lambda a,b: a+b, args,0) def ret1(): return 1,2,3,4 def ret2(): return "sd","lk","ki" def ret3(): return ["sd","lk","ki"] py/scripts/sendrecv.py0000644000175000017500000001042013104443402015602 0ustar zmoelnigzmoelnig# py/pyext - python script objects 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. # """This is an example script for the py/pyext object's send/receive functionality. You can: - bind There are several classes exposing py/pyext features: - ex1: A class receiving messages and sending them out again - ex2: A class receiving messages and putting them out to an outlet - ex3: Do some PD scripting """ try: import pyext except: print "ERROR: This script must be loaded by the PD/Max pyext external" from time import sleep ################################################################# def recv_gl(arg): """This is a global receive function, it has no access to class members.""" print "GLOBAL",arg class ex1(pyext._class): """Example of a class which receives and sends messages It has two creation arguments: a receiver and a sender name. There are no inlets and outlets. Python functions (one global function, one class method) are bound to PD's or Max/MSP's receive symbols. The class method sends the received messages out again. """ # no inlets and outlets _inlets=1 _outlets=0 recvname="" sendname="" def recv(self,*arg): """This is a class-local receive function, which has access to class members.""" # print some stuff print "CLASS",self.recvname,arg # send data to specified send address self._send(self.sendname,arg) def __init__(self,*args): """Class constructor""" # store sender/receiver names if len(args) >= 1: self.recvname = args[0] if len(args) >= 2: self.sendname = args[1] self.bind_1() def bind_1(self): # bind functions to receiver names # both are called upon message self._bind(self.recvname,self.recv) self._bind(self.recvname,recv_gl) def unbind_1(self): self._unbind(self.recvname,self.recv) self._unbind(self.recvname,recv_gl) def __del__(self): """Class destructor""" # unbinding is automatically done at destruction pass ################################################################# class ex2(pyext._class): """Example of a class which receives a message and forwards it to an outlet It has one creation argument: the receiver name. """ # define inlets and outlets _inlets=0 _outlets=1 recvname="" def recv(self,*arg): """This is a class-local receive function""" # send received data to outlet self._outlet(1,arg) def __init__(self,rname): """Class constructor""" # store receiver names self.recvname = rname # bind function to receiver name self._bind(self.recvname,self.recv) ################################################################# from math import pi from cmath import exp from random import random,randint class ex3(pyext._class): """Example of a class which does some object manipulation by scripting""" # define inlets and outlets _inlets=1 _outlets=0 def __init__(self): """Class constructor""" # called scripting method should run on its own thread if self._isthreaded: print "Threading is on" self._detach(1) def bang_1(self): """Do some scripting - PD only!""" num = 12 # number of objects ori = complex(150,180) # origin rad = 100 # radius l = range(num) # initialize list # make flower self._tocanvas("obj",ori.real,ori.imag,"bng",20,250,50,0,"empty","yeah","empty",0,-6,64,8,-24198,-1,-1) for i in xrange(num): l[i] = ori+rad*exp(complex(0,i*2*pi/num)) self._tocanvas("obj",l[i].real,l[i].imag,"bng",15,250,50,0,"empty","yeah"+str(i),"empty",0,-6,64,8,0,-1,-1) self._tocanvas("connect",6,0,7+i,0) # blink for i in range(10): self._send("yeah","bang") sleep(1./(i+1)) # move objects around for i in xrange(200): ix = randint(0,num-1) l[ix] = ori+rad*complex(2*random()-1,2*random()-1) self._send("yeah"+str(ix),"pos",l[ix].real,l[ix].imag) sleep(0.02) # now delete # this is not well-done... from time to time an object remains self._tocanvas("editmode",1) for i in xrange(num): self._tocanvas("mouse",l[i].real,l[i].imag,0,0) self._tocanvas("cut") self._tocanvas("mouse",ori.real+1,ori.imag+1,0,0) self._tocanvas("cut") self._tocanvas("editmode",0) py/py.xcodeproj/0000755000175000017500000000000013104443402014357 5ustar zmoelnigzmoelnigpy/py.xcodeproj/project.pbxproj0000644000175000017500000012033013104443402017432 0ustar zmoelnigzmoelnig// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ E90043870887A302008AEAFC /* pyatom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043820887A302008AEAFC /* pyatom.cpp */; }; E90043880887A302008AEAFC /* pyatom.h in Headers */ = {isa = PBXBuildFile; fileRef = E90043830887A302008AEAFC /* pyatom.h */; }; E90043890887A302008AEAFC /* pybase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043840887A302008AEAFC /* pybase.cpp */; }; E900438A0887A302008AEAFC /* pybase.h in Headers */ = {isa = PBXBuildFile; fileRef = E90043850887A302008AEAFC /* pybase.h */; }; E900438B0887A302008AEAFC /* pymeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043860887A302008AEAFC /* pymeth.cpp */; }; E903AC8E09D32D03004755CA /* pybundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E903AC8C09D32D03004755CA /* pybundle.cpp */; }; E903AC8F09D32D03004755CA /* pybundle.h in Resources */ = {isa = PBXBuildFile; fileRef = E903AC8D09D32D03004755CA /* pybundle.h */; }; E903AC9009D32D03004755CA /* pybundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E903AC8C09D32D03004755CA /* pybundle.cpp */; }; E903AC9109D32D03004755CA /* pybundle.h in Headers */ = {isa = PBXBuildFile; fileRef = E903AC8D09D32D03004755CA /* pybundle.h */; }; E90E52E908092581001341AC /* main.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51DE08091989001341AC /* main.h */; }; E90E52EA08092581001341AC /* pybuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51E308091989001341AC /* pybuffer.h */; }; E90E52EB08092581001341AC /* pyext.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51E608091989001341AC /* pyext.h */; }; E90E52EC08092581001341AC /* pyprefix.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51E708091989001341AC /* pyprefix.h */; }; E90E52ED08092581001341AC /* pysymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51E908091989001341AC /* pysymbol.h */; }; E90E52EE0809258A001341AC /* bound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DB08091989001341AC /* bound.cpp */; }; E90E52EF0809258A001341AC /* clmeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DC08091989001341AC /* clmeth.cpp */; }; E90E52F00809258A001341AC /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DD08091989001341AC /* main.cpp */; }; E90E52F10809258A001341AC /* modmeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DF08091989001341AC /* modmeth.cpp */; }; E90E52F20809258A001341AC /* py.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E008091989001341AC /* py.cpp */; }; E90E52F30809258A001341AC /* pyargs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E108091989001341AC /* pyargs.cpp */; }; E90E52F40809258A001341AC /* pybuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E208091989001341AC /* pybuffer.cpp */; }; E90E52F50809258A001341AC /* pydsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E408091989001341AC /* pydsp.cpp */; }; E90E52F60809258A001341AC /* pyext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E508091989001341AC /* pyext.cpp */; }; E90E52F70809258A001341AC /* pysymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E808091989001341AC /* pysymbol.cpp */; }; E90E52F80809258A001341AC /* register.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51EA08091989001341AC /* register.cpp */; }; E90E535D08092593001341AC /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E90E521108091CA5001341AC /* ApplicationServices.framework */; }; E90EBAEC1ADDC06600CFDB74 /* main.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51DE08091989001341AC /* main.h */; }; E90EBAED1ADDC06600CFDB74 /* pybuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51E308091989001341AC /* pybuffer.h */; }; E90EBAEE1ADDC06600CFDB74 /* pyext.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51E608091989001341AC /* pyext.h */; }; E90EBAEF1ADDC06600CFDB74 /* pyprefix.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51E708091989001341AC /* pyprefix.h */; }; E90EBAF01ADDC06600CFDB74 /* pysymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = E90E51E908091989001341AC /* pysymbol.h */; }; E90EBAF11ADDC06600CFDB74 /* pyatom.h in Headers */ = {isa = PBXBuildFile; fileRef = E90043830887A302008AEAFC /* pyatom.h */; }; E90EBAF21ADDC06600CFDB74 /* pybase.h in Headers */ = {isa = PBXBuildFile; fileRef = E90043850887A302008AEAFC /* pybase.h */; }; E90EBAF31ADDC06600CFDB74 /* pybundle.h in Headers */ = {isa = PBXBuildFile; fileRef = E903AC8D09D32D03004755CA /* pybundle.h */; }; E90EBAF51ADDC06600CFDB74 /* bound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DB08091989001341AC /* bound.cpp */; }; E90EBAF61ADDC06600CFDB74 /* clmeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DC08091989001341AC /* clmeth.cpp */; }; E90EBAF71ADDC06600CFDB74 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DD08091989001341AC /* main.cpp */; }; E90EBAF81ADDC06600CFDB74 /* modmeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DF08091989001341AC /* modmeth.cpp */; }; E90EBAF91ADDC06600CFDB74 /* py.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E008091989001341AC /* py.cpp */; }; E90EBAFA1ADDC06600CFDB74 /* pyargs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E108091989001341AC /* pyargs.cpp */; }; E90EBAFB1ADDC06600CFDB74 /* pybuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E208091989001341AC /* pybuffer.cpp */; }; E90EBAFC1ADDC06600CFDB74 /* pydsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E408091989001341AC /* pydsp.cpp */; }; E90EBAFD1ADDC06600CFDB74 /* pyext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E508091989001341AC /* pyext.cpp */; }; E90EBAFE1ADDC06600CFDB74 /* pysymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E808091989001341AC /* pysymbol.cpp */; }; E90EBAFF1ADDC06600CFDB74 /* register.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51EA08091989001341AC /* register.cpp */; }; E90EBB001ADDC06600CFDB74 /* pyatom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043820887A302008AEAFC /* pyatom.cpp */; }; E90EBB011ADDC06600CFDB74 /* pybase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043840887A302008AEAFC /* pybase.cpp */; }; E90EBB021ADDC06600CFDB74 /* pymeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043860887A302008AEAFC /* pymeth.cpp */; }; E90EBB031ADDC06600CFDB74 /* pybundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E903AC8C09D32D03004755CA /* pybundle.cpp */; }; E90EBB051ADDC06600CFDB74 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E90E521108091CA5001341AC /* ApplicationServices.framework */; }; E926B6D8089F76D90034D534 /* pyatom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043820887A302008AEAFC /* pyatom.cpp */; }; E926B6D9089F76D90034D534 /* pyatom.h in Sources */ = {isa = PBXBuildFile; fileRef = E90043830887A302008AEAFC /* pyatom.h */; }; E926B6DA089F76D90034D534 /* pybase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043840887A302008AEAFC /* pybase.cpp */; }; E926B6DB089F76D90034D534 /* pybase.h in Sources */ = {isa = PBXBuildFile; fileRef = E90043850887A302008AEAFC /* pybase.h */; }; E926B6DC089F76D90034D534 /* pymeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90043860887A302008AEAFC /* pymeth.cpp */; }; E926B6DD089F76D90034D534 /* bound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DB08091989001341AC /* bound.cpp */; }; E926B6DE089F76D90034D534 /* clmeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DC08091989001341AC /* clmeth.cpp */; }; E926B6DF089F76D90034D534 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DD08091989001341AC /* main.cpp */; }; E926B6E0089F76D90034D534 /* main.h in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DE08091989001341AC /* main.h */; }; E926B6E1089F76D90034D534 /* modmeth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51DF08091989001341AC /* modmeth.cpp */; }; E926B6E2089F76D90034D534 /* py.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E008091989001341AC /* py.cpp */; }; E926B6E3089F76D90034D534 /* pyargs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E108091989001341AC /* pyargs.cpp */; }; E926B6E4089F76D90034D534 /* pybuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E208091989001341AC /* pybuffer.cpp */; }; E926B6E5089F76D90034D534 /* pybuffer.h in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E308091989001341AC /* pybuffer.h */; }; E926B6E6089F76D90034D534 /* pydsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E408091989001341AC /* pydsp.cpp */; }; E926B6E7089F76D90034D534 /* pyext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E508091989001341AC /* pyext.cpp */; }; E926B6E8089F76D90034D534 /* pyext.h in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E608091989001341AC /* pyext.h */; }; E926B6E9089F76D90034D534 /* pyprefix.h in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E708091989001341AC /* pyprefix.h */; }; E926B6EA089F76D90034D534 /* pysymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E808091989001341AC /* pysymbol.cpp */; }; E926B6EB089F76D90034D534 /* pysymbol.h in Sources */ = {isa = PBXBuildFile; fileRef = E90E51E908091989001341AC /* pysymbol.h */; }; E926B6EC089F76D90034D534 /* register.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E90E51EA08091989001341AC /* register.cpp */; }; E926B7B6089F77B90034D534 /* Python.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E90E51FB080919EC001341AC /* Python.framework */; }; E926B818089F782F0034D534 /* MaxAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E926B817089F782F0034D534 /* MaxAPI.framework */; }; E926B81A089F78400034D534 /* MaxAudioAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E926B819089F78400034D534 /* MaxAudioAPI.framework */; }; E926B833089F7CB50034D534 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E90E521108091CA5001341AC /* ApplicationServices.framework */; }; E9D6763308FC61A40039A6F6 /* libflext-max_d.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E9D6762D08FC61860039A6F6 /* libflext-max_d.dylib */; }; E9D6763408FC61A40039A6F6 /* libflext-max.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E9D6762E08FC61860039A6F6 /* libflext-max.dylib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ E90043820887A302008AEAFC /* pyatom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pyatom.cpp; path = source/pyatom.cpp; sourceTree = ""; }; E90043830887A302008AEAFC /* pyatom.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pyatom.h; path = source/pyatom.h; sourceTree = ""; }; E90043840887A302008AEAFC /* pybase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pybase.cpp; path = source/pybase.cpp; sourceTree = ""; }; E90043850887A302008AEAFC /* pybase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pybase.h; path = source/pybase.h; sourceTree = ""; }; E90043860887A302008AEAFC /* pymeth.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pymeth.cpp; path = source/pymeth.cpp; sourceTree = ""; }; E903AC8C09D32D03004755CA /* pybundle.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pybundle.cpp; path = source/pybundle.cpp; sourceTree = ""; }; E903AC8D09D32D03004755CA /* pybundle.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pybundle.h; path = source/pybundle.h; sourceTree = ""; }; E90E51DB08091989001341AC /* bound.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = bound.cpp; path = source/bound.cpp; sourceTree = ""; }; E90E51DC08091989001341AC /* clmeth.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = clmeth.cpp; path = source/clmeth.cpp; sourceTree = ""; }; E90E51DD08091989001341AC /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = source/main.cpp; sourceTree = ""; }; E90E51DE08091989001341AC /* main.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = main.h; path = source/main.h; sourceTree = ""; }; E90E51DF08091989001341AC /* modmeth.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = modmeth.cpp; path = source/modmeth.cpp; sourceTree = ""; }; E90E51E008091989001341AC /* py.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = py.cpp; path = source/py.cpp; sourceTree = ""; }; E90E51E108091989001341AC /* pyargs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pyargs.cpp; path = source/pyargs.cpp; sourceTree = ""; }; E90E51E208091989001341AC /* pybuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pybuffer.cpp; path = source/pybuffer.cpp; sourceTree = ""; }; E90E51E308091989001341AC /* pybuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pybuffer.h; path = source/pybuffer.h; sourceTree = ""; }; E90E51E408091989001341AC /* pydsp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pydsp.cpp; path = source/pydsp.cpp; sourceTree = ""; }; E90E51E508091989001341AC /* pyext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pyext.cpp; path = source/pyext.cpp; sourceTree = ""; }; E90E51E608091989001341AC /* pyext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pyext.h; path = source/pyext.h; sourceTree = ""; }; E90E51E708091989001341AC /* pyprefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pyprefix.h; path = source/pyprefix.h; sourceTree = ""; }; E90E51E808091989001341AC /* pysymbol.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pysymbol.cpp; path = source/pysymbol.cpp; sourceTree = ""; }; E90E51E908091989001341AC /* pysymbol.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pysymbol.h; path = source/pysymbol.h; sourceTree = ""; }; E90E51EA08091989001341AC /* register.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = register.cpp; path = source/register.cpp; sourceTree = ""; }; E90E51FB080919EC001341AC /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = /System/Library/Frameworks/Python.framework; sourceTree = ""; }; E90E521108091CA5001341AC /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; E90E52E608092505001341AC /* py.pd_darwin */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = py.pd_darwin; sourceTree = BUILT_PRODUCTS_DIR; }; E90EBB0B1ADDC06600CFDB74 /* py.pd_darwin */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = py.pd_darwin; sourceTree = BUILT_PRODUCTS_DIR; }; E926B6D3089F75950034D534 /* py.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = py.mxo; sourceTree = BUILT_PRODUCTS_DIR; }; E926B817089F782F0034D534 /* MaxAPI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MaxAPI.framework; path = /Library/Frameworks/MaxAPI.framework; sourceTree = ""; }; E926B819089F78400034D534 /* MaxAudioAPI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MaxAudioAPI.framework; path = /Library/Frameworks/MaxAudioAPI.framework; sourceTree = ""; }; E9D6762D08FC61860039A6F6 /* libflext-max_d.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libflext-max_d.dylib"; path = "/usr/local/lib/libflext-max_d.dylib"; sourceTree = ""; }; E9D6762E08FC61860039A6F6 /* libflext-max.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libflext-max.dylib"; path = "/usr/local/lib/libflext-max.dylib"; sourceTree = ""; }; E9D6762F08FC61860039A6F6 /* libflext-pd_d.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libflext-pd_d.dylib"; path = "/usr/local/lib/libflext-pd_d.dylib"; sourceTree = ""; }; E9D6763008FC61860039A6F6 /* libflext-pd.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libflext-pd.dylib"; path = "/usr/local/lib/libflext-pd.dylib"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ E90E52E408092505001341AC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( E90E535D08092593001341AC /* ApplicationServices.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; E90EBB041ADDC06600CFDB74 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( E90EBB051ADDC06600CFDB74 /* ApplicationServices.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; E926B6D1089F75950034D534 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( E9D6763308FC61A40039A6F6 /* libflext-max_d.dylib in Frameworks */, E9D6763408FC61A40039A6F6 /* libflext-max.dylib in Frameworks */, E926B833089F7CB50034D534 /* ApplicationServices.framework in Frameworks */, E926B7B6089F77B90034D534 /* Python.framework in Frameworks */, E926B818089F782F0034D534 /* MaxAPI.framework in Frameworks */, E926B81A089F78400034D534 /* MaxAudioAPI.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 089C166AFE841209C02AAC07 /* py */ = { isa = PBXGroup; children = ( 08FB77ADFE841716C02AAC07 /* Source */, 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */, 19C28FB4FE9D528D11CA2CBB /* Products */, ); name = py; sourceTree = ""; }; 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */ = { isa = PBXGroup; children = ( E9D6762D08FC61860039A6F6 /* libflext-max_d.dylib */, E9D6762E08FC61860039A6F6 /* libflext-max.dylib */, E9D6762F08FC61860039A6F6 /* libflext-pd_d.dylib */, E9D6763008FC61860039A6F6 /* libflext-pd.dylib */, E926B819089F78400034D534 /* MaxAudioAPI.framework */, E926B817089F782F0034D534 /* MaxAPI.framework */, E90E521108091CA5001341AC /* ApplicationServices.framework */, E90E51FB080919EC001341AC /* Python.framework */, ); name = "External Frameworks and Libraries"; sourceTree = ""; }; 08FB77ADFE841716C02AAC07 /* Source */ = { isa = PBXGroup; children = ( E903AC8C09D32D03004755CA /* pybundle.cpp */, E903AC8D09D32D03004755CA /* pybundle.h */, E90043820887A302008AEAFC /* pyatom.cpp */, E90043830887A302008AEAFC /* pyatom.h */, E90043840887A302008AEAFC /* pybase.cpp */, E90043850887A302008AEAFC /* pybase.h */, E90043860887A302008AEAFC /* pymeth.cpp */, E90E51DB08091989001341AC /* bound.cpp */, E90E51DC08091989001341AC /* clmeth.cpp */, E90E51DD08091989001341AC /* main.cpp */, E90E51DE08091989001341AC /* main.h */, E90E51DF08091989001341AC /* modmeth.cpp */, E90E51E008091989001341AC /* py.cpp */, E90E51E108091989001341AC /* pyargs.cpp */, E90E51E208091989001341AC /* pybuffer.cpp */, E90E51E308091989001341AC /* pybuffer.h */, E90E51E408091989001341AC /* pydsp.cpp */, E90E51E508091989001341AC /* pyext.cpp */, E90E51E608091989001341AC /* pyext.h */, E90E51E708091989001341AC /* pyprefix.h */, E90E51E808091989001341AC /* pysymbol.cpp */, E90E51E908091989001341AC /* pysymbol.h */, E90E51EA08091989001341AC /* register.cpp */, ); name = Source; sourceTree = ""; }; 19C28FB4FE9D528D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( E90E52E608092505001341AC /* py.pd_darwin */, E926B6D3089F75950034D534 /* py.mxo */, E90EBB0B1ADDC06600CFDB74 /* py.pd_darwin */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ E90E52E208092505001341AC /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( E90E52E908092581001341AC /* main.h in Headers */, E90E52EA08092581001341AC /* pybuffer.h in Headers */, E90E52EB08092581001341AC /* pyext.h in Headers */, E90E52EC08092581001341AC /* pyprefix.h in Headers */, E90E52ED08092581001341AC /* pysymbol.h in Headers */, E90043880887A302008AEAFC /* pyatom.h in Headers */, E900438A0887A302008AEAFC /* pybase.h in Headers */, E903AC9109D32D03004755CA /* pybundle.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; E90EBAEB1ADDC06600CFDB74 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( E90EBAEC1ADDC06600CFDB74 /* main.h in Headers */, E90EBAED1ADDC06600CFDB74 /* pybuffer.h in Headers */, E90EBAEE1ADDC06600CFDB74 /* pyext.h in Headers */, E90EBAEF1ADDC06600CFDB74 /* pyprefix.h in Headers */, E90EBAF01ADDC06600CFDB74 /* pysymbol.h in Headers */, E90EBAF11ADDC06600CFDB74 /* pyatom.h in Headers */, E90EBAF21ADDC06600CFDB74 /* pybase.h in Headers */, E90EBAF31ADDC06600CFDB74 /* pybundle.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ E90E52E508092505001341AC /* py.pd_darwin */ = { isa = PBXNativeTarget; buildConfigurationList = E93C2D850A5DB6E70023B566 /* Build configuration list for PBXNativeTarget "py.pd_darwin" */; buildPhases = ( E90E52E208092505001341AC /* Headers */, E90E52E308092505001341AC /* Sources */, E90E52E408092505001341AC /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = py.pd_darwin; productName = py; productReference = E90E52E608092505001341AC /* py.pd_darwin */; productType = "com.apple.product-type.library.dynamic"; }; E90EBAEA1ADDC06600CFDB74 /* py.pd_darwin (inline) */ = { isa = PBXNativeTarget; buildConfigurationList = E90EBB071ADDC06600CFDB74 /* Build configuration list for PBXNativeTarget "py.pd_darwin (inline)" */; buildPhases = ( E90EBAEB1ADDC06600CFDB74 /* Headers */, E90EBAF41ADDC06600CFDB74 /* Sources */, E90EBB041ADDC06600CFDB74 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = "py.pd_darwin (inline)"; productName = py; productReference = E90EBB0B1ADDC06600CFDB74 /* py.pd_darwin */; productType = "com.apple.product-type.library.dynamic"; }; E926B6D2089F75950034D534 /* py */ = { isa = PBXNativeTarget; buildConfigurationList = E93C2D890A5DB6E70023B566 /* Build configuration list for PBXNativeTarget "py" */; buildPhases = ( E926B6CF089F75950034D534 /* Resources */, E926B6D0089F75950034D534 /* Sources */, E926B6D1089F75950034D534 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = py; productName = py; productReference = E926B6D3089F75950034D534 /* py.mxo */; productType = "com.apple.product-type.bundle"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 089C1669FE841209C02AAC07 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0620; }; buildConfigurationList = E93C2D8D0A5DB6E70023B566 /* Build configuration list for PBXProject "py" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, Japanese, French, German, ); mainGroup = 089C166AFE841209C02AAC07 /* py */; projectDirPath = ""; projectRoot = ""; targets = ( E90E52E508092505001341AC /* py.pd_darwin */, E926B6D2089F75950034D534 /* py */, E90EBAEA1ADDC06600CFDB74 /* py.pd_darwin (inline) */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ E926B6CF089F75950034D534 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( E903AC8F09D32D03004755CA /* pybundle.h in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ E90E52E308092505001341AC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E90E52EE0809258A001341AC /* bound.cpp in Sources */, E90E52EF0809258A001341AC /* clmeth.cpp in Sources */, E90E52F00809258A001341AC /* main.cpp in Sources */, E90E52F10809258A001341AC /* modmeth.cpp in Sources */, E90E52F20809258A001341AC /* py.cpp in Sources */, E90E52F30809258A001341AC /* pyargs.cpp in Sources */, E90E52F40809258A001341AC /* pybuffer.cpp in Sources */, E90E52F50809258A001341AC /* pydsp.cpp in Sources */, E90E52F60809258A001341AC /* pyext.cpp in Sources */, E90E52F70809258A001341AC /* pysymbol.cpp in Sources */, E90E52F80809258A001341AC /* register.cpp in Sources */, E90043870887A302008AEAFC /* pyatom.cpp in Sources */, E90043890887A302008AEAFC /* pybase.cpp in Sources */, E900438B0887A302008AEAFC /* pymeth.cpp in Sources */, E903AC9009D32D03004755CA /* pybundle.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E90EBAF41ADDC06600CFDB74 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E90EBAF51ADDC06600CFDB74 /* bound.cpp in Sources */, E90EBAF61ADDC06600CFDB74 /* clmeth.cpp in Sources */, E90EBAF71ADDC06600CFDB74 /* main.cpp in Sources */, E90EBAF81ADDC06600CFDB74 /* modmeth.cpp in Sources */, E90EBAF91ADDC06600CFDB74 /* py.cpp in Sources */, E90EBAFA1ADDC06600CFDB74 /* pyargs.cpp in Sources */, E90EBAFB1ADDC06600CFDB74 /* pybuffer.cpp in Sources */, E90EBAFC1ADDC06600CFDB74 /* pydsp.cpp in Sources */, E90EBAFD1ADDC06600CFDB74 /* pyext.cpp in Sources */, E90EBAFE1ADDC06600CFDB74 /* pysymbol.cpp in Sources */, E90EBAFF1ADDC06600CFDB74 /* register.cpp in Sources */, E90EBB001ADDC06600CFDB74 /* pyatom.cpp in Sources */, E90EBB011ADDC06600CFDB74 /* pybase.cpp in Sources */, E90EBB021ADDC06600CFDB74 /* pymeth.cpp in Sources */, E90EBB031ADDC06600CFDB74 /* pybundle.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E926B6D0089F75950034D534 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E926B6D8089F76D90034D534 /* pyatom.cpp in Sources */, E926B6D9089F76D90034D534 /* pyatom.h in Sources */, E926B6DA089F76D90034D534 /* pybase.cpp in Sources */, E926B6DB089F76D90034D534 /* pybase.h in Sources */, E926B6DC089F76D90034D534 /* pymeth.cpp in Sources */, E926B6DD089F76D90034D534 /* bound.cpp in Sources */, E926B6DE089F76D90034D534 /* clmeth.cpp in Sources */, E926B6DF089F76D90034D534 /* main.cpp in Sources */, E926B6E0089F76D90034D534 /* main.h in Sources */, E926B6E1089F76D90034D534 /* modmeth.cpp in Sources */, E926B6E2089F76D90034D534 /* py.cpp in Sources */, E926B6E3089F76D90034D534 /* pyargs.cpp in Sources */, E926B6E4089F76D90034D534 /* pybuffer.cpp in Sources */, E926B6E5089F76D90034D534 /* pybuffer.h in Sources */, E926B6E6089F76D90034D534 /* pydsp.cpp in Sources */, E926B6E7089F76D90034D534 /* pyext.cpp in Sources */, E926B6E8089F76D90034D534 /* pyext.h in Sources */, E926B6E9089F76D90034D534 /* pyprefix.h in Sources */, E926B6EA089F76D90034D534 /* pysymbol.cpp in Sources */, E926B6EB089F76D90034D534 /* pysymbol.h in Sources */, E926B6EC089F76D90034D534 /* register.cpp in Sources */, E903AC8E09D32D03004755CA /* pybundle.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ E90EBB081ADDC06600CFDB74 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_EXTENSION = pd_darwin; FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "FLEXT_SYS=2", FLEXT_DEBUG, FLEXT_INLINE, FLEXT_USE_CMEM, ); HEADER_SEARCH_PATHS = ( "$(inherited)", "$(flext)/source", "$(PD)/src", ); INSTALL_PATH = "~/Library/Pure Data"; LIBRARY_SEARCH_PATHS = "$(flext)/build"; MACH_O_TYPE = mh_dylib; OTHER_LDFLAGS = ( "-undefined", dynamic_lookup, "-framework", Python, ); PRODUCT_NAME = py; }; name = Development; }; E90EBB091ADDC06600CFDB74 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_EXTENSION = pd_darwin; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "FLEXT_SYS=2", FLEXT_INLINE, FLEXT_USE_CMEM, ); HEADER_SEARCH_PATHS = ( "$(inherited)", "$(flext)/source", "$(PD-devel)/src", ); INSTALL_PATH = "~/Library/Pure Data"; LIBRARY_SEARCH_PATHS = "$(flext)/build"; MACH_O_TYPE = mh_dylib; OTHER_LDFLAGS = ( "-undefined", dynamic_lookup, ); PRODUCT_NAME = py; }; name = Deployment; }; E90EBB0A1ADDC06600CFDB74 /* Default */ = { isa = XCBuildConfiguration; buildSettings = { DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_EXTENSION = pd_darwin; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = "FLEXT_SYS=2"; HEADER_SEARCH_PATHS = ( "$(flext)/source", "$(PD-devel)/src", ); INSTALL_PATH = "~/Library/Pure Data"; LIBRARY_SEARCH_PATHS = "$(flext)/build"; MACH_O_TYPE = mh_dylib; PRODUCT_NAME = py; }; name = Default; }; E93C2D860A5DB6E70023B566 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { DEBUGGING_SYMBOLS = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_EXTENSION = pd_darwin; FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; GCC_ALTIVEC_EXTENSIONS = YES; GCC_MODEL_CPU = G4; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "FLEXT_SYS=2", FLEXT_DEBUG, FLEXT_SHARED, ); GCC_VERSION = com.apple.compilers.llvm.clang.1_0; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(flext)/source", "$(PD)/src", ); INSTALL_PATH = "$(PDApp)/extra"; LIBRARY_SEARCH_PATHS = /usr/local/lib; LIBRARY_STYLE = STATIC; MACH_O_TYPE = mh_dylib; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ( "-undefined", dynamic_lookup, "-lflext-pd_d", "-framework", Python, ); OTHER_REZFLAGS = ""; PRODUCT_NAME = py; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); ZERO_LINK = YES; }; name = Development; }; E93C2D870A5DB6E70023B566 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_EXTENSION = pd_darwin; GCC_ALTIVEC_EXTENSIONS = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_CPU = G4; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "FLEXT_SYS=2", FLEXT_SHARED, ); GCC_VERSION = com.apple.compilers.llvm.clang.1_0; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(flext)/source", "$(PD)/src", ); INSTALL_PATH = "$(PDApp)/extra"; LIBRARY_SEARCH_PATHS = /usr/local/lib; LIBRARY_STYLE = DYNAMIC; MACH_O_TYPE = mh_dylib; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ( "-undefined", dynamic_lookup, "-lflext-pd", ); OTHER_REZFLAGS = ""; PRODUCT_NAME = py; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); ZERO_LINK = NO; }; name = Deployment; }; E93C2D880A5DB6E70023B566 /* Default */ = { isa = XCBuildConfiguration; buildSettings = { DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_EXTENSION = pd_darwin; GCC_ALTIVEC_EXTENSIONS = YES; GCC_MODEL_CPU = G4; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = "FLEXT_SYS=2"; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; HEADER_SEARCH_PATHS = ( "$(flext)/source", "$(PD)/src", ); INSTALL_PATH = "$(PDApp)/extra"; LIBRARY_SEARCH_PATHS = /usr/local/lib; LIBRARY_STYLE = DYNAMIC; MACH_O_TYPE = mh_dylib; OTHER_CFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = py; SECTORDER_FLAGS = ""; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); }; name = Default; }; E93C2D8A0A5DB6E70023B566 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUGGING_SYMBOLS = YES; GCC_ALTIVEC_EXTENSIONS = YES; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "FLEXT_SYS=1", FLEXT_SHARED, ); GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GENERATE_PKGINFO_FILE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(maxsdk)/max-includes", "$(maxsdk)/msp-includes", ); INFOPLIST_FILE = "source/py-Info.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(maxsdk)/max-includes", "$(maxsdk)/msp-includes", ); LIBRARY_STYLE = STATIC; OTHER_CFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = py; SECTORDER_FLAGS = ""; SKIP_INSTALL = YES; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = mxo; ZERO_LINK = YES; }; name = Development; }; E93C2D8B0A5DB6E70023B566 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; GCC_ALTIVEC_EXTENSIONS = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", "FLEXT_SYS=1", FLEXT_SHARED, ); GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GENERATE_PKGINFO_FILE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(maxsdk)/max-includes", "$(maxsdk)/msp-includes", ); INFOPLIST_FILE = "source/py-Info.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(maxsdk)/max-includes", "$(maxsdk)/msp-includes", ); OTHER_CFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = py; SECTORDER_FLAGS = ""; SKIP_INSTALL = YES; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = mxo; ZERO_LINK = NO; }; name = Deployment; }; E93C2D8C0A5DB6E70023B566 /* Default */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; GCC_ALTIVEC_EXTENSIONS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = "FLEXT_SYS=1"; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GENERATE_PKGINFO_FILE = YES; HEADER_SEARCH_PATHS = ( "$(flext)/source", "$(MaxSDK)/max-includes", "$(MaxSDK)/msp-includes", ); INFOPLIST_FILE = "py-Info.plist"; LIBRARY_SEARCH_PATHS = ( "$(MaxSDK)/max-includes", "$(MaxSDK)/msp-includes", ); OTHER_CFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = py; SECTORDER_FLAGS = ""; SKIP_INSTALL = YES; WARNING_CFLAGS = ( "-Wmost", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); WRAPPER_EXTENSION = mxo; }; name = Default; }; E93C2D8E0A5DB6E70023B566 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; COPY_PHASE_STRIP = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", _DEBUG, PY_NUMPY, xPY_USE_GIL, FLEXT_THREADS, FLEXT_USE_CMEM, ); GCC_VERSION = ""; HEADER_SEARCH_PATHS = ( "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/core/include", "$(flext)/source", ); MACOSX_DEPLOYMENT_TARGET = 10.6; }; name = Development; }; E93C2D8F0A5DB6E70023B566 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NDEBUG, PY_NUMPY, xPY_USE_GIL, FLEXT_THREADS, FLEXT_USE_CMEM, ); HEADER_SEARCH_PATHS = "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/core/include"; MACOSX_DEPLOYMENT_TARGET = 10.6; }; name = Deployment; }; E93C2D900A5DB6E70023B566 /* Default */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_PREPROCESSOR_DEFINITIONS = PY_NUMPY; MACOSX_DEPLOYMENT_TARGET = 10.6; }; name = Default; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ E90EBB071ADDC06600CFDB74 /* Build configuration list for PBXNativeTarget "py.pd_darwin (inline)" */ = { isa = XCConfigurationList; buildConfigurations = ( E90EBB081ADDC06600CFDB74 /* Development */, E90EBB091ADDC06600CFDB74 /* Deployment */, E90EBB0A1ADDC06600CFDB74 /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; E93C2D850A5DB6E70023B566 /* Build configuration list for PBXNativeTarget "py.pd_darwin" */ = { isa = XCConfigurationList; buildConfigurations = ( E93C2D860A5DB6E70023B566 /* Development */, E93C2D870A5DB6E70023B566 /* Deployment */, E93C2D880A5DB6E70023B566 /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; E93C2D890A5DB6E70023B566 /* Build configuration list for PBXNativeTarget "py" */ = { isa = XCConfigurationList; buildConfigurations = ( E93C2D8A0A5DB6E70023B566 /* Development */, E93C2D8B0A5DB6E70023B566 /* Deployment */, E93C2D8C0A5DB6E70023B566 /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; E93C2D8D0A5DB6E70023B566 /* Build configuration list for PBXProject "py" */ = { isa = XCConfigurationList; buildConfigurations = ( E93C2D8E0A5DB6E70023B566 /* Development */, E93C2D8F0A5DB6E70023B566 /* Deployment */, E93C2D900A5DB6E70023B566 /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; /* End XCConfigurationList section */ }; rootObject = 089C1669FE841209C02AAC07 /* Project object */; } py/gpl.txt0000644000175000017500000003545213104443402013267 0ustar zmoelnigzmoelnig GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS py/license.txt0000644000175000017500000000373613104443402014127 0ustar zmoelnigzmoelnigpy/pyext - python script objects for PD and MaxMSP Copyright (C) 2002-2008 Thomas Grill This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. In the official py/pyext distribution, the GNU General Public License is in the file gpl.txt --------------------------------------------------------- OTHER COPYRIGHT NOTICES --------------------------------------------------------- This package uses the flext C++ layer - See its license text below: --- flext ---------------------------------------------- flext - C++ layer for Max/MSP and pd (pure data) externals Copyright (C) 2001-2008 Thomas Grill This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. In the official flext distribution, the GNU General Public License is in the file gpl.txt py/maxmsp/0000755000175000017500000000000013104443402013240 5ustar zmoelnigzmoelnigpy/maxmsp/thread-1.mxb0000644000175000017500000000601013104443402015352 0ustar zmoelnigzmoelnigpmaxqv2 r#NsvpatcherX0z t#PuwindowvsetfontwSans Serif$A txcomment^P ‹yfullyzparallel txNP ‹{with|threads t}newex‚ ‹~tbR t1buttono_P t1user1umenuB.$‹S@)Q 1#X1setrgbRPÖóHÿÿÿÿÿÿÿÿÿPPPÿÿÿ 11add1license t1hidden}&# ‹~1open t1}B&- ‹1pcontrol rsr8P t1originPR t11inlet[_P tuvw$A txê' ‹1This1package1uses1the1 flext1!C++1"layer1#and1$some1%code1&snippets1'from1(pd1)(pure1*data).1+See111,texts1-below: 1.#B1/color\ tx1} ‹110program11is12free13software14;15you16can17redistribute18it19and/or1:modify181;under11GNU1?General1@Public1ALicense1Bas1Cpublished1Dby11EFree1FSoftware1GFoundation141Heither1IversionR1=11A1J,1Kor1L(at1Myour1Noption)1Oany1Plater1Qversion.110111Rdistributed1Sin11Thope1Uthat181Vwill1Wbe1Xuseful1J1Ybut1ZWITHOUT1[ANY1\WARRANTY141]without1^even11_implied1`warranty1=1aMERCHANTABILITY1K1bFITNESS1cFOR1dA1ePARTICULAR1fPURPOSE.1+11>1?1@1A1gfor1hmore1idetails.1jYou1kshould1lhave1mreceived1na1ocopy1=11>1?1@1A1palong{1qthis10141rif1snot1J1twrite1uto11E1F1G1J1vInc.1J;1wTemple1xPlace1y-1zSuiteJ1J1{Boston1J1|MA1}02111-13071J1~USA.1In11€official1xsample1‚distribution1J11>1?1@1A111S11ƒfile1„gpl.txt tx{ ‹11y1…extended1†sample1‡objects1g1ˆMax/MSP1#1(1)1‰data)1ŠCopyright1‹(C)1Œ2001-20031Thomas1ŽGrill 1.1/\ txÙ' ‹1OTHER1COPYRIGHT1‘NOTICES 1.1/\ tx ‹1 1y1!1"1g1ˆ1#1(1)1‰1’externals1Š1‹1“2001-Ó11Ž1101112131415161718191:181;11<1=11>1?1@1A1B1C1D11E1F1G141H1IR1=11A1J1K1L1M1N1O1P1Q110111R1S11T1U181V1W1X1J1Y1Z1[1\141]1^11_1`1=1a1K1b1c1d1e1f1+11>1?1@1A1g1h1i1j1k1l1m1n1o1=11>1?1@1A1p{1q10141r1s1J1t1u11E1F1G1J1v1J;1w1x1y1zJ1J1{1J1|1}1J1~111€1 1‚1J11>1?1@1A111S11ƒ1„ tx ‹1”---1 1•---------------------------------------------- t1–pop t11—newobjq'D ‹1˜p1™GPL1 tx. ‹1šread1 tuvw$ÀA tx[Y׋1›pyext1œ/1thread-1 tuvw$A tx[*ü ‹1žPython1’1y1Ÿthreading1 example txoOP ‹15161^1¡stop1¢it... tuvw$ A t}K™ ‹1›|1£ex11¤@detachQ 1.1/^ tuvw$A tx®]P ‹1¥non-blocking tx®MP ‹{| tx>]P ‹1”1¦blocking!1” t}» ‹~Q t}W ‹~P t1ºn_P t1Wn_P t1§messagern ‹1¡ t1§'Ö ‹1¨doc+ t1§^Ö ‹1©doc t1§¿ ‹1ªhelp tuvw$`A t1«number¨ #^PPP‹PPPÝÝÝÞÞÞPPP t1«b #^PPP‹PPPÝÝÝÞÞÞPPP tuvw$A t1§Y¸; ‹1¬detach1­$1 tuvw$`A t}`Ó—‹1›|1£ 1.1/^ txl#d‹1®watch1¯that! tuvw$A tx>MP ‹1]| t11°panelUWì4 11±brgbóH 11²frgbPPP 11³borderP 11´roundedP 11µshadowP 11¶done txLôn ‹11¬1·state161W1¸given1B1¹an1ºattribute t1»connect\P^P t1»QUP t1»^QUP t1»_QUP t1»UPTP t11»XPTP t11»ZPTP t11»YPTP t1»[PTP t1»TPVP t1»PTQ t1»_PTQ t1»^PTQ t1»TQWP t1»]P_P t1»PTR t1»^PTR t1»_PTR t1»PP t11»PP t11»PP t11»PP t1– py/maxmsp/py.maxhelp0000644000175000017500000010612713104443402015257 0ustar zmoelnigzmoelnig{ "patcher" : { "fileversion" : 1, "appversion" : { "major" : 5, "minor" : 1, "revision" : 9 } , "rect" : [ 282.0, 229.0, 669.0, 757.0 ], "bglocked" : 0, "defrect" : [ 282.0, 229.0, 669.0, 757.0 ], "openrect" : [ 0.0, 0.0, 0.0, 0.0 ], "openinpresentation" : 0, "default_fontsize" : 12.0, "default_fontface" : 0, "default_fontname" : "Arial", "gridonopen" : 0, "gridsize" : [ 15.0, 15.0 ], "gridsnaponopen" : 0, "toolbarvisible" : 1, "boxanimatetime" : 200, "imprint" : 0, "enablehscroll" : 1, "enablevscroll" : 1, "devicewidth" : 0.0, "boxes" : [ { "box" : { "maxclass" : "message", "text" : "size 1000", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 477.0, 1089.0, 62.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-85" } } , { "box" : { "maxclass" : "message", "text" : "add buffer3 buffer1 buffer2", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 25.272558, 1114.80603, 152.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-81", "presentation_rect" : [ 25.272558, 1114.80603, 0.0, 0.0 ] } } , { "box" : { "maxclass" : "message", "text" : "reload.", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 7.0, 1065.0, 47.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-74" } } , { "box" : { "maxclass" : "newobj", "text" : "loadbang", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 266.272583, 1045.0, 60.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "bang" ], "fontname" : "Arial", "id" : "obj-9" } } , { "box" : { "maxclass" : "toggle", "numinlets" : 1, "patching_rect" : [ 214.5, 1235.0, 20.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "int" ], "id" : "obj-82" } } , { "box" : { "maxclass" : "newobj", "text" : "gate~", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 214.5, 1264.583496, 41.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "signal" ], "fontname" : "Arial", "id" : "obj-77" } } , { "box" : { "maxclass" : "newobj", "text" : "cycle~ 440", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 236.5, 1235.0, 68.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "signal" ], "fontname" : "Arial", "id" : "obj-76" } } , { "box" : { "maxclass" : "ezdac~", "numinlets" : 2, "patching_rect" : [ 208.772568, 1296.583496, 45.0, 45.0 ], "numoutlets" : 0, "id" : "obj-75" } } , { "box" : { "maxclass" : "message", "text" : "set gain 0.5", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 100.77256, 1262.583496, 53.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-37" } } , { "box" : { "maxclass" : "newobj", "text" : "pyext 1 0 sig gain", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 38.77256, 1296.583496, 104.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-39" } } , { "box" : { "maxclass" : "comment", "text" : "Signal Example", "fontsize" : 14.0, "numinlets" : 1, "patching_rect" : [ 15.272558, 1230.583496, 174.0, 23.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-71" } } , { "box" : { "maxclass" : "number", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 480.0, 944.0, 50.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "int", "bang" ], "fontname" : "Arial", "id" : "obj-79" } } , { "box" : { "maxclass" : "newobj", "text" : "s TestSend2", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 479.0, 975.0, 76.0, 20.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-80" } } , { "box" : { "maxclass" : "number", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 181.493576, 890.0, 50.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "int", "bang" ], "fontname" : "Arial", "id" : "obj-78" } } , { "box" : { "maxclass" : "number", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 385.0, 944.0, 50.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "int", "bang" ], "fontname" : "Arial", "id" : "obj-72" } } , { "box" : { "maxclass" : "newobj", "text" : "s TestSend1", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 384.0, 975.0, 76.0, 20.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-70" } } , { "box" : { "maxclass" : "newobj", "text" : "print TestSend2", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 480.0, 903.0, 94.0, 20.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-69" } } , { "box" : { "maxclass" : "newobj", "text" : "print TestSend1", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 385.0, 903.0, 94.0, 20.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-68" } } , { "box" : { "maxclass" : "newobj", "text" : "r TestSend2", "fontsize" : 12.0, "numinlets" : 0, "patching_rect" : [ 480.0, 860.303955, 74.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-63" } } , { "box" : { "maxclass" : "newobj", "text" : "r TestSend1", "fontsize" : 12.0, "numinlets" : 0, "patching_rect" : [ 385.0, 860.303955, 74.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-62" } } , { "box" : { "maxclass" : "newobj", "text" : "print Sendrecv", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 42.493576, 960.534729, 88.0, 20.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-49" } } , { "box" : { "maxclass" : "newobj", "text" : "py sendrecv ex2 TestSend1", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 42.493576, 932.303955, 158.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-55" } } , { "box" : { "maxclass" : "comment", "text" : "Sendrecv Example", "fontsize" : 14.0, "numinlets" : 1, "patching_rect" : [ 21.0, 844.303955, 174.0, 23.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-60" } } , { "box" : { "maxclass" : "message", "text" : "ret1", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 30.0, 673.769226, 32.5, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-33" } } , { "box" : { "maxclass" : "message", "text" : "strcat abc def", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 122.75, 727.769226, 83.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-7" } } , { "box" : { "maxclass" : "message", "text" : "strlen supercalafragialisticexpialadocious", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 115.993576, 697.769226, 228.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-6" } } , { "box" : { "maxclass" : "newobj", "text" : "print script", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 42.493576, 756.0, 66.0, 20.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-5" } } , { "box" : { "maxclass" : "message", "text" : "numargs a b c", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 88.493576, 673.769226, 87.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-65" } } , { "box" : { "maxclass" : "newobj", "text" : "py script", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 42.493576, 727.769226, 55.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "", "" ], "fontname" : "Arial", "id" : "obj-66" } } , { "box" : { "maxclass" : "comment", "text" : "Script Example", "fontsize" : 14.0, "numinlets" : 1, "patching_rect" : [ 21.0, 639.769226, 174.0, 23.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-67" } } , { "box" : { "maxclass" : "message", "text" : "mul buffer3 buffer1 buffer2", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 26.272558, 1090.80603, 151.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-64" } } , { "box" : { "maxclass" : "waveform~", "setunit" : 1, "numinlets" : 5, "selectioncolor" : [ 0.313726, 0.498039, 0.807843, 0.0 ], "patching_rect" : [ 475.272583, 1141.80603, 134.0, 48.594055 ], "numoutlets" : 6, "bgcolor" : [ 0.501961, 0.717647, 0.764706, 1.0 ], "outlettype" : [ "float", "float", "float", "float", "list", "" ], "buffername" : "buffer3", "tickmarkcolor" : [ 0.352941, 0.337255, 0.521569, 1.0 ], "id" : "obj-59", "textcolor" : [ ], "waveformcolor" : [ 0.082353, 0.25098, 0.431373, 1.0 ], "labelbgcolor" : [ 0.352941, 0.337255, 0.521569, 1.0 ] } } , { "box" : { "maxclass" : "newobj", "text" : "buffer~ buffer3", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 475.272583, 1112.103027, 88.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "float", "bang" ], "fontname" : "Arial", "id" : "obj-61" } } , { "box" : { "maxclass" : "waveform~", "setunit" : 1, "numinlets" : 5, "selectioncolor" : [ 0.313726, 0.498039, 0.807843, 0.0 ], "patching_rect" : [ 332.272583, 1141.80603, 134.0, 48.594055 ], "numoutlets" : 6, "bgcolor" : [ 0.501961, 0.717647, 0.764706, 1.0 ], "outlettype" : [ "float", "float", "float", "float", "list", "" ], "buffername" : "buffer2", "tickmarkcolor" : [ 0.352941, 0.337255, 0.521569, 1.0 ], "id" : "obj-58", "textcolor" : [ ], "waveformcolor" : [ 0.082353, 0.25098, 0.431373, 1.0 ], "labelbgcolor" : [ 0.352941, 0.337255, 0.521569, 1.0 ] } } , { "box" : { "maxclass" : "message", "text" : "read rainstick.aif", "fontsize" : 13.0, "numinlets" : 2, "patching_rect" : [ 332.272583, 1087.80603, 105.0, 19.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-56" } } , { "box" : { "maxclass" : "newobj", "text" : "buffer~ buffer2", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 332.272583, 1112.103027, 88.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "float", "bang" ], "fontname" : "Arial", "id" : "obj-57" } } , { "box" : { "maxclass" : "message", "text" : "read drumLoop.aif", "fontsize" : 13.0, "numinlets" : 2, "patching_rect" : [ 187.272568, 1087.80603, 119.0, 19.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-8" } } , { "box" : { "maxclass" : "waveform~", "setunit" : 1, "numinlets" : 5, "selectioncolor" : [ 0.313726, 0.498039, 0.807843, 0.0 ], "patching_rect" : [ 187.272568, 1141.80603, 134.0, 48.594055 ], "numoutlets" : 6, "bgcolor" : [ 0.501961, 0.717647, 0.764706, 1.0 ], "outlettype" : [ "float", "float", "float", "float", "list", "" ], "buffername" : "buffer1", "tickmarkcolor" : [ 0.352941, 0.337255, 0.521569, 1.0 ], "id" : "obj-73", "textcolor" : [ ], "waveformcolor" : [ 0.082353, 0.25098, 0.431373, 1.0 ], "labelbgcolor" : [ 0.352941, 0.337255, 0.521569, 1.0 ] } } , { "box" : { "maxclass" : "newobj", "text" : "buffer~ buffer1", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 187.272568, 1112.103027, 88.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "float", "bang" ], "fontname" : "Arial", "id" : "obj-53" } } , { "box" : { "maxclass" : "newobj", "text" : "py buffer", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 37.272556, 1159.80603, 57.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "", "" ], "fontname" : "Arial", "id" : "obj-52" } } , { "box" : { "maxclass" : "comment", "text" : "Buffer Example", "fontsize" : 14.0, "numinlets" : 1, "patching_rect" : [ 15.772556, 1031.80603, 174.0, 23.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-51" } } , { "box" : { "maxclass" : "message", "text" : "threeargs foo bar maz", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 250.5, 477.0, 128.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-47" } } , { "box" : { "maxclass" : "message", "text" : "onearg start", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 250.5, 428.0, 75.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-45" } } , { "box" : { "maxclass" : "message", "text" : "twoargs 1 2", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 250.5, 452.0, 73.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-43" } } , { "box" : { "maxclass" : "message", "text" : "banana", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 177.25, 477.0, 51.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-36" } } , { "box" : { "maxclass" : "message", "text" : "ho", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 177.25, 452.0, 32.5, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-35" } } , { "box" : { "maxclass" : "message", "text" : "hey", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 177.25, 428.0, 32.5, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-34" } } , { "box" : { "maxclass" : "message", "text" : "1 2 3 foo", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 77.5, 491.0, 57.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-50" } } , { "box" : { "maxclass" : "flonum", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 49.0, 428.0, 50.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "float", "bang" ], "fontname" : "Arial", "id" : "obj-48" } } , { "box" : { "maxclass" : "number", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 68.5, 461.0, 50.0, 20.0 ], "numoutlets" : 2, "outlettype" : [ "int", "bang" ], "fontname" : "Arial", "id" : "obj-46" } } , { "box" : { "maxclass" : "button", "numinlets" : 1, "patching_rect" : [ 21.0, 461.0, 20.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "bang" ], "id" : "obj-44" } } , { "box" : { "maxclass" : "comment", "text" : "Simple Example", "fontsize" : 14.0, "numinlets" : 1, "patching_rect" : [ 21.0, 398.0, 174.0, 23.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-42" } } , { "box" : { "maxclass" : "newobj", "text" : "print simple", "fontsize" : 12.0, "numinlets" : 1, "patching_rect" : [ 30.0, 560.0, 72.0, 20.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-41" } } , { "box" : { "maxclass" : "comment", "text" : "Threading Example", "fontsize" : 14.0, "numinlets" : 1, "patching_rect" : [ 9.5, 75.0, 173.0, 23.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-40" } } , { "box" : { "maxclass" : "newobj", "text" : "pyext simple ex1", "fontsize" : 12.0, "numinlets" : 4, "patching_rect" : [ 30.0, 531.0, 100.0, 20.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-38" } } , { "box" : { "maxclass" : "comment", "text" : "fully parallel", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 254.0, 120.0, 80.0, 17.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-1" } } , { "box" : { "maxclass" : "comment", "text" : "with threads", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 254.0, 104.0, 80.0, 17.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-2" } } , { "box" : { "maxclass" : "newobj", "text" : "t b 2", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 267.0, 156.0, 27.0, 17.0 ], "numoutlets" : 2, "outlettype" : [ "bang", "int" ], "fontname" : "Arial", "id" : "obj-3" } } , { "box" : { "maxclass" : "button", "numinlets" : 1, "patching_rect" : [ 266.0, 137.0, 15.0, 15.0 ], "numoutlets" : 1, "outlettype" : [ "bang" ], "id" : "obj-4" } } , { "box" : { "maxclass" : "comment", "text" : "py and pyext", "fontsize" : 24.0, "numinlets" : 1, "patching_rect" : [ 11.0, 9.0, 215.0, 34.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-10" } } , { "box" : { "maxclass" : "comment", "text" : "Python externals ", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 11.0, 42.0, 252.0, 17.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-11" } } , { "box" : { "maxclass" : "comment", "text" : "you can even stop it...", "linecount" : 2, "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 350.0, 105.0, 80.0, 27.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-12" } } , { "box" : { "maxclass" : "newobj", "text" : "pyext threads ex1 @detach 1", "fontsize" : 10.0, "numinlets" : 3, "patching_rect" : [ 285.0, 241.0, 141.0, 18.0 ], "numoutlets" : 3, "outlettype" : [ "", "", "" ], "fontname" : "Arial", "color" : [ 1.0, 0.360784, 0.682353, 1.0 ], "id" : "obj-13" } } , { "box" : { "maxclass" : "comment", "text" : "non-blocking", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 157.0, 119.0, 80.0, 17.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-14" } } , { "box" : { "maxclass" : "comment", "text" : "with threads", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 157.0, 103.0, 80.0, 17.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-15" } } , { "box" : { "maxclass" : "comment", "text" : "--- blocking! ---", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 45.0, 119.0, 80.0, 17.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-16" } } , { "box" : { "maxclass" : "newobj", "text" : "t b 1", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 170.0, 155.0, 27.0, 17.0 ], "numoutlets" : 2, "outlettype" : [ "bang", "int" ], "fontname" : "Arial", "id" : "obj-17" } } , { "box" : { "maxclass" : "newobj", "text" : "t b 0", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 70.0, 155.0, 27.0, 17.0 ], "numoutlets" : 2, "outlettype" : [ "bang", "int" ], "fontname" : "Arial", "id" : "obj-18" } } , { "box" : { "maxclass" : "button", "numinlets" : 1, "patching_rect" : [ 169.0, 136.0, 15.0, 15.0 ], "numoutlets" : 1, "outlettype" : [ "bang" ], "id" : "obj-19" } } , { "box" : { "maxclass" : "button", "numinlets" : 1, "patching_rect" : [ 70.0, 136.0, 15.0, 15.0 ], "numoutlets" : 1, "outlettype" : [ "bang" ], "id" : "obj-20" } } , { "box" : { "maxclass" : "message", "text" : "stop", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 353.0, 136.0, 31.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-21" } } , { "box" : { "maxclass" : "message", "text" : "doc+", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 21.0, 209.53334, 35.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-22" } } , { "box" : { "maxclass" : "message", "text" : "doc", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 21.0, 185.266663, 28.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-23" } } , { "box" : { "maxclass" : "message", "text" : "help", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 21.0, 161.0, 39.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-24" } } , { "box" : { "maxclass" : "number", "fontsize" : 14.0, "htextcolor" : [ 0.870588, 0.870588, 0.870588, 1.0 ], "numinlets" : 1, "patching_rect" : [ 151.0, 292.0, 35.0, 23.0 ], "numoutlets" : 2, "bgcolor" : [ 0.866667, 0.866667, 0.866667, 1.0 ], "outlettype" : [ "int", "bang" ], "fontname" : "Arial", "triscale" : 0.9, "id" : "obj-25" } } , { "box" : { "maxclass" : "number", "fontsize" : 14.0, "htextcolor" : [ 0.870588, 0.870588, 0.870588, 1.0 ], "numinlets" : 1, "patching_rect" : [ 81.0, 293.0, 35.0, 23.0 ], "numoutlets" : 2, "bgcolor" : [ 0.866667, 0.866667, 0.866667, 1.0 ], "outlettype" : [ "int", "bang" ], "fontname" : "Arial", "triscale" : 0.9, "id" : "obj-26" } } , { "box" : { "maxclass" : "message", "text" : "detach $1", "fontsize" : 12.0, "numinlets" : 2, "patching_rect" : [ 72.0, 210.0, 75.0, 18.0 ], "numoutlets" : 1, "outlettype" : [ "" ], "fontname" : "Arial", "id" : "obj-27" } } , { "box" : { "maxclass" : "newobj", "text" : "pyext threads ex1", "fontsize" : 14.0, "numinlets" : 3, "patching_rect" : [ 79.0, 237.0, 121.0, 23.0 ], "numoutlets" : 3, "outlettype" : [ "", "", "" ], "fontname" : "Arial", "color" : [ 1.0, 0.360784, 0.682353, 1.0 ], "id" : "obj-28" } } , { "box" : { "maxclass" : "comment", "text" : "watch that!", "fontsize" : 14.0, "numinlets" : 1, "patching_rect" : [ 91.0, 317.0, 100.0, 23.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-29" } } , { "box" : { "maxclass" : "comment", "text" : "without threads", "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 45.0, 103.0, 80.0, 17.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-30" } } , { "box" : { "maxclass" : "panel", "numinlets" : 1, "patching_rect" : [ 5.0, 7.0, 626.0, 61.0 ], "grad1" : [ 0.633501, 0.929412, 0.919324, 1.0 ], "numoutlets" : 0, "bgcolor" : [ 0.952941, 0.564706, 0.282353, 1.0 ], "mode" : 1, "grad2" : [ 0.219255, 0.350905, 0.347096, 1.0 ], "id" : "obj-31" } } , { "box" : { "maxclass" : "comment", "text" : "the detach state can be given as an attribute", "linecount" : 2, "fontsize" : 9.0, "numinlets" : 1, "patching_rect" : [ 286.0, 210.0, 110.0, 27.0 ], "numoutlets" : 0, "fontname" : "Arial", "id" : "obj-32" } } ], "lines" : [ { "patchline" : { "source" : [ "obj-37", 0 ], "destination" : [ "obj-39", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-9", 0 ], "destination" : [ "obj-85", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-85", 0 ], "destination" : [ "obj-61", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-81", 0 ], "destination" : [ "obj-52", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-74", 0 ], "destination" : [ "obj-52", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-64", 0 ], "destination" : [ "obj-52", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-34", 0 ], "destination" : [ "obj-38", 2 ], "hidden" : 0, "midpoints" : [ 186.75, 447.0, 146.5, 447.0, 146.5, 528.0, 93.5, 528.0 ] } } , { "patchline" : { "source" : [ "obj-35", 0 ], "destination" : [ "obj-38", 2 ], "hidden" : 0, "midpoints" : [ 186.75, 471.0, 146.5, 471.0, 146.5, 528.0, 93.5, 528.0 ] } } , { "patchline" : { "source" : [ "obj-36", 0 ], "destination" : [ "obj-38", 2 ], "hidden" : 0, "midpoints" : [ 186.75, 528.0, 93.5, 528.0 ] } } , { "patchline" : { "source" : [ "obj-38", 0 ], "destination" : [ "obj-41", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-43", 0 ], "destination" : [ "obj-38", 3 ], "hidden" : 0, "midpoints" : [ 260.0, 519.0, 120.5, 519.0 ] } } , { "patchline" : { "source" : [ "obj-44", 0 ], "destination" : [ "obj-38", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-45", 0 ], "destination" : [ "obj-38", 3 ], "hidden" : 0, "midpoints" : [ 260.0, 521.0, 120.5, 521.0 ] } } , { "patchline" : { "source" : [ "obj-46", 0 ], "destination" : [ "obj-38", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-47", 0 ], "destination" : [ "obj-38", 3 ], "hidden" : 0, "midpoints" : [ 260.0, 521.5, 120.5, 521.5 ] } } , { "patchline" : { "source" : [ "obj-48", 0 ], "destination" : [ "obj-38", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-50", 0 ], "destination" : [ "obj-38", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-3", 0 ], "destination" : [ "obj-28", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-3", 0 ], "destination" : [ "obj-28", 2 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-28", 0 ], "destination" : [ "obj-26", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-28", 1 ], "destination" : [ "obj-25", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-27", 0 ], "destination" : [ "obj-28", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-24", 0 ], "destination" : [ "obj-28", 0 ], "hidden" : 1, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-23", 0 ], "destination" : [ "obj-28", 0 ], "hidden" : 1, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-22", 0 ], "destination" : [ "obj-28", 0 ], "hidden" : 1, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-21", 0 ], "destination" : [ "obj-28", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-18", 0 ], "destination" : [ "obj-28", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-18", 0 ], "destination" : [ "obj-28", 2 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-17", 0 ], "destination" : [ "obj-28", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-17", 0 ], "destination" : [ "obj-28", 2 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-33", 0 ], "destination" : [ "obj-66", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-6", 0 ], "destination" : [ "obj-66", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-65", 0 ], "destination" : [ "obj-66", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-66", 0 ], "destination" : [ "obj-5", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-7", 0 ], "destination" : [ "obj-66", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-9", 0 ], "destination" : [ "obj-8", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-9", 0 ], "destination" : [ "obj-56", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-82", 0 ], "destination" : [ "obj-77", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-8", 0 ], "destination" : [ "obj-53", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-79", 0 ], "destination" : [ "obj-80", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-78", 0 ], "destination" : [ "obj-55", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-77", 0 ], "destination" : [ "obj-75", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-77", 0 ], "destination" : [ "obj-75", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-76", 0 ], "destination" : [ "obj-77", 1 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-72", 0 ], "destination" : [ "obj-70", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-63", 0 ], "destination" : [ "obj-69", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-62", 0 ], "destination" : [ "obj-68", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-56", 0 ], "destination" : [ "obj-57", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-55", 0 ], "destination" : [ "obj-49", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-4", 0 ], "destination" : [ "obj-3", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-3", 1 ], "destination" : [ "obj-27", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-20", 0 ], "destination" : [ "obj-18", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-19", 0 ], "destination" : [ "obj-17", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-18", 1 ], "destination" : [ "obj-27", 0 ], "hidden" : 0, "midpoints" : [ ] } } , { "patchline" : { "source" : [ "obj-17", 1 ], "destination" : [ "obj-27", 0 ], "hidden" : 0, "midpoints" : [ ] } } ] } } py/maxmsp/py-objectmappings.txt0000644000175000017500000000071413104443402017436 0ustar zmoelnigzmoelnigmax objectfile py py; max objectfile py. py; max objectfile pyext py; max objectfile pyext. py; max objectfile pyx py; max objectfile pyx. py; max objectfile pyext~ py; max objectfile pyext.~ py; max objectfile pyx~ py; max objectfile pyx.~ py; max objectfile pym py; max oblist python py; max oblist python py.; max oblist python pyext; max oblist python pyext.; max oblist python pyext~; max oblist python pyext.~; max oblist python pym; py/pd/0000755000175000017500000000000013104443402012336 5ustar zmoelnigzmoelnigpy/pd/sendrecv-1.pd0000644000175000017500000000161613104443402014636 0ustar zmoelnigzmoelnig#N canvas 145 126 658 333 12; #X msg 125 81 reload mi ma; #X floatatom 48 238 5 0 0 0 - - -; #X floatatom 297 239 5 0 0 0 - - -; #X obj 297 263 s mi; #X floatatom 143 265 5 0 0 0 - - -; #X floatatom 382 267 5 0 0 0 - - -; #X obj 382 240 r ma; #X obj 48 262 s he; #X obj 143 238 r hu; #X text 247 81 reload with different args; #X msg 20 82 help; #X msg 19 114 doc; #X msg 58 114 doc+; #X obj 49 165 pyext sendrecv ex1 he hu; #X text 30 218 scroll here; #X text 292 219 or here; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X msg 202 128 bind; #X msg 249 129 unbind; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X text 213 32 http://grrrr.org/ext; #X connect 0 0 13 0; #X connect 1 0 7 0; #X connect 2 0 3 0; #X connect 6 0 5 0; #X connect 8 0 4 0; #X connect 10 0 13 0; #X connect 11 0 13 0; #X connect 12 0 13 0; #X connect 17 0 13 1; #X connect 18 0 13 1; py/pd/simple-2.pd0000644000175000017500000000203113104443402014307 0ustar zmoelnigzmoelnig#N canvas 570 275 788 398 12; #X floatatom 202 113 5 0 0 0 - - -; #X text 338 286 watch the console output!; #X msg 20 115 help; #X text 16 69 This demonstrates message handling. See the simple.py file.; #X msg 19 140 doc; #X msg 55 141 doc+; #X floatatom 259 113 5 0 0 0 - - -; #X msg 169 235 msg 2; #X obj 123 289 pyext simple ex2; #X floatatom 123 334 5 0 0 0 - - -; #X floatatom 240 335 5 0 0 0 - - -; #X msg 100 204 msg 1 3; #X msg 234 220 msg a b; #X msg 120 174 hello; #X msg 193 180 hello; #X msg 266 179 msg; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X text 213 32 http://grrrr.org/ext; #X msg 333 186 whoopie a b c; #X connect 0 0 8 1; #X connect 2 0 8 0; #X connect 4 0 8 0; #X connect 5 0 8 0; #X connect 6 0 8 2; #X connect 7 0 8 2; #X connect 8 0 9 0; #X connect 8 1 10 0; #X connect 11 0 8 1; #X connect 12 0 8 3; #X connect 13 0 8 1; #X connect 14 0 8 3; #X connect 15 0 8 2; #X connect 19 0 8 3; py/pd/simple-1.pd0000644000175000017500000000233013104443402014310 0ustar zmoelnigzmoelnig#N canvas 156 192 682 409 12; #X obj 53 123 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; #X floatatom 52 155 5 0 0 0 - - -; #X text 388 337 watch the console output!; #X msg 52 186 2 3 4; #X msg 277 131 ho; #X msg 233 155 lets; #X msg 283 190 go; #X msg 212 214 !!!; #X msg 205 113 hey; #X obj 183 301 pyext simple ex1; #X msg 434 114 onearg 123; #X msg 456 167 threeargs 9 8 7; #X msg 463 196 varargs 8 4 2 1; #X msg 447 140 twoargs 41 15; #X msg 453 239 twoargs 1 2 3; #X msg 71 299 help; #X text 16 69 This demonstrates message handling. See the simple.py file.; #X text 232 322 file class; #X msg 70 324 doc; #X msg 106 325 doc+; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 213 32 http://grrrr.org/ext; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X msg 41 246 reload; #X connect 0 0 9 1; #X connect 1 0 9 1; #X connect 3 0 9 1; #X connect 4 0 9 2; #X connect 5 0 9 2; #X connect 6 0 9 2; #X connect 7 0 9 2; #X connect 8 0 9 2; #X connect 10 0 9 3; #X connect 11 0 9 3; #X connect 12 0 9 3; #X connect 13 0 9 3; #X connect 14 0 9 3; #X connect 15 0 9 0; #X connect 18 0 9 0; #X connect 19 0 9 0; #X connect 23 0 9 0; py/pd/buffer-2.pd0000644000175000017500000000261513104443402014277 0ustar zmoelnigzmoelnig#N canvas 608 159 694 442 12; #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 how to resize buffers; #N canvas 0 0 450 300 graph1 0; #X array array1 42 float 3; #A 0 0 0 0 0 0.0285715 0.0857145 0.128572 0.171429 0.257144 0.314287 0.385715 0.385715 0.385715 0.385715 0.385715 0.37143 0.342858 0.314287 0.228572 0.128572 0.0428573 -0.0857145 -0.200001 -0.285715 -0.328572 -0.357144 -0.400001 -0.428573 -0.428573 -0.457144 -0.457144 -0.457144 -0.457144 -0.457144 -0.457144 -0.457144 -0.457144 -0.457144 -0.414287 -0.342858 -0.314287 1.02445e-007; #X coords 0 1 42 -1 200 140 1; #X restore 413 259 graph; #X msg 40 148 symbol array1; #X obj 40 194 py pyext.Buffer @py 1; #X obj 143 238 nbx 5 14 0 100 0 1 empty empty empty 0 -6 0 10 -260818 -1 -1 42 256; #X obj 143 260 t b f; #X obj 39 287 pym 2 resize @py 1; #X obj 40 120 loadbang; #X text 37 310 returns buffer object; #X obj 41 361 py .len; #X text 111 361 call __builtin__.len; #X text 222 192 create Buffer object; #X obj 41 394 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -261681 -1 -1 0 256; #X connect 5 0 6 1; #X connect 6 0 9 1; #X connect 7 0 8 0; #X connect 8 0 9 0; #X connect 8 1 9 2; #X connect 9 0 12 1; #X connect 10 0 5 0; #X connect 12 0 15 0; py/pd/methods-1.pd0000644000175000017500000000154613104443402014472 0ustar zmoelnigzmoelnig#N canvas 540 469 734 369 12; #X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 235 32 http://grrrr.org/ext; #X symbolatom 21 139 10 0 0 0 - - -; #X symbolatom 25 298 10 0 0 0 - - -; #X obj 22 179 py .str @py 1; #X text 145 170 convert the symbol to a Python string; #X text 35 216 pass it as a true Python object; #X symbolatom 364 295 10 0 0 0 - - -; #X text 462 269 use module function; #X text 23 119 enter some text; #X text 145 187 using the built-in str function; #X obj 25 252 pym swapcase; #X text 63 270 use swapcase method; #X obj 363 250 py string.swapcase; #X text 235 16 Python script objects \, (C)2003-2006 Thomas Grill; #X text 21 73 Py can act on Python objects in an object-oriented manner ; #X connect 2 0 4 1; #X connect 4 0 11 1; #X connect 4 0 13 1; #X connect 11 0 3 0; #X connect 13 0 7 0; py/pd/sig-1.pd0000644000175000017500000000157713104443402013615 0ustar zmoelnigzmoelnig#N canvas 52 147 663 315 12; #X obj 56 234 dac~; #X msg 523 211 \; pd dsp 1; #X obj 524 184 loadbang; #X obj 194 114 hsl 128 15 0.01 1 1 1 empty empty gain -2 -6 0 8 -225271 -1 -1 11200 1; #X obj 89 116 noise~; #X msg 21 116 reload; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 213 32 http://grrrr.org/ext; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X text 17 66 This demonstrates signal support. See the sig.py file. ; #X obj 191 131 nbx 5 14 0.001 1 1 0 empty empty empty 0 -6 0 10 -225271 -1 -1 0.58047 256; #X msg 192 148 set gain \$1; #X text 123 202 message inlets \, outlets; #X text 123 217 signal inlets \, outlets; #X obj 67 181 pyext~ 0 0 1 1 sig gain2; #X connect 2 0 1 0; #X connect 3 0 10 0; #X connect 4 0 14 0; #X connect 5 0 14 0; #X connect 10 0 11 0; #X connect 11 0 14 0; #X connect 14 0 0 0; #X connect 14 0 0 1; py/pd/pak.pd0000644000175000017500000000177113104443402013444 0ustar zmoelnigzmoelnig#N canvas 463 293 282 232 12; #X obj 17 32 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 47 256; #X obj 34 52 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 182 256; #X obj 56 68 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 86 256; #X obj 68 88 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 31 256; #X obj 118 29 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 117 256; #X obj 135 49 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 0 256; #X obj 157 65 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 86 256; #X obj 169 85 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 0 256; #X obj 36 168 print; #X obj 37 129 pyx. pak 8; #X connect 0 0 9 1; #X connect 1 0 9 2; #X connect 2 0 9 3; #X connect 3 0 9 4; #X connect 4 0 9 5; #X connect 5 0 9 6; #X connect 6 0 9 7; #X connect 7 0 9 8; #X connect 9 0 8 0; py/pd/simple-3.pd0000644000175000017500000000172313104443402014317 0ustar zmoelnigzmoelnig#N canvas 136 275 657 369 12; #X msg 73 266 help; #X text 17 80 This demonstrates message handling. See the simple.py file.; #X msg 72 291 doc; #X msg 108 292 doc+; #X floatatom 258 305 5 0 0 0 - - -; #X floatatom 316 119 5 0 0 0 - - -; #X floatatom 399 119 5 0 0 0 - - -; #X msg 24 182 reload.; #X msg 24 210 reload -10; #X text 95 181 reload script and keep arguments; #X text 113 211 reload script with new arguments; #X text 281 140 triggers; #X text 310 304 result; #X text 410 140 sets argument; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X text 213 32 http://grrrr.org/ext; #X obj 210 266 pyext simple.ex3 1; #X text 369 258 the name can also be given in dotted Python style; #X connect 0 0 17 0; #X connect 2 0 17 0; #X connect 3 0 17 0; #X connect 5 0 17 1; #X connect 6 0 17 2; #X connect 7 0 17 0; #X connect 8 0 17 0; #X connect 17 0 4 0; py/pd/sendrecv-3.pd0000644000175000017500000000061613104443402014637 0ustar zmoelnigzmoelnig#N canvas 294 237 648 327 12; #X obj 410 265 pyext sendrecv ex3 @detach 1; #X obj 611 236 bng 25 250 50 0 empty ugh empty 0 -6 0 8 -258699 -1 -1; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X text 213 32 http://grrrr.org/ext; #X text 414 213 quite likely not to work...; #X connect 1 0 0 1; py/pd/sendrecv-2.pd0000644000175000017500000000064113104443402014634 0ustar zmoelnigzmoelnig#N canvas 133 322 647 189 12; #X obj 152 98 pyext sendrecv ex2 huha; #X floatatom 152 128 5 0 0 0 - - -; #X floatatom 33 96 5 0 0 0 - - -; #X obj 32 123 s huha; #X text 20 77 scroll here; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X text 213 32 http://grrrr.org/ext; #X connect 0 0 1 0; #X connect 2 0 3 0; py/pd/methods-2.pd0000644000175000017500000000163713104443402014474 0ustar zmoelnigzmoelnig#N canvas 540 469 746 351 12; #X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 235 32 http://grrrr.org/ext; #X symbolatom 21 139 10 0 0 0 - #0-t -; #X text 23 119 enter some text; #X obj 25 252 pym 2 *; #X obj 213 183 t b f; #X text 215 117 multiply it!; #X symbolatom 25 307 80 0 0 0 - - -; #X obj 214 139 nbx 5 14 1 100 0 1 empty empty empty 0 -6 0 10 -262131 -1 -1 6 256; #N canvas 0 22 462 312 init 0; #X obj 61 116 s \$0-t; #X obj 64 44 loadbang; #X obj 64 81 symbol a; #X connect 1 0 2 0; #X connect 2 0 0 0; #X restore 606 127 pd init; #X obj 213 159 int; #X text 21 73 Py can act on Python objects in an object-oriented manner ; #X text 20 285 repeated text; #X text 100 252 method * takes 2 args; #X text 235 16 Python script objects \, (C)2003-2008 Thomas Grill; #X connect 2 0 4 1; #X connect 4 0 7 0; #X connect 5 0 4 0; #X connect 5 1 4 2; #X connect 8 0 10 0; #X connect 10 0 5 0; py/pd/attr-1.pd0000644000175000017500000000232313104443402013773 0ustar zmoelnigzmoelnig#N canvas 114 127 697 455 12; #X obj 224 397 pyext simple ex3; #X obj 392 398 print A; #X msg 362 247 get tmp; #X msg 396 320 get _inlets; #X msg 395 344 set _inlets 4; #X msg 18 206 dir; #X msg 15 312 getattributes; #X msg 15 336 getmethods; #X msg 18 234 dir+; #X text 15 75 This demonstrates the usage of attributes. See the simple.py file.; #X text 260 212 access a class variable; #X text 395 301 try to get/set internal stuff; #X text 506 347 (NOT allowed!); #X text 14 288 get attributes and methods; #X text 51 205 Python module dict; #X text 59 235 Python class dict; #X text 17 128 All attribute-related methods dump eventual output to the attribute outlet (which is the right-most one); #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 msg 260 248 set tmp \$1; #X obj 259 230 nbx 5 14 -1e+037 1e+037 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 0 256; #X connect 0 1 1 0; #X connect 2 0 0 0; #X connect 3 0 0 0; #X connect 4 0 0 0; #X connect 5 0 0 0; #X connect 6 0 0 0; #X connect 7 0 0 0; #X connect 8 0 0 0; #X connect 20 0 0 0; #X connect 21 0 20 0; py/pd/sig-2.pd0000644000175000017500000000132513104443402013605 0ustar zmoelnigzmoelnig#N canvas 56 67 663 315 12; #X obj 121 246 dac~; #X msg 523 211 \; pd dsp 1; #X obj 524 184 loadbang; #X obj 266 134 hsl 128 15 0 1 0 1 empty empty pan -2 -6 0 8 -225271 -1 -1 4700 1; #X obj 100 127 noise~; #X msg 31 127 reload; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 213 32 http://grrrr.org/ext; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X text 17 66 This demonstrates signal support. See the sig.py file. ; #X obj 92 179 pyext~ 1 0 1 2 sig pan; #X text 185 202 message inlets \, outlets; #X text 183 218 signal inlets \, outlets; #X connect 2 0 1 0; #X connect 3 0 10 1; #X connect 4 0 10 0; #X connect 5 0 10 0; #X connect 10 0 0 0; #X connect 10 1 0 1; py/pd/tcltk.pd0000644000175000017500000000112613104443402014004 0ustar zmoelnigzmoelnig#N canvas 156 192 614 333 12; #X obj 328 118 bng 25 250 50 0 empty empty empty 0 -6 0 8 -258699 -1 -1; #X msg 94 128 help; #X msg 139 127 doc; #X text 14 49 This demonstrates a tcl/tk dialog. See the tcltk.py file. ; #X text 10 263 Note: When used concurrently with audio \, you will notice clicks. This Tk window is NOT called over a net socket \, like PD is; #X obj 206 169 pyext tcltk myapp; #X obj 206 200 print tcltk; #X text 16 15 py/pyext - Python script objects \, (C)2002-2005 Thomas Grill; #X connect 0 0 5 1; #X connect 1 0 5 0; #X connect 2 0 5 0; #X connect 5 0 6 0; py/pd/script-1.pd0000644000175000017500000000342113104443402014325 0ustar zmoelnigzmoelnig#N canvas 297 17 700 542 12; #X obj 39 278 print; #X obj 345 251 print; #X msg 499 149 freakhole; #X msg 148 149 list H e l l o; #X msg 166 175 Hello friend; #X obj 42 460 print; #X msg 102 367 0 1 2 3 4; #X msg 197 367 5 67 3; #X obj 350 456 print; #X obj 316 358 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X obj 515 455 print; #X obj 484 381 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X msg 188 204 1 3; #X msg 345 155 help; #X msg 350 320 set ret1; #X msg 369 344 set ret2; #X text 424 319 functions can be set; #X msg 421 120 somewhere_past_mars; #X text 152 101 reload with new arguments; #X msg 40 104 reload 1 2 3; #X text 21 69 This demonstrates simple scripting. See the script.py file.; #X obj 39 241 py script strcat; #X obj 43 424 py script addall; #X obj 350 420 py script; #X obj 346 204 py script strlen; #X msg 21 159 dir; #X obj 146 279 print A; #X msg 58 160 dir+; #X obj 16 13 cnv 15 630 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 msg 509 178 a b c; #X text 556 181 too many args; #X text 505 372 just trigger without arguments; #X msg 386 371 set ret4; #X obj 516 419 py script ret3; #X connect 2 0 24 1; #X connect 3 0 21 1; #X connect 4 0 21 1; #X connect 6 0 22 1; #X connect 7 0 22 1; #X connect 9 0 23 0; #X connect 11 0 35 0; #X connect 12 0 21 1; #X connect 13 0 24 0; #X connect 14 0 23 0; #X connect 15 0 23 0; #X connect 17 0 24 1; #X connect 19 0 21 0; #X connect 21 0 0 0; #X connect 21 1 26 0; #X connect 22 0 5 0; #X connect 23 0 8 0; #X connect 24 0 1 0; #X connect 25 0 21 0; #X connect 27 0 21 0; #X connect 31 0 24 1; #X connect 34 0 23 0; #X connect 35 0 10 0; py/pd/buffer-1.pd0000644000175000017500000000550013104443402014272 0ustar zmoelnigzmoelnig#N canvas 123 58 716 496 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.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.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; #X array array3 100 float 2; #X coords 0 1 99 -1 200 140 1; #X restore 65 301 graph; #X obj 36 199 py buffer @detach 1; #X msg 200 123 mul array3 array1 array2; #X msg 200 145 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 201 172 fadein array1; #X msg 199 196 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; py/pd/thread-1.pd0000644000175000017500000000323013104443402014266 0ustar zmoelnigzmoelnig#N canvas 135 178 652 409 12; #X msg 35 292 help; #X msg 34 317 doc; #X msg 70 318 doc+; #X floatatom 142 340 5 0 0 0 - - -; #X text 17 66 This demonstrates threading. See the threads.py file. ; #X obj 137 243 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 2 2; #X msg 137 263 detach \$1; #X floatatom 250 341 5 0 0 0 - - -; #X obj 272 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -258699 -1 -1; #X obj 143 154 bng 15 250 50 0 empty empty empty 0 -6 0 8 -258699 -1 -1; #X obj 143 181 t b b b; #X obj 272 177 t b b b; #X obj 286 206 1; #X obj 157 208 0; #X text 84 114 without threads; #X text 248 112 with threads; #X text 175 362 watch that!; #X msg 421 264 stop; #X text 391 243 you can even stop it; #X obj 142 306 pyext threads ex1; #X text 90 128 - blocking!! -; #X obj 16 13 cnv 15 600 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X obj 407 150 bng 15 250 50 0 empty empty empty 0 -6 0 8 -258699 -1 -1; #X obj 407 177 t b b b; #X text 383 112 with threads; #X text 249 129 non-blocking; #X text 384 129 parallel; #X obj 445 205 2; #X text 213 32 http://grrrr.org/ext; #X text 213 16 Python script objects \, (C)2003-2005 Thomas Grill; #X msg 44 195 reload; #X connect 0 0 19 0; #X connect 1 0 19 0; #X connect 2 0 19 0; #X connect 5 0 6 0; #X connect 6 0 19 0; #X connect 8 0 11 0; #X connect 9 0 10 0; #X connect 10 0 19 1; #X connect 10 1 19 2; #X connect 10 2 13 0; #X connect 11 0 19 1; #X connect 11 1 19 2; #X connect 11 2 12 0; #X connect 12 0 5 0; #X connect 13 0 5 0; #X connect 17 0 19 0; #X connect 19 0 3 0; #X connect 19 1 7 0; #X connect 22 0 23 0; #X connect 23 0 19 1; #X connect 23 1 19 2; #X connect 23 2 27 0; #X connect 27 0 5 0; #X connect 30 0 19 0; py/pd/builtins-1.pd0000644000175000017500000000314513104443402014655 0ustar zmoelnigzmoelnig#N canvas 602 394 714 429 12; #X obj 36 241 py .range @py 1; #X floatatom 35 356 5 0 0 0 - - -; #X obj 35 323 py .sum; #X obj 16 13 cnv 15 650 40 empty empty py/pyext 10 22 0 24 -260818 -1 0; #X text 235 32 http://grrrr.org/ext; #X obj 36 159 nbx 5 14 -1e+037 1e+037 0 1 empty empty min 0 -6 0 10 -262131 -1 -1 51 256; #X obj 95 159 nbx 5 14 -1e+037 1e+037 0 1 empty empty max 0 -6 0 10 -262131 -1 -1 131 256; #X obj 154 159 nbx 5 14 1 100000 1 1 empty empty step 0 -6 0 10 -262131 -1 -1 6.61169 256; #N canvas 0 0 466 316 pak3 0; #X obj 22 25 inlet; #X obj 81 26 inlet; #X obj 136 26 inlet; #X obj 36 158 outlet; #X obj 36 123 pack 0 0 0; #X obj 78 71 t b f; #X obj 133 73 t b f; #X obj 208 46 loadbang; #X obj 208 73 1; #X obj 23 53 int; #X obj 135 51 int; #X obj 80 50 int; #X connect 0 0 9 0; #X connect 1 0 11 0; #X connect 2 0 10 0; #X connect 4 0 3 0; #X connect 5 0 4 0; #X connect 5 1 4 1; #X connect 6 0 4 0; #X connect 6 1 4 2; #X connect 7 0 8 0; #X connect 8 0 4 2; #X connect 9 0 4 0; #X connect 10 0 6 0; #X connect 11 0 5 0; #X restore 36 190 pd pak3; #X text 169 239 construct a Python list; #X text 78 282 Python object pointer is propagated to next object; #X text 106 320 calculate sum over list elements; #X text 21 73 Py can use built-in Python functions; #X text 21 97 A . preceding the function name searches for the function in either the pyext module or in __builtins__; #X text 235 16 Python script objects \, (C)2003-2006 Thomas Grill; #X connect 0 0 2 1; #X connect 2 0 1 0; #X connect 5 0 8 0; #X connect 6 0 8 1; #X connect 7 0 8 2; #X connect 8 0 0 1; py/py.xcode/0000755000175000017500000000000013104443402013464 5ustar zmoelnigzmoelnigpy/py.xcode/project.pbxproj0000644000175000017500000005564713104443402016561 0ustar zmoelnigzmoelnig// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 39; objects = { 089C1669FE841209C02AAC07 = { buildSettings = { }; buildStyles = ( 4F9091AC011F3BD104CA0E50, 4F9091AD011F3BD104CA0E50, ); hasScannedForEncodings = 1; isa = PBXProject; mainGroup = 089C166AFE841209C02AAC07; projectDirPath = ""; targets = ( E90E52E508092505001341AC, E926B6D2089F75950034D534, ); }; 089C166AFE841209C02AAC07 = { children = ( 08FB77ADFE841716C02AAC07, 089C1671FE841209C02AAC07, 19C28FB4FE9D528D11CA2CBB, E926B6D4089F75950034D534, ); isa = PBXGroup; name = py; refType = 4; sourceTree = ""; }; 089C1671FE841209C02AAC07 = { children = ( E9D6762D08FC61860039A6F6, E9D6762E08FC61860039A6F6, E9D6762F08FC61860039A6F6, E9D6763008FC61860039A6F6, E926B819089F78400034D534, E926B817089F782F0034D534, E90E52D208091F79001341AC, E90E521108091CA5001341AC, E90E51FB080919EC001341AC, ); isa = PBXGroup; name = "External Frameworks and Libraries"; refType = 4; sourceTree = ""; }; 08FB77ADFE841716C02AAC07 = { children = ( E903AC8C09D32D03004755CA, E903AC8D09D32D03004755CA, E90043820887A302008AEAFC, E90043830887A302008AEAFC, E90043840887A302008AEAFC, E90043850887A302008AEAFC, E90043860887A302008AEAFC, E90E51DB08091989001341AC, E90E51DC08091989001341AC, E90E51DD08091989001341AC, E90E51DE08091989001341AC, E90E51DF08091989001341AC, E90E51E008091989001341AC, E90E51E108091989001341AC, E90E51E208091989001341AC, E90E51E308091989001341AC, E90E51E408091989001341AC, E90E51E508091989001341AC, E90E51E608091989001341AC, E90E51E708091989001341AC, E90E51E808091989001341AC, E90E51E908091989001341AC, E90E51EA08091989001341AC, ); isa = PBXGroup; name = Source; refType = 4; sourceTree = ""; }; //080 //081 //082 //083 //084 //190 //191 //192 //193 //194 19C28FB4FE9D528D11CA2CBB = { children = ( E90E52E608092505001341AC, E926B6D3089F75950034D534, ); isa = PBXGroup; name = Products; refType = 4; sourceTree = ""; }; //190 //191 //192 //193 //194 //4F0 //4F1 //4F2 //4F3 //4F4 4F9091AC011F3BD104CA0E50 = { buildSettings = { COPY_PHASE_STRIP = NO; DEBUGGING_SYMBOLS = YES; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) FLEXT_DEBUG FLEXT_THREADS"; LIBRARY_STYLE = STATIC; OPTIMIZATION_CFLAGS = "-O0"; ZERO_LINK = YES; }; isa = PBXBuildStyle; name = Development; }; 4F9091AD011F3BD104CA0E50 = { buildSettings = { COPY_PHASE_STRIP = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) FLEXT_SHARED"; ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Deployment; }; //4F0 //4F1 //4F2 //4F3 //4F4 //E90 //E91 //E92 //E93 //E94 E90043820887A302008AEAFC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pyatom.cpp; path = source/pyatom.cpp; refType = 4; sourceTree = ""; }; E90043830887A302008AEAFC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = pyatom.h; path = source/pyatom.h; refType = 4; sourceTree = ""; }; E90043840887A302008AEAFC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pybase.cpp; path = source/pybase.cpp; refType = 4; sourceTree = ""; }; E90043850887A302008AEAFC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = pybase.h; path = source/pybase.h; refType = 4; sourceTree = ""; }; E90043860887A302008AEAFC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pymeth.cpp; path = source/pymeth.cpp; refType = 4; sourceTree = ""; }; E90043870887A302008AEAFC = { fileRef = E90043820887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E90043880887A302008AEAFC = { fileRef = E90043830887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E90043890887A302008AEAFC = { fileRef = E90043840887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E900438A0887A302008AEAFC = { fileRef = E90043850887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E900438B0887A302008AEAFC = { fileRef = E90043860887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E903AC8C09D32D03004755CA = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pybundle.cpp; path = source/pybundle.cpp; refType = 4; sourceTree = ""; }; E903AC8D09D32D03004755CA = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = pybundle.h; path = source/pybundle.h; refType = 4; sourceTree = ""; }; E903AC8E09D32D03004755CA = { fileRef = E903AC8C09D32D03004755CA; isa = PBXBuildFile; settings = { }; }; E903AC8F09D32D03004755CA = { fileRef = E903AC8D09D32D03004755CA; isa = PBXBuildFile; settings = { }; }; E903AC9009D32D03004755CA = { fileRef = E903AC8C09D32D03004755CA; isa = PBXBuildFile; settings = { }; }; E903AC9109D32D03004755CA = { fileRef = E903AC8D09D32D03004755CA; isa = PBXBuildFile; settings = { }; }; E90E51DB08091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = bound.cpp; path = source/bound.cpp; refType = 4; sourceTree = ""; }; E90E51DC08091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = clmeth.cpp; path = source/clmeth.cpp; refType = 4; sourceTree = ""; }; E90E51DD08091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = source/main.cpp; refType = 4; sourceTree = ""; }; E90E51DE08091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = main.h; path = source/main.h; refType = 4; sourceTree = ""; }; E90E51DF08091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = modmeth.cpp; path = source/modmeth.cpp; refType = 4; sourceTree = ""; }; E90E51E008091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = py.cpp; path = source/py.cpp; refType = 4; sourceTree = ""; }; E90E51E108091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pyargs.cpp; path = source/pyargs.cpp; refType = 4; sourceTree = ""; }; E90E51E208091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pybuffer.cpp; path = source/pybuffer.cpp; refType = 4; sourceTree = ""; }; E90E51E308091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = pybuffer.h; path = source/pybuffer.h; refType = 4; sourceTree = ""; }; E90E51E408091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pydsp.cpp; path = source/pydsp.cpp; refType = 4; sourceTree = ""; }; E90E51E508091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pyext.cpp; path = source/pyext.cpp; refType = 4; sourceTree = ""; }; E90E51E608091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = pyext.h; path = source/pyext.h; refType = 4; sourceTree = ""; }; E90E51E708091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = pyprefix.h; path = source/pyprefix.h; refType = 4; sourceTree = ""; }; E90E51E808091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = pysymbol.cpp; path = source/pysymbol.cpp; refType = 4; sourceTree = ""; }; E90E51E908091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = pysymbol.h; path = source/pysymbol.h; refType = 4; sourceTree = ""; }; E90E51EA08091989001341AC = { fileEncoding = 30; isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = register.cpp; path = source/register.cpp; refType = 4; sourceTree = ""; }; E90E51FB080919EC001341AC = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = /System/Library/Frameworks/Python.framework; refType = 0; sourceTree = ""; }; E90E521108091CA5001341AC = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; refType = 0; sourceTree = ""; }; E90E52D208091F79001341AC = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = vecLib.framework; path = /System/Library/Frameworks/vecLib.framework; refType = 0; sourceTree = ""; }; E90E52E208092505001341AC = { buildActionMask = 2147483647; files = ( E90E52E908092581001341AC, E90E52EA08092581001341AC, E90E52EB08092581001341AC, E90E52EC08092581001341AC, E90E52ED08092581001341AC, E90043880887A302008AEAFC, E900438A0887A302008AEAFC, E903AC9109D32D03004755CA, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; E90E52E308092505001341AC = { buildActionMask = 2147483647; files = ( E90E52EE0809258A001341AC, E90E52EF0809258A001341AC, E90E52F00809258A001341AC, E90E52F10809258A001341AC, E90E52F20809258A001341AC, E90E52F30809258A001341AC, E90E52F40809258A001341AC, E90E52F50809258A001341AC, E90E52F60809258A001341AC, E90E52F70809258A001341AC, E90E52F80809258A001341AC, E90043870887A302008AEAFC, E90043890887A302008AEAFC, E900438B0887A302008AEAFC, E903AC9009D32D03004755CA, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; E90E52E408092505001341AC = { buildActionMask = 2147483647; files = ( E9D6763108FC619F0039A6F6, E9D6763208FC619F0039A6F6, E90E535B08092593001341AC, E90E535D08092593001341AC, E90E535E08092593001341AC, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; E90E52E508092505001341AC = { buildPhases = ( E90E52E208092505001341AC, E90E52E308092505001341AC, E90E52E408092505001341AC, ); buildRules = ( ); buildSettings = { DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; EXECUTABLE_EXTENSION = pd_darwin; GCC_ALTIVEC_EXTENSIONS = YES; GCC_MODEL_CPU = G4; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = "FLEXT_SYS=2"; HEADER_SEARCH_PATHS = "$(flext)/source $(PDApp)/src"; INSTALL_PATH = "$(PDApp)/extra"; LIBRARY_SEARCH_PATHS = "$(flext)/build"; LIBRARY_STYLE = DYNAMIC; OTHER_CFLAGS = ""; OTHER_LDFLAGS = "-bundle_loader $(PDApp)/bin/pd"; OTHER_REZFLAGS = ""; PRODUCT_NAME = py; SECTORDER_FLAGS = ""; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; }; dependencies = ( ); isa = PBXNativeTarget; name = py.pd_darwin; productName = py; productReference = E90E52E608092505001341AC; productType = "com.apple.product-type.library.dynamic"; }; E90E52E608092505001341AC = { explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; isa = PBXFileReference; path = py.pd_darwin; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; }; E90E52E908092581001341AC = { fileRef = E90E51DE08091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52EA08092581001341AC = { fileRef = E90E51E308091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52EB08092581001341AC = { fileRef = E90E51E608091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52EC08092581001341AC = { fileRef = E90E51E708091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52ED08092581001341AC = { fileRef = E90E51E908091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52EE0809258A001341AC = { fileRef = E90E51DB08091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52EF0809258A001341AC = { fileRef = E90E51DC08091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F00809258A001341AC = { fileRef = E90E51DD08091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F10809258A001341AC = { fileRef = E90E51DF08091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F20809258A001341AC = { fileRef = E90E51E008091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F30809258A001341AC = { fileRef = E90E51E108091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F40809258A001341AC = { fileRef = E90E51E208091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F50809258A001341AC = { fileRef = E90E51E408091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F60809258A001341AC = { fileRef = E90E51E508091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F70809258A001341AC = { fileRef = E90E51E808091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E52F80809258A001341AC = { fileRef = E90E51EA08091989001341AC; isa = PBXBuildFile; settings = { }; }; E90E535B08092593001341AC = { fileRef = E90E51FB080919EC001341AC; isa = PBXBuildFile; settings = { }; }; E90E535D08092593001341AC = { fileRef = E90E521108091CA5001341AC; isa = PBXBuildFile; settings = { }; }; E90E535E08092593001341AC = { fileRef = E90E52D208091F79001341AC; isa = PBXBuildFile; settings = { }; }; E926B6CF089F75950034D534 = { buildActionMask = 2147483647; files = ( E903AC8F09D32D03004755CA, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; E926B6D0089F75950034D534 = { buildActionMask = 2147483647; files = ( E926B6D8089F76D90034D534, E926B6D9089F76D90034D534, E926B6DA089F76D90034D534, E926B6DB089F76D90034D534, E926B6DC089F76D90034D534, E926B6DD089F76D90034D534, E926B6DE089F76D90034D534, E926B6DF089F76D90034D534, E926B6E0089F76D90034D534, E926B6E1089F76D90034D534, E926B6E2089F76D90034D534, E926B6E3089F76D90034D534, E926B6E4089F76D90034D534, E926B6E5089F76D90034D534, E926B6E6089F76D90034D534, E926B6E7089F76D90034D534, E926B6E8089F76D90034D534, E926B6E9089F76D90034D534, E926B6EA089F76D90034D534, E926B6EB089F76D90034D534, E926B6EC089F76D90034D534, E903AC8E09D32D03004755CA, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; E926B6D1089F75950034D534 = { buildActionMask = 2147483647; files = ( E9D6763308FC61A40039A6F6, E9D6763408FC61A40039A6F6, E926B833089F7CB50034D534, E926B7B6089F77B90034D534, E926B6F4089F77B20034D534, E926B818089F782F0034D534, E926B81A089F78400034D534, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; }; E926B6D2089F75950034D534 = { buildPhases = ( E926B6CF089F75950034D534, E926B6D0089F75950034D534, E926B6D1089F75950034D534, ); buildRules = ( ); buildSettings = { GCC_ALTIVEC_EXTENSIONS = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = source/pyprefix.h; GCC_PREPROCESSOR_DEFINITIONS = "FLEXT_SYS=1"; GENERATE_PKGINFO_FILE = YES; HEADER_SEARCH_PATHS = "$(flext)/source $(MaxSDK)/max-includes $(MaxSDK)/msp-includes"; INFOPLIST_FILE = "py-Info.plist"; LIBRARY_SEARCH_PATHS = "$(MaxSDK)/max-includes $(MaxSDK)/msp-includes"; OTHER_CFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = py; SECTORDER_FLAGS = ""; SKIP_INSTALL = YES; WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; WRAPPER_EXTENSION = mxo; }; dependencies = ( ); isa = PBXNativeTarget; name = py; productName = py; productReference = E926B6D3089F75950034D534; productSettingsXML = " CFBundleDevelopmentRegion English CFBundleExecutable py CFBundleIdentifier com.yourcompany.py CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes "; productType = "com.apple.product-type.bundle"; }; E926B6D3089F75950034D534 = { explicitFileType = wrapper.cfbundle; includeInIndex = 0; isa = PBXFileReference; path = py.mxo; refType = 3; sourceTree = BUILT_PRODUCTS_DIR; }; E926B6D4089F75950034D534 = { isa = PBXFileReference; lastKnownFileType = text.xml; name = "py-Info.plist"; path = "/Users/thomas/Develop/pdmax/py/py-Info.plist"; refType = 0; sourceTree = ""; }; E926B6D8089F76D90034D534 = { fileRef = E90043820887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E926B6D9089F76D90034D534 = { fileRef = E90043830887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E926B6DA089F76D90034D534 = { fileRef = E90043840887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E926B6DB089F76D90034D534 = { fileRef = E90043850887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E926B6DC089F76D90034D534 = { fileRef = E90043860887A302008AEAFC; isa = PBXBuildFile; settings = { }; }; E926B6DD089F76D90034D534 = { fileRef = E90E51DB08091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6DE089F76D90034D534 = { fileRef = E90E51DC08091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6DF089F76D90034D534 = { fileRef = E90E51DD08091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E0089F76D90034D534 = { fileRef = E90E51DE08091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E1089F76D90034D534 = { fileRef = E90E51DF08091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E2089F76D90034D534 = { fileRef = E90E51E008091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E3089F76D90034D534 = { fileRef = E90E51E108091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E4089F76D90034D534 = { fileRef = E90E51E208091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E5089F76D90034D534 = { fileRef = E90E51E308091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E6089F76D90034D534 = { fileRef = E90E51E408091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E7089F76D90034D534 = { fileRef = E90E51E508091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E8089F76D90034D534 = { fileRef = E90E51E608091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6E9089F76D90034D534 = { fileRef = E90E51E708091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6EA089F76D90034D534 = { fileRef = E90E51E808091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6EB089F76D90034D534 = { fileRef = E90E51E908091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6EC089F76D90034D534 = { fileRef = E90E51EA08091989001341AC; isa = PBXBuildFile; settings = { }; }; E926B6F4089F77B20034D534 = { fileRef = E90E52D208091F79001341AC; isa = PBXBuildFile; settings = { }; }; E926B7B6089F77B90034D534 = { fileRef = E90E51FB080919EC001341AC; isa = PBXBuildFile; settings = { }; }; E926B817089F782F0034D534 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MaxAPI.framework; path = /Library/Frameworks/MaxAPI.framework; refType = 0; sourceTree = ""; }; E926B818089F782F0034D534 = { fileRef = E926B817089F782F0034D534; isa = PBXBuildFile; settings = { }; }; E926B819089F78400034D534 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MaxAudioAPI.framework; path = /Library/Frameworks/MaxAudioAPI.framework; refType = 0; sourceTree = ""; }; E926B81A089F78400034D534 = { fileRef = E926B819089F78400034D534; isa = PBXBuildFile; settings = { }; }; E926B833089F7CB50034D534 = { fileRef = E90E521108091CA5001341AC; isa = PBXBuildFile; settings = { }; }; E9D6762D08FC61860039A6F6 = { isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libflext-max_d.dylib"; path = "/usr/local/lib/libflext-max_d.dylib"; refType = 0; sourceTree = ""; }; E9D6762E08FC61860039A6F6 = { isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libflext-max.dylib"; path = "/usr/local/lib/libflext-max.dylib"; refType = 0; sourceTree = ""; }; E9D6762F08FC61860039A6F6 = { isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libflext-pd_d.dylib"; path = "/usr/local/lib/libflext-pd_d.dylib"; refType = 0; sourceTree = ""; }; E9D6763008FC61860039A6F6 = { isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libflext-pd.dylib"; path = "/usr/local/lib/libflext-pd.dylib"; refType = 0; sourceTree = ""; }; E9D6763108FC619F0039A6F6 = { fileRef = E9D6762F08FC61860039A6F6; isa = PBXBuildFile; settings = { }; }; E9D6763208FC619F0039A6F6 = { fileRef = E9D6763008FC61860039A6F6; isa = PBXBuildFile; settings = { }; }; E9D6763308FC61A40039A6F6 = { fileRef = E9D6762D08FC61860039A6F6; isa = PBXBuildFile; settings = { }; }; E9D6763408FC61A40039A6F6 = { fileRef = E9D6762E08FC61860039A6F6; isa = PBXBuildFile; settings = { }; }; }; rootObject = 089C1669FE841209C02AAC07; } py/package.txt0000644000175000017500000000055313104443402014072 0ustar zmoelnigzmoelnigNAME=py BUILDTYPE=multi BUILDDIR=build SRCDIR=source PRECOMPILE=pyprefix.h SRCS= \ main.cpp \ py.cpp pyext.cpp modmeth.cpp clmeth.cpp \ register.cpp bound.cpp pyargs.cpp \ pysymbol.cpp pybuffer.cpp pybundle.cpp pydsp.cpp \ pyatom.cpp pybase.cpp pymeth.cpp HDRS= pyprefix.h main.h pyext.h pysymbol.h pybuffer.h pybundle.h pyatom.h pybase.h py/build/0000755000175000017500000000000013104443402013032 5ustar zmoelnigzmoelnigpy/build/nmake-win-msvc.inc0000644000175000017500000000073113104443402016362 0ustar zmoelnigzmoelnigDEFS = $(DEFS) /DPY_EXPORTS INCPATH=/I$(PYTHONPATH)\include LIBPATH=/LIBPATH:$(PYTHONPATH)\libs LIBS=$(LIBS) shell32.lib !ifdef PY_NUMARRAY DEFS = $(DEFS) /DPY_NUMARRAY !endif !ifdef PY_NUMPY INCPATH=$(INCPATH) /I$(PYTHONPATH)\Lib\site-packages\numpy\core\include DEFS = $(DEFS) /DPY_NUMPY !endif !ifdef PY_NUMERIC DEFS = $(DEFS) /DPY_NUMERIC !endif !ifdef PY_USE_GIL DEFS = $(DEFS) /DPY_USE_GIL !endif !ifdef PY_USE_INOFFICIAL DEFS = $(DEFS) /DPY_USE_INOFFICIAL !endif py/build/config-lnx.def0000644000175000017500000000070213104443402015555 0ustar zmoelnigzmoelnig# what is the base prefix of the Python installation? PYTHONPREFIX=/usr # which Python version do you want to compile against? PYTHONVERSION=2.7 # uncomment if numpy/numarray/numeric support should be compiled in # for info see http://numeric.scipy.org PY_NUMPY=1 # PY_NUMARRAY=1 # PY_NUMERIC=1 # use thread-safe GIL functionality (do this for python version >= 2.3!) PY_USE_GIL=1 # use inofficial (pure data) functionality # PY_USE_INOFFICIAL=1 py/build/gnumake-mac-gcc.inc0000644000175000017500000000257513104443402016455 0ustar zmoelnigzmoelnig# don't use -framework Python, since this will stick to the default system version _LOCAL_FRAMEWORK := /Library/Frameworks/Python.framework/Versions/$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) _SYSTEM_FRAMEWORK := /System/Library/Frameworks/Python.framework/Versions/$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) _LOCAL_LIBRARY := /Library/Python/$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) _SYSTEM_LIBRARY := /System/Library/Python/$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION) DEFS += -DPY_EXPORTS INCPATH += -F/Library/Frameworks -framework Python ifeq ($(PY_DEFAULT),1) LIBS += $(_SYSTEM_FRAMEWORK)/Python INCPATH += -I$(_SYSTEM_FRAMEWORK)/Headers else LIBS += $(_LOCAL_FRAMEWORK)/Python INCPATH += -I$(_LOCAL_FRAMEWORK)/Headers endif ifdef PY_NUMARRAY DEFS += -DPY_NUMARRAY endif ifdef PY_NUMPY DEFS += -DPY_NUMPY INCPATH += -I$(_LOCAL_LIBRARY)/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include ifeq ($(PY_DEFAULT),1) INCPATH += -I$(_SYSTEM_FRAMEWORK)/lib/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include INCPATH += -I$(_SYSTEM_FRAMEWORK)/Extras/lib/python/numpy/core/include else INCPATH += -I$(_LOCAL_FRAMEWORK)/lib/python$(PY_MAJOR_VERSION).$(PY_MINOR_VERSION)/site-packages/numpy/core/include endif endif ifdef PY_NUMERIC DEFS += -DPY_NUMERIC endif ifdef PY_USE_GIL DEFS += -DPY_USE_GIL endif ifdef PY_USE_INOFFICIAL DEFS += -DPY_USE_INOFFICIAL endif py/build/gnumake-win-cygwin.inc0000644000175000017500000000055213104443402017247 0ustar zmoelnigzmoelnigDEFS += -DPY_EXPORTS INCPATH += -I$(PYTHONPATH)/include LIBPATH += -L$(PYTHONPATH)/libs LIBS += -lpython$(PYTHONVER) -lshell32 ifdef PY_NUMARRAY DEFS += -DPY_NUMARRAY endif ifdef PY_NUMPY DEFS += -DPY_NUMPY endif ifdef PY_NUMERIC DEFS += -DPY_NUMERIC endif ifdef PY_USE_GIL DEFS += -DPY_USE_GIL endif ifdef PY_USE_INOFFICIAL DEFS += -DPY_USE_INOFFICIAL endif py/build/gnumake-lnx-gcc.inc0000644000175000017500000000053513104443402016510 0ustar zmoelnigzmoelnigDEFS += -DPY_EXPORTS INCPATH += -I$(PYTHONPREFIX)/include/python$(PYTHONVERSION) LIBS += -lpython$(PYTHONVERSION) ifdef PY_NUMARRAY DEFS += -DPY_NUMARRAY endif ifdef PY_NUMPY DEFS += -DPY_NUMPY endif ifdef PY_NUMERIC DEFS += -DPY_NUMERIC endif ifdef PY_USE_GIL DEFS += -DPY_USE_GIL endif ifdef PY_USE_INOFFICIAL DEFS += -DPY_USE_INOFFICIAL endif py/build/config-win.def0000644000175000017500000000065513104443402015560 0ustar zmoelnigzmoelnig# which major python version? PYTHONVER=24 # where is the Python installation? PYTHONPATH=%programfiles%/python$(PYTHONVER) # uncomment if numpy/numarray/numeric support should be compiled in # for info see http://numeric.scipy.org PY_NUMPY=1 # PY_NUMARRAY=1 # PY_NUMERIC=1 # use thread-safe GIL functionality (do this for python version >= 2.3!) PY_USE_GIL=1 # use inofficial (pure data) functionality # PY_USE_INOFFICIAL=1 py/build/config-mac.def0000644000175000017500000000201413104443402015512 0ustar zmoelnigzmoelnig# set PY_DEFAULT=0 if you manually installed Python on your system # (overriding the one that came with OS X by default) PY_DEFAULT=1 ######################################################################### # which Python version are you building for? # Mac OSX 10.3 -> default Python version (major.minor) = 2.3 # Mac OSX 10.4 -> default Python version (major.minor) = 2.3 # Mac OSX 10.5 -> default Python version (major.minor) = 2.5 # Mac OSX 10.6 -> default Python version (major.minor) = 2.6 PY_MAJOR_VERSION=2 PY_MINOR_VERSION=6 ######################################################################### # uncomment if numpy/numarray/numeric support should be compiled in # for info see http://numeric.scipy.org # numarray and numeric are outdated # PY_NUMPY=1 # PY_NUMARRAY=1 # PY_NUMERIC=1 ######################################################################### # use thread-safe GIL functionality (do this only if python version >= 2.3!) PY_USE_GIL=1 # use inofficial (pure data) functionality # PY_USE_INOFFICIAL=1 py/py.vcproj0000644000175000017500000011324113104443402013612 0ustar zmoelnigzmoelnig py/source/0000755000175000017500000000000013104443402013233 5ustar zmoelnigzmoelnigpy/source/register.cpp0000644000175000017500000000750413104443402015571 0ustar zmoelnigzmoelnig/* py/pyext - python external object for PD and MaxMSP Copyright (c)2002-2015 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 "pybase.h" #if 1 PyObject *pybase::GetRegistry(const char *regnm) { if(module) { FLEXT_ASSERT(dict); // module must have a valid dict // add this to module registry PyObject *reg = PyDict_GetItemString(dict,(char *)regnm); // borrowed!!! if(reg) FLEXT_ASSERT(PyDict_Check(reg)); else { // make a new empty registry reg = PyDict_New(); PyDict_SetItemString(dict,(char *)regnm,reg); } return reg; } else return NULL; } void pybase::SetRegistry(const char *regnm,PyObject *reg) { if(module) { FLEXT_ASSERT(dict); // module must have a valid dict FLEXT_ASSERT(reg && PyDict_Check(reg)); PyDict_SetItemString(dict,(char *)regnm,reg); } } void pybase::Register(PyObject *reg) { if(!module) return; FLEXT_ASSERT(reg && PyDict_Check(reg)); // add this to module registry Py_INCREF(Py_None); PyObject *key = PyLong_FromUnsignedLong((size_t)this); PyDict_SetItem(reg,key,Py_None); } void pybase::Unregister(PyObject *reg) { if(!module) return; FLEXT_ASSERT(reg && PyDict_Check(reg)); // remove this from module registry PyObject *key = PyLong_FromUnsignedLong((size_t)this); PyObject *item = PyDict_GetItem(reg,key); if(!item) post("py/pyext - Internal error: object not found in registry"); else PyDict_DelItem(reg,key); } /* void pybase::RegLoad(PyObject *reg) { } void pybase::RegUnload(PyObject *reg) { } */ #else void pybase::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("py/pyext - Could not set registry"); } } else { PySequence_InPlaceConcat(reg,add); } } } void pybase::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("py/pyext - Internal error: Registry not found!?"); else { int ix = PySequence_Index(reg,add); if(ix < 0) { post("py/pyext - Internal error: object not found in registry?!"); } else { PySequence_DelItem(reg,ix); } } Py_DECREF(add); } } void pybase::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("py/pyext - Internal error: Registry not found!?"); 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("py/pyext - Internal error: Corrupt registry?!"); } else { pybase *th = (pybase *)PyInt_AsLong(it); th->module = module; th->dict = dict; th->Reload(); } Py_XDECREF(it); } } } } #endif py/source/pyprefix.h0000644000175000017500000000216313104443402015254 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and MaxMSP Copyright (c)2002-2015 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. */ #ifndef __PYPREFIX_H #define __PYPREFIX_H #define FLEXT_ATTRIBUTES 1 #include // hack: must include math.h before Python.h (at least on OSX) // otherwise some functions don't get defined #include #if FLEXT_OS == FLEXT_OS_MAC #include #else #include #endif #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 501) #error You need at least flext version 0.5.1 #endif #if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX #include #endif #if FLEXT_SYS == FLEXT_SYS_PD && (!defined (PD_MINOR_VERSION) || ( PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 37)) #error PD version >= 0.37 required, please upgrade! #endif #include #include #if FLEXT_SYS == FLEXT_SYS_PD && defined(PY_USE_INOFFICIAL) extern "C" { #include } #endif #if PY_VERSION_HEX < 0x02050000 typedef int Py_ssize_t; #endif #endif py/source/pyext.cpp0000644000175000017500000004022713104443402015115 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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 "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; ThrLockSys lock; // 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(); } bool pyext::Init() { ThrLockSys lock; 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(); return pyobj && flext_dsp::Init(); } bool pyext::Finalize() { bool ok = true; ThrLockSys lock; 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(); return ok && flext_dsp::Finalize(); } void pyext::Exit() { pybase::Exit(); // exit threads ThrLockSys lock; DoExit(); Unregister(GetRegistry(REGNAME)); UnimportModule(); Report(); 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) { ThrLockSys lock; 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(); } void pyext::m_set(int argc,const t_atom *argv) { ThrLockSys lock; 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(); } 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-2012 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; ThrLock lock; 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; // 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); 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); } py/source/pydsp.cpp0000644000175000017500000001016713104443402015103 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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. */ #ifndef PY_NODSP #include "pyext.h" class pydsp : public pyext { FLEXT_HEADER(pydsp,pyext) public: pydsp(int argc,const t_atom *argv); protected: virtual bool CbDsp(); virtual void CbSignal(); virtual bool DoInit(); virtual void DoExit(); virtual PyObject *GetSig(int ix,bool in); void NewBuffers(); void FreeBuffers(); PyObject *dspfun,*sigfun; PyObject **buffers; }; FLEXT_LIB_DSP_V("pyext~ pyext.~ pyx~ pyx.~",pydsp) pydsp::pydsp(int argc,const t_atom *argv) : pyext(argc,argv,true) , dspfun(NULL),sigfun(NULL) {} bool pydsp::DoInit() { if(!pyext::DoInit()) return false; if(pyobj) { dspfun = PyObject_GetAttrString(pyobj,"_dsp"); // get ref if(!dspfun) PyErr_Clear(); else if(!PyMethod_Check(dspfun)) { Py_DECREF(dspfun); dspfun = NULL; } } return true; } void pydsp::DoExit() { if(dspfun) { Py_DECREF(dspfun); dspfun = NULL; } if(sigfun) { Py_DECREF(sigfun); sigfun = NULL; } FreeBuffers(); } PyObject *arrayfrombuffer(PyObject *buf,int c,int n); void pydsp::NewBuffers() { int i,n = Blocksize(); const int ins = CntInSig(),outs = CntOutSig(); t_sample *const *insigs = InSig(); t_sample *const *outsigs = OutSig(); // inlet/outlet count can't change so we don't have to deallocate if(!buffers) { int cnt = ins+outs; buffers = new PyObject *[cnt]; memset(buffers,0,cnt*sizeof(*buffers)); } for(i = 0; i < ins; ++i) { Py_XDECREF(buffers[i]); PyObject *b = PyBuffer_FromReadWriteMemory(insigs[i],n*sizeof(t_sample)); buffers[i] = arrayfrombuffer(b,1,n); Py_DECREF(b); } for(i = 0; i < outs; ++i) { Py_XDECREF(buffers[ins+i]); if(i < ins && outsigs[i] == insigs[i]) { // same vectors - share the objects! buffers[ins+i] = buffers[i]; Py_XINCREF(buffers[i]); } else { PyObject *b = PyBuffer_FromReadWriteMemory(outsigs[i],n*sizeof(t_sample)); buffers[ins+i] = arrayfrombuffer(b,1,n); Py_DECREF(b); } } } void pydsp::FreeBuffers() { if(buffers) { int cnt = CntInSig()+CntOutSig(); for(int i = 0; i < cnt; ++i) Py_XDECREF(buffers[i]); delete[] buffers; buffers = NULL; } } bool pydsp::CbDsp() { if(pyobj && (CntInSig() || CntOutSig())) { ThrLockSys lock; NewBuffers(); bool dodsp = true; if(dspfun) { PyObject *ret = PyObject_CallObject(dspfun,NULL); if(ret) { dodsp = PyObject_IsTrue(ret) != 0; Py_DECREF(ret); } else { #ifdef FLEXT_DEBUG PyErr_Print(); #else PyErr_Clear(); #endif } } // do that here instead of where dspfun is initialized, so that // _signal can be assigned in _dsp // optimizations may be done there to assign the right _signal version Py_XDECREF(sigfun); if(dodsp) { sigfun = PyObject_GetAttrString(pyobj,"_signal"); // get ref if(!sigfun) PyErr_Clear(); else if(!PyMethod_Check(sigfun)) { Py_DECREF(sigfun); sigfun = NULL; } } else sigfun = NULL; return sigfun != NULL; } else // switch on dsp only if there are signal inlets or outlets return false; } void pydsp::CbSignal() { ThrLockSys lock; PyObject *ret = PyObject_CallObject(sigfun,NULL); if(ret) Py_DECREF(ret); else { #ifdef FLEXT_DEBUG PyErr_Print(); #else PyErr_Clear(); #endif } } PyObject *pydsp::GetSig(int ix,bool in) { PyObject *r = buffers[in?ix:CntInSig()+ix]; Py_XINCREF(r); return r; } #endif py/source/modmeth.cpp0000644000175000017500000001760513104443402015405 0ustar zmoelnigzmoelnig/* py/pyext - python external object for PD and Max/MSP Copyright (c)2002-2015 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 "pybase.h" // function table for module PyMethodDef pybase::func_tbl[] = { { "_send", pybase::py_send, METH_VARARGS,"Send message to a named object" }, #ifdef FLEXT_THREADS { "_priority", pybase::py_priority, METH_VARARGS,"Set priority of current thread" }, #endif { "_arraysupport", pybase::py_arraysupport, METH_NOARGS,"Query Python array support" }, { "_samplerate", pybase::py_samplerate, METH_NOARGS,"Get system sample rate" }, { "_blocksize", pybase::py_blocksize, METH_NOARGS,"Get system block size" }, { "_searchpaths", pybase::py_searchpaths, METH_NOARGS,"Get system search paths" }, { "_helppaths", pybase::py_helppaths, METH_NOARGS,"Get system help paths" }, #if FLEXT_SYS == FLEXT_SYS_PD { "_getvalue", pybase::py_getvalue, METH_VARARGS,"Get value of a 'value' object" }, { "_setvalue", pybase::py_setvalue, METH_VARARGS,"Set value of a 'value' object" }, #endif { "_list", pybase::py_list, METH_VARARGS,"Make a list from arguments" }, { "_tuple", pybase::py_tuple, METH_VARARGS,"Make a tuple from arguments" }, {NULL, NULL, 0, NULL} // sentinel }; const char *pybase::py_doc = "py/pyext - python external object for PD and Max/MSP, (C)2002-2008 Thomas Grill\n" "\n" "This is the pyext module. Available function:\n" "_send(args...): Send a message to a send symbol\n" #ifdef FLEXT_THREADS "_priority(int): Raise/lower thread priority\n" #endif "_samplerate(): Get system sample rate\n" "_blocksize(): Get current blocksize\n" "_getvalue(name): Get value of a 'value' object\n" "_setvalue(name,float): Set value of a 'value' object\n" "_list(args...): Make a list from args\n" "_tuple(args...): Make a tuple from args\n" ; #ifdef FLEXT_THREADS void pybase::tick(void *) { Lock(); if(!thrcount) { // all threads have stopped shouldexit = false; stoptick = 0; } else { // still active threads if(!--stoptick) { post("py/pyext - Threads couldn't be stopped entirely - %i remaining",thrcount); shouldexit = false; } else // continue waiting stoptmr.Delay(PY_STOP_TICK/1000.); } Unlock(); } #endif void pybase::m_stop(int argc,const t_atom *argv) { #ifdef FLEXT_THREADS 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 if(ticks < stoptick) stoptick = ticks; } else stoptick = ticks; shouldexit = true; stoptmr.Delay(PY_STOP_TICK/1000.); Unlock(); } #endif } PyObject *pybase::py_samplerate(PyObject *self,PyObject *args) { return PyFloat_FromDouble(sys_getsr()); } PyObject *pybase::py_blocksize(PyObject *self,PyObject *args) { return PyLong_FromLong(sys_getblksize()); } PyObject *pybase::py_searchpaths(PyObject *self,PyObject *args) { #if FLEXT_SYS == FLEXT_SYS_PD && defined(PD_DEVEL_VERSION) && defined(PY_USE_INOFFICIAL) PyObject *ret = PyList_New(0); char *dir; for(int i = 0; (dir = namelist_get(sys_searchpath,i)) != NULL; ++i) PyList_Append(ret,PyString_FromString(dir)); return ret; #else Py_INCREF(Py_None); return Py_None; #endif } PyObject *pybase::py_helppaths(PyObject *self,PyObject *args) { #if FLEXT_SYS == FLEXT_SYS_PD && defined(PD_DEVEL_VERSION) && defined(PY_USE_INOFFICIAL) PyObject *ret = PyList_New(0); char *dir; for(int i = 0; (dir = namelist_get(sys_helppath,i)) != NULL; ++i) PyList_Append(ret,PyString_FromString(dir)); return ret; #else Py_INCREF(Py_None); return Py_None; #endif } PyObject *pybase::py_send(PyObject *,PyObject *args) { // should always be a tuple FLEXT_ASSERT(PyTuple_Check(args)); const int sz = PyTuple_GET_SIZE(args); const t_symbol *recv; if( sz >= 1 && (recv = pyObject_AsSymbol(PyTuple_GET_ITEM(args,0))) != NULL ) { PyObject *val; #if 0 bool tp = sz == 2 && PySequence_Check( val = PyTuple_GET_ITEM(args,1) // borrowed ref ); if(!tp) val = PySequence_GetSlice(args,1,sz); // new ref #else if(sz == 2) { val = PyTuple_GET_ITEM(args,1); // borrow reference Py_INCREF(val); } else val = PySequence_GetSlice(args,1,sz); // new ref #endif AtomListStatic<16> lst; const t_symbol *sym = GetPyArgs(lst,val); Py_DECREF(val); if(sym) { bool ok; if(sym == sym_list && !lst.Count()) // empty list is translated to a bang message ok = Forward(recv,sym_bang,0,NULL); else ok = Forward(recv,sym,lst.Count(),lst.Atoms()); #ifdef FLEXT_DEBUG if(!ok) post("py/pyext - Receiver doesn't exist"); #endif Py_INCREF(Py_None); return Py_None; } /* else if(PyErr_Occurred()) PyErr_Print(); else post("py/pyext - No data to send"); */ else { FLEXT_ASSERT(PyErr_Occurred()); return NULL; } } /* else post("py/pyext - Send name is invalid"); */ else { PyErr_SetString(PyExc_ValueError,"py/pyext - Send name is invalid"); return NULL; } } #ifdef FLEXT_THREADS PyObject *pybase::py_priority(PyObject *self,PyObject *args) { int val; if(!PyArg_ParseTuple(args, "i:py_priority", &val)) { post("py/pyext - Syntax: _priority [int]"); } else RelPriority(val); Py_INCREF(Py_None); return Py_None; } #endif #if FLEXT_SYS == FLEXT_SYS_PD PyObject *pybase::py_getvalue(PyObject *self,PyObject *args) { FLEXT_ASSERT(PyTuple_Check(args)); const int sz = PyTuple_GET_SIZE(args); const t_symbol *sym; PyObject *ret; if( sz == 1 && (sym = pyObject_AsSymbol(PyTuple_GET_ITEM(args,0))) != NULL ) { float f; if(value_getfloat(const_cast(sym),&f)) { post("py/pyext - Could not get value '%s'",GetString(sym)); Py_INCREF(Py_None); ret = Py_None; } else ret = PyFloat_FromDouble(f); } else { post("py/pyext - Syntax: _getvalue [name]"); Py_INCREF(Py_None); ret = Py_None; } return ret; } PyObject *pybase::py_setvalue(PyObject *self,PyObject *args) { FLEXT_ASSERT(PyTuple_Check(args)); const int sz = PyTuple_GET_SIZE(args); const t_symbol *sym; PyObject *val; // borrowed reference if( sz == 2 && (sym = pyObject_AsSymbol(PyTuple_GET_ITEM(args,0))) != NULL && PyNumber_Check(val = PyTuple_GET_ITEM(args,1)) ) { float f = (float)PyFloat_AsDouble(val); if(value_setfloat(const_cast(sym),f)) post("py/pyext - Could not set value '%s'",GetString(sym)); } else post("py/pyext - Syntax: _setvalue [name] [value]"); Py_INCREF(Py_None); return Py_None; } #endif PyObject *pybase::py_list(PyObject *,PyObject *args) { // should always be a tuple FLEXT_ASSERT(PyTuple_Check(args)); const int sz = PyTuple_GET_SIZE(args); PyObject *ret = PyList_New(sz); for(int i = 0; i < sz; ++i) { PyObject *el = PyTuple_GET_ITEM(args,i); Py_INCREF(el); PyList_SET_ITEM(ret,i,el); } return ret; } PyObject *pybase::py_tuple(PyObject *,PyObject *args) { // should always be a tuple FLEXT_ASSERT(PyTuple_Check(args)); Py_INCREF(args); return args; } py/source/pysymbol.h0000644000175000017500000000401613104443402015263 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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. */ #ifndef __PYSYMBOL_H #define __PYSYMBOL_H #include #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) #error You need at least flext version 0.5.0 #endif #if FLEXT_OS == FLEXT_OS_MAC #include #else #include #endif #ifdef _MSC_VER #ifdef PY_EXPORTS #define PY_EXPORT __declspec(dllexport) #else #define PY_EXPORT __declspec(dllimport) #endif #else #define PY_EXPORT #endif typedef struct { PyObject_HEAD /* Type-specific fields go here. */ const t_symbol *sym; } pySymbol; PY_EXPORT extern PyTypeObject pySymbol_Type; PY_EXPORT extern pySymbol *pySymbol__; PY_EXPORT extern pySymbol *pySymbol_bang; PY_EXPORT extern pySymbol *pySymbol_list; PY_EXPORT extern pySymbol *pySymbol_symbol; PY_EXPORT extern pySymbol *pySymbol_float; PY_EXPORT extern pySymbol *pySymbol_int; #define pySymbol_Check(op) PyObject_TypeCheck(op, &pySymbol_Type) #define pySymbol_CheckExact(op) ((op)->ob_type == &pySymbol_Type) PY_EXPORT PyObject *pySymbol_FromSymbol(const t_symbol *sym); inline PyObject *pySymbol_FromString(const char *str) { return pySymbol_FromSymbol(flext::MakeSymbol(str)); } inline PyObject *pySymbol_FromString(PyObject *str) { return pySymbol_FromString(PyString_AsString(str)); } inline const t_symbol *pySymbol_AS_SYMBOL(PyObject *op) { return ((pySymbol *)op)->sym; } inline const t_symbol *pySymbol_AsSymbol(PyObject *op) { return pySymbol_Check(op)?pySymbol_AS_SYMBOL(op):NULL; } inline const char *pySymbol_AS_STRING(PyObject *op) { return flext::GetString(pySymbol_AS_SYMBOL(op)); } inline const t_symbol *pyObject_AsSymbol(PyObject *op) { if(PyString_Check(op)) return flext::MakeSymbol(PyString_AS_STRING(op)); else return pySymbol_AsSymbol(op); } #endif py/source/pyargs.cpp0000644000175000017500000001435713104443402015256 0ustar zmoelnigzmoelnig/* py/pyext - python external object for PD and MaxMSP Copyright (c)2002-2015 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 "pybase.h" #include "pyatom.h" static const t_symbol *symatom = flext::MakeSymbol(" py "); static PyObject *MakePyAtom(const t_atom &at) { if(flext::IsSymbol(at)) return pySymbol_FromSymbol(flext::GetSymbol(at)); #if 1 else if(flext::CanbeFloat(at)) { // if a number can be an integer... let it be an integer! int ival = flext::GetAInt(at); double fval = flext::GetAFloat(at); return (double)ival == fval?PyInt_FromLong(ival):PyFloat_FromDouble(fval); } #else else if(flext::IsFloat(at)) return PyFloat_FromDouble(flext::GetFloat(at)); else if(flext::IsInt(at)) return PyInt_FromLong(flext::GetInt(at)); #endif return NULL; } static PyObject *MakePyAtom(int argc,const t_atom *argv) { if(argc != sizeof(size_t)/2) return NULL; size_t atom = 0; for(int i = sizeof(size_t)/2-1; i >= 0; --i) if(!flext::CanbeInt(argv[i])) { atom = 0; break; } else atom = (atom<<16)+flext::GetAInt(argv[i]); if(atom) { PyObject *el = PyAtom::Retrieve(atom); if(!el) el = Py_None; // object already gone.... Py_INCREF(el); return el; } else return NULL; } PyObject *pybase::MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet) { PyObject *ret,*el; if(s == symatom && (el = MakePyAtom(argc,argv)) != NULL) { ret = PyTuple_New(1); PyTuple_SET_ITEM(ret,0,el); } else { bool any = IsAnything(s); ret = PyTuple_New(argc+(any?1:0)+(inlet >= 0?1:0)); int pix = 0; if(inlet >= 0) PyTuple_SET_ITEM(ret,pix++,PyInt_FromLong(inlet)); if(any) PyTuple_SET_ITEM(ret,pix++,pySymbol_FromSymbol(s)); for(int i = 0; i < argc; ++i) { el = MakePyAtom(argv[i]); if(!el) { post("py/pyext: cannot convert argument %i",any?i+1:i); el = Py_None; Py_INCREF(Py_None); } PyTuple_SET_ITEM(ret,pix++,el); // reference stolen } } return ret; } PyObject *pybase::MakePyArg(const t_symbol *s,int argc,const t_atom *argv) { PyObject *ret; if(s == symatom && (ret = MakePyAtom(argc,argv)) != NULL) { // ok! } else if(argc == 1 && !IsAnything(s)) // convert atoms and one-element lists ret = MakePyAtom(*argv); else { bool any = s != sym_list; ret = PyTuple_New(argc+(any?1:0)); int pix = 0; if(any) PyTuple_SET_ITEM(ret,pix++,pySymbol_FromSymbol(s)); for(int i = 0; i < argc; ++i) { PyObject *el = MakePyAtom(argv[i]); if(!el) { post("py/pyext: cannot convert argument %i",any?i+1:i); el = Py_None; Py_INCREF(Py_None); } PyTuple_SET_ITEM(ret,pix++,el); // reference stolen } } return ret; } inline bool issym(PyObject *p) { return PyString_Check(p) || pySymbol_Check(p); } inline bool isseq(PyObject *p) { return PySequence_Check(p) && !issym(p); } const t_symbol *pybase::getone(t_atom &at,PyObject *arg) { if(PyInt_Check(arg)) { flext::SetInt(at,PyInt_AsLong(arg)); return sym_fint; } else if(PyLong_Check(arg)) { flext::SetInt(at,PyLong_AsLong(arg)); return sym_fint; } else if(PyFloat_Check(arg)) { flext::SetFloat(at,(float)PyFloat_AsDouble(arg)); return flext::sym_float; } else if(pySymbol_Check(arg)) { flext::SetSymbol(at,pySymbol_AS_SYMBOL(arg)); return flext::sym_symbol; } else if(PyString_Check(arg)) { flext::SetString(at,PyString_AS_STRING(arg)); return flext::sym_symbol; } else { PyObject *tp = PyObject_Type(arg); PyObject *stp = tp?PyObject_Str(tp):NULL; const char *tmp = ""; if(stp) tmp = PyString_AS_STRING(stp); flext::post("py/pyext: Could not convert argument %s",tmp); Py_XDECREF(stp); Py_XDECREF(tp); flext::SetSymbol(at,flext::sym__); return sym_symbol; } } const t_symbol *pybase::getlist(t_atom *lst,PyObject *seq,int cnt,int offs) { for(int ix = 0; ix < cnt; ++ix) { PyObject *arg = PySequence_GetItem(seq,ix+offs); // new reference getone(lst[ix],arg); Py_DECREF(arg); } return flext::sym_list; } const t_symbol *pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) { if(pValue == NULL) return NULL; // output bang on None returned if(pValue == Py_None) return sym_bang; // analyze return value or tuple const t_symbol *sym = NULL; if(isseq(pValue)) { // Python might crash here if pValue is no "real" sequence, but rather e.g. an instance int rargc = PySequence_Size(pValue); if(rargc == 2) { // check if syntax is symbol/string, list -> anything message PyObject *s = PySequence_GetItem(pValue,0); PyObject *l = PySequence_GetItem(pValue,1); if(issym(s) && isseq(l)) { // is anything message rargc = PySequence_Size(l); lst(offs+rargc); getlist(lst.Atoms(),l,rargc); sym = pyObject_AsSymbol(s); } else { // (symbol,atom) list lst(offs+rargc); sym = getlist(lst.Atoms(),pValue,rargc); } Py_DECREF(s); Py_DECREF(l); } else { lst(offs+rargc); sym = getlist(lst.Atoms(),pValue,rargc); } } else { lst(offs+1); sym = getone(lst[offs],pValue); } return sym; } const t_symbol *pybase::GetPyAtom(AtomList &lst,PyObject *obj) { size_t atom = PyAtom::Register(obj); size_t szat = sizeof(atom)/2; lst(szat); for(size_t i = 0; i < szat; ++i,atom >>= 16) flext::SetInt(lst[i],(int)(atom&((1<<16)-1))); return symatom; } py/source/pyatom.h0000644000175000017500000000062613104443402014721 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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" class PyAtom { public: static size_t Register(PyObject *obj); static PyObject *Retrieve(size_t id); static void Collect(); }; py/source/pybundle.cpp0000644000175000017500000001523313104443402015565 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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 "pyprefix.h" #include "pybundle.h" #include "pyext.h" static PyObject *bundle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { pyBundle *self = (pyBundle *)pyBundle_Type.tp_alloc(&pyBundle_Type, 0); if(self) self->bundle = flext::MsgNew(); return (PyObject *)self; } static int bundle_init(PyObject *self, PyObject *args, PyObject *kwds) { FLEXT_ASSERT(pyBundle_Check(self)); int len = PySequence_Length(args); if(len) { PyErr_SetString(PyExc_TypeError,"no arguments expected"); return -1; } return 0; } static void bundle_dealloc(PyObject *obj) { pyBundle *self = (pyBundle *)obj; if(self->bundle) flext::MsgFree(self->bundle); obj->ob_type->tp_free(obj); } static PyObject *bundle_send(PyObject *obj) { pyBundle *self = (pyBundle *)obj; if(self->bundle) { flext::ToOutMsg(self->bundle); self->bundle = NULL; Py_INCREF(obj); return obj; } else { PyErr_SetString(PyExc_RuntimeError,"already sent"); return NULL; } } static PyObject *bundle_repr(PyObject *self) { FLEXT_ASSERT(pyBundle_Check(self)); return (PyObject *)PyString_FromFormat("",pyBundle_AS_BUNDLE(self)); } static PyObject *bundle_str(PyObject *self) { return bundle_repr(self); } static PyObject *bundle_richcompare(PyObject *a,PyObject *b,int cmp) { if(pyBundle_Check(a) && pyBundle_Check(b)) { const flext::MsgBundle *abnd = pyBundle_AS_BUNDLE(a); const flext::MsgBundle *bbnd = pyBundle_AS_BUNDLE(b); bool ret; switch(cmp) { case Py_LT: ret = abnd < bbnd; break; case Py_LE: ret = abnd <= bbnd; break; case Py_EQ: ret = abnd == bbnd; break; case Py_NE: ret = abnd != bbnd; break; case Py_GT: ret = abnd > bbnd; break; case Py_GE: ret = abnd >= bbnd; break; } return PyBool_FromLong(ret); } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } static long bundle_hash(PyObject *self) { FLEXT_ASSERT(pyBundle_Check(self)); return (long)pyBundle_AS_BUNDLE(self); } static PyObject *bundle_append(PyObject *self,PyObject *args) { flext::MsgBundle *b = pyBundle_AS_BUNDLE(self); if(b) { int sz = PyTuple_GET_SIZE(args),offs = 0; PyObject *tg,*outl; pyext *ext = NULL; const t_symbol *recv; int o; if(sz > 2 && (tg = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(tg) && (outl = PyTuple_GET_ITEM(args,1)) != NULL && PyInt_Check(outl) ) { // Sending to outlet ext = pyext::GetThis(tg); o = PyInt_AS_LONG(outl); if(o < 1 || o > ext->Outlets()) { PyErr_SetString(PyExc_ValueError,"Outlet index out of range"); return NULL; } offs += 2; } else if(sz > 1 && (tg = PyTuple_GET_ITEM(args,0)) != NULL && (recv = pyObject_AsSymbol(tg)) != NULL ) { // Sending to receiver offs++; } else { // not recognized PyErr_SetString(PyExc_SyntaxError,"Unrecognized arguments"); return NULL; } PyObject *val; if(sz-offs == 1) { val = PyTuple_GET_ITEM(args,offs); // borrow reference Py_INCREF(val); } else val = PyTuple_GetSlice(args,offs,sz); // new ref flext::AtomListStatic<16> lst; const t_symbol *sym = pybase::GetPyArgs(lst,val); Py_DECREF(val); if(sym) { if(ext) { FLEXT_ASSERT(outl); ext->MsgAddAnything(b,o-1,sym,lst.Count(),lst.Atoms()); } else { FLEXT_ASSERT(sym); if(!flext::MsgForward(b,recv,sym,lst.Count(),lst.Atoms())) { PyErr_SetString(PyExc_ValueError,"Receiver not found"); return NULL; } } Py_INCREF(Py_None); return Py_None; } else { FLEXT_ASSERT(PyErr_Occurred()); return NULL; } Py_INCREF(self); return self; } else { PyErr_SetString(PyExc_RuntimeError,"Invalid bundle"); return NULL; } } static PyMethodDef bundle_methods[] = { {"append", (PyCFunction)bundle_append,METH_VARARGS,"Append message to bundle"}, {"send", (PyCFunction)bundle_send,METH_NOARGS,"Send bundle"}, {NULL} /* Sentinel */ }; PyTypeObject pyBundle_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "Bundle", /*tp_name*/ sizeof(pyBundle), /*tp_basicsize*/ 0, /*tp_itemsize*/ bundle_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ bundle_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ bundle_hash, /*tp_hash */ 0, /*tp_call*/ bundle_str, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ "Bundle objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ bundle_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ bundle_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ bundle_init, /* tp_init */ 0, /* tp_alloc */ bundle_new, /* tp_new */ }; void initbundle() { if(PyType_Ready(&pyBundle_Type) < 0) FLEXT_ASSERT(false); else Py_INCREF(&pyBundle_Type); } py/source/bound.cpp0000644000175000017500000001275013104443402015053 0ustar zmoelnigzmoelnig/* py/pyext - python external object for PD and MaxMSP Copyright (c)2002-2015 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 "pyext.h" #include "flinternal.h" #include class MethodCompare: public std::less { public: bool operator()(PyObject *a,PyObject *b) const { if(PyMethod_Check(a)) if(PyMethod_Check(b)) { // both are methods PyObject *sa = PyMethod_GET_SELF(a); PyObject *sb = PyMethod_GET_SELF(b); if(sa) if(sb) { // both have self if(sa == sb) return PyMethod_GET_FUNCTION(a) < PyMethod_GET_FUNCTION(b); else return sa < sb; } else return false; else if(sb) return true; else return PyMethod_GET_FUNCTION(a) < PyMethod_GET_FUNCTION(b); } else return false; else if(PyMethod_Check(b)) return true; else // both are non-method callables return a < b; } }; typedef std::set FuncSet; struct bounddata { PyObject *self; FuncSet funcs; }; bool pyext::boundmeth(flext_base *th,t_symbol *sym,int argc,t_atom *argv,void *data) { bounddata *obj = (bounddata *)data; pyext *pyth = static_cast(th); ThrState state = pyth->PyLock(); PyObject *args = MakePyArgs(sym,argc,argv); // call all functions bound by this symbol for(FuncSet::iterator it = obj->funcs.begin(); it != obj->funcs.end(); ++it) { PyObject *ret = PyObject_CallObject(*it,args); if(!ret) PyErr_Print(); else Py_DECREF(ret); } Py_XDECREF(args); pyth->PyUnlock(state); return true; } PyObject *pyext::pyext_bind(PyObject *,PyObject *args) { PyObject *self,*meth,*name; if(!PyArg_ParseTuple(args, "OOO:pyext_bind", &self,&name,&meth)) // borrowed references post("py/pyext - Wrong arguments!"); else if(!PyInstance_Check(self) || !PyCallable_Check(meth)) { post("py/pyext - Wrong argument types!"); } else { pyext *th = GetThis(self); if(!th) { PyErr_SetString(PyExc_RuntimeError,"pyext - _bind: instance not associated with pd object"); return NULL; } const t_symbol *recv = pyObject_AsSymbol(name); void *data = NULL; if(recv && th->GetBoundMethod(recv,boundmeth,data)) { // already bound to that symbol and function bounddata *bdt = (bounddata *)data; FLEXT_ASSERT(bdt != NULL && bdt->self == self); FuncSet::iterator it = bdt->funcs.find(meth); if(it == bdt->funcs.end()) { bdt->funcs.insert(meth); Py_INCREF(meth); } } else { Py_INCREF(self); // self is borrowed reference Py_INCREF(meth); bounddata *data = new bounddata; data->self = self; data->funcs.insert(meth); th->BindMethod(recv,boundmeth,data); } } Py_INCREF(Py_None); return Py_None; } PyObject *pyext::pyext_unbind(PyObject *,PyObject *args) { PyObject *self,*meth,*name; if(!PyArg_ParseTuple(args, "OOO:pyext_bind", &self,&name,&meth)) // borrowed references post("py/pyext - Wrong arguments!"); else if(!PyInstance_Check(self) || !PyCallable_Check(meth)) { post("py/pyext - Wrong argument types!"); } else { pyext *th = GetThis(self); if(!th) { PyErr_SetString(PyExc_RuntimeError,"pyext - _unbind: instance not associated with pd object"); return NULL; } const t_symbol *recv = pyObject_AsSymbol(name); void *data = NULL; if(recv && th->GetBoundMethod(recv,boundmeth,data)) { bounddata *bdt = (bounddata *)data; FLEXT_ASSERT(bdt != NULL); // erase from map // ATTENTION: meth is different from the element found in the map // it just points to the same instance method FuncSet::iterator it = bdt->funcs.find(meth); if(it != bdt->funcs.end()) { Py_DECREF(*it); bdt->funcs.erase(it); } else post("py/pyext - Function to unbind couldn't be found"); if(bdt->funcs.empty()) { Py_DECREF(bdt->self); delete bdt; th->UnbindMethod(recv,boundmeth,NULL); } } } Py_INCREF(Py_None); return Py_None; } void pyext::ClearBinding() { // in case the object couldn't be constructed... if(!pyobj) return; pyext *th = GetThis(pyobj); if(!th) return; void *data = NULL; const t_symbol *sym = NULL; // unbind all while(th->UnbindMethod(sym,NULL,&data)) { bounddata *bdt = (bounddata *)data; if(bdt) { for(FuncSet::iterator it = bdt->funcs.begin(); it != bdt->funcs.end(); ++it) Py_DECREF(*it); Py_DECREF(bdt->self); delete bdt; } } } py/source/main.h0000644000175000017500000000136313104443402014333 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and MaxMSP Copyright (c)2002-2015 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. */ #ifndef __MAIN_H #define __MAIN_H #include "pyprefix.h" #define PY__VERSION "0.2.2" #define PYEXT_MODULE "pyext" // name for module #define PYEXT_CLASS "_class" // name for base class #define REGNAME "_registry" #define PY_STOP_WAIT 100 // ms #define PY_STOP_TICK 1 // ms class pybase; class FifoEl : public FifoCell { public: void Set(pybase *t,PyObject *f,PyObject *a) { th = t,fun = f,args = a; } pybase *th; PyObject *fun,*args; }; typedef PooledFifo PyFifo; #endif py/source/pybundle.h0000644000175000017500000000231413104443402015226 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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. */ #ifndef __PYBUNDLE_H #define __PYBUNDLE_H #include #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) #error You need at least flext version 0.5.0 #endif #if FLEXT_OS == FLEXT_OS_MAC #include #else #include #endif #ifdef _MSC_VER #ifdef PY_EXPORTS #define PY_EXPORT __declspec(dllexport) #else #define PY_EXPORT __declspec(dllimport) #endif #else #define PY_EXPORT #endif typedef struct { PyObject_HEAD /* Type-specific fields go here. */ flext::MsgBundle *bundle; } pyBundle; PY_EXPORT extern PyTypeObject pyBundle_Type; #define pyBundle_Check(op) PyObject_TypeCheck(op, &pyBundle_Type) #define pyBundle_CheckExact(op) ((op)->ob_type == &pyBundle_Type) inline flext::MsgBundle *pyBundle_AS_BUNDLE(PyObject *op) { return ((pyBundle *)op)->bundle; } inline flext::MsgBundle *pyBundle_AsBundle(PyObject *op) { return pyBundle_Check(op)?pyBundle_AS_BUNDLE(op):NULL; } #endif py/source/pymeth.cpp0000644000175000017500000003006113104443402015245 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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 "pybase.h" #include struct xlt { const t_symbol *from,*to; }; static const xlt xtdefs[] = { { flext::MakeSymbol("+"),flext::MakeSymbol("__add__") }, { flext::MakeSymbol("+="),flext::MakeSymbol("__iadd__") }, { flext::MakeSymbol("!+"),flext::MakeSymbol("__radd__") }, { flext::MakeSymbol("-"),flext::MakeSymbol("__sub__") }, { flext::MakeSymbol("-="),flext::MakeSymbol("__isub__") }, { flext::MakeSymbol("!-"),flext::MakeSymbol("__rsub__") }, { flext::MakeSymbol("*"),flext::MakeSymbol("__mul__") }, { flext::MakeSymbol("*="),flext::MakeSymbol("__imul__") }, { flext::MakeSymbol("!*"),flext::MakeSymbol("__rmul__") }, { flext::MakeSymbol("/"),flext::MakeSymbol("__div__") }, { flext::MakeSymbol("/="),flext::MakeSymbol("__idiv__") }, { flext::MakeSymbol("!/"),flext::MakeSymbol("__rdiv__") }, { flext::MakeSymbol("//"),flext::MakeSymbol("__floordiv__") }, { flext::MakeSymbol("//="),flext::MakeSymbol("__ifloordiv__") }, { flext::MakeSymbol("!//"),flext::MakeSymbol("__rfloordiv__") }, { flext::MakeSymbol("%"),flext::MakeSymbol("__mod__") }, { flext::MakeSymbol("%="),flext::MakeSymbol("__imod__") }, { flext::MakeSymbol("!%"),flext::MakeSymbol("__rmod__") }, { flext::MakeSymbol("**"),flext::MakeSymbol("__pow__") }, { flext::MakeSymbol("**="),flext::MakeSymbol("__ipow__") }, { flext::MakeSymbol("!**"),flext::MakeSymbol("__rpow__") }, { flext::MakeSymbol("&"),flext::MakeSymbol("__and__") }, { flext::MakeSymbol("&="),flext::MakeSymbol("__iand__") }, { flext::MakeSymbol("!&"),flext::MakeSymbol("__rand__") }, { flext::MakeSymbol("|"),flext::MakeSymbol("__or__") }, { flext::MakeSymbol("|="),flext::MakeSymbol("__ior__") }, { flext::MakeSymbol("!|"),flext::MakeSymbol("__ror__") }, { flext::MakeSymbol("^"),flext::MakeSymbol("__xor__") }, { flext::MakeSymbol("^="),flext::MakeSymbol("__ixor__") }, { flext::MakeSymbol("!^"),flext::MakeSymbol("__rxor__") }, { flext::MakeSymbol("<<"),flext::MakeSymbol("__lshift__") }, { flext::MakeSymbol("<<="),flext::MakeSymbol("__ilshift__") }, { flext::MakeSymbol("!<<"),flext::MakeSymbol("__rlshift__") }, { flext::MakeSymbol(">>"),flext::MakeSymbol("__rshift__") }, { flext::MakeSymbol(">>="),flext::MakeSymbol("__irshift__") }, { flext::MakeSymbol("!>>"),flext::MakeSymbol("__rrshift__") }, { flext::MakeSymbol("=="),flext::MakeSymbol("__eq__") }, { flext::MakeSymbol("!="),flext::MakeSymbol("__ne__") }, { flext::MakeSymbol("<"),flext::MakeSymbol("__lt__") }, { flext::MakeSymbol(">"),flext::MakeSymbol("__gt__") }, { flext::MakeSymbol("<="),flext::MakeSymbol("__le__") }, { flext::MakeSymbol(">="),flext::MakeSymbol("__ge__") }, { flext::MakeSymbol("!"),flext::MakeSymbol("__nonzero__") }, { flext::MakeSymbol("~"),flext::MakeSymbol("__invert__") }, { flext::MakeSymbol("[]"),flext::MakeSymbol("__getitem__") }, { flext::MakeSymbol("[]="),flext::MakeSymbol("__setitem__") }, { flext::MakeSymbol("[:]"),flext::MakeSymbol("__getslice__") }, { flext::MakeSymbol("[:]="),flext::MakeSymbol("__setslice__") }, { flext::MakeSymbol(".abs"),flext::MakeSymbol("__abs__") }, { flext::MakeSymbol(".neg"),flext::MakeSymbol("__neg__") }, { flext::MakeSymbol(".pos"),flext::MakeSymbol("__pos__") }, { flext::MakeSymbol(".divmod"),flext::MakeSymbol("__divmod__") }, { flext::MakeSymbol(".int"),flext::MakeSymbol("__int__") }, { flext::MakeSymbol(".long"),flext::MakeSymbol("__long__") }, { flext::MakeSymbol(".float"),flext::MakeSymbol("__float__") }, { flext::MakeSymbol(".complex"),flext::MakeSymbol("__complex__") }, { flext::MakeSymbol(".str"),flext::MakeSymbol("__str__") }, { flext::MakeSymbol(".coerce"),flext::MakeSymbol("__coerce__") }, { flext::MakeSymbol(".doc"),flext::MakeSymbol("__doc__") }, { flext::MakeSymbol(".repr"),flext::MakeSymbol("__repr__") }, { flext::MakeSymbol(".len"),flext::MakeSymbol("__len__") }, { flext::MakeSymbol(".in"),flext::MakeSymbol("__contains") }, { NULL,NULL } // sentinel }; typedef std::map XTable; static XTable xtable; class pymeth : public pybase , public flext_base { FLEXT_HEADER_S(pymeth,flext_base,Setup) public: pymeth(int argc,const t_atom *argv); ~pymeth(); protected: virtual void Exit(); virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv); void m_help(); void m_reload() { Reload(); } void m_reload_(int argc,const t_atom *argv) { args(argc,argv); Reload(); } void m_set(int argc,const t_atom *argv); void m_dir_() { m__dir(function); } void m_doc_() { m__doc(function); } const t_symbol *funname; PyObject *function; virtual void LoadModule(); virtual void UnloadModule(); virtual void Load(); virtual void Unload(); void SetFunction(const t_symbol *func); void ResetFunction(); virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv); PyObject **objects; private: virtual void callpy(PyObject *fun,PyObject *args); static void Setup(t_classid c); FLEXT_CALLBACK(m_help) FLEXT_CALLBACK(m_reload) FLEXT_CALLBACK_V(m_reload_) FLEXT_CALLBACK_V(m_set) FLEXT_CALLBACK(m_dir_) FLEXT_CALLBACK(m_doc_) // callbacks FLEXT_ATTRVAR_I(detach) FLEXT_ATTRVAR_B(pymsg) FLEXT_ATTRVAR_B(respond) FLEXT_CALLBACK_V(m_stop) FLEXT_CALLBACK(m_dir) FLEXT_CALLGET_V(mg_dir) FLEXT_CALLBACK(m_doc) #ifdef FLEXT_THREADS FLEXT_CALLBACK_T(tick) #endif }; FLEXT_LIB_V("pym",pymeth) void pymeth::Setup(t_classid c) { 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_CADDMETHOD_(c,0,"set",m_set); FLEXT_CADDATTR_VAR1(c,"py",pymsg); FLEXT_CADDATTR_VAR1(c,"respond",respond); // init translation map for(const xlt *xi = xtdefs; xi->from; ++xi) xtable[xi->from] = xi->to; } pymeth::pymeth(int argc,const t_atom *argv) : funname(NULL) , function(NULL) , objects(NULL) { #ifdef FLEXT_THREADS FLEXT_ADDTIMER(stoptmr,tick); #endif ThrLockSys lock; int inlets; if(argc && CanbeInt(*argv)) { inlets = GetAInt(*argv); if(inlets < 1) inlets = 1; argv++,argc--; } else inlets = 1; objects = new PyObject *[inlets]; for(int i = 0; i < inlets; ++i) { objects[i] = Py_None; Py_INCREF(Py_None); } if(inlets <= 0) InitProblem(); AddInAnything(1+(inlets < 0?1:inlets)); AddOutAnything(); Register(GetRegistry(REGNAME)); if(argc) { const t_symbol *funnm = GetASymbol(*argv); argv++,argc--; if(funnm) SetFunction(funnm); else PyErr_SetString(PyExc_ValueError,"Invalid function name"); } if(argc) args(argc,argv); Report(); } pymeth::~pymeth() { if(objects) { for(int i = 0; i < CntIn()-1; ++i) Py_DECREF(objects[i]); delete[] objects; } ThrLockSys lock; Unregister(GetRegistry(REGNAME)); Report(); } void pymeth::Exit() { pybase::Exit(); flext_base::Exit(); } void pymeth::m_set(int argc,const t_atom *argv) { ThrLockSys lock; // function name has precedence if(argc >= 2) { const char *sn = GetAString(*argv); ++argv,--argc; if(sn) { if(!module || !strcmp(sn,PyModule_GetName(module))) { ImportModule(sn); Register(GetRegistry(REGNAME)); } } else PyErr_SetString(PyExc_ValueError,"Invalid module name"); } if(argc) { const t_symbol *fn = GetASymbol(*argv); if(fn) SetFunction(fn); else PyErr_SetString(PyExc_ValueError,"Invalid function name"); } Report(); } void pymeth::m_help() { post(""); post("%s %s - python method object, (C)2002-2012 Thomas Grill",thisName(),PY__VERSION); #ifdef FLEXT_DEBUG post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__); #endif post("Arguments: %s [method 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"); post("\tdir: dump module dictionary"); post("\tdir+: dump function dictionary"); #ifdef FLEXT_THREADS post("\tdetach 0/1/2: detach threads"); post("\tstop {wait time (ms)}: stop threads"); #endif post(""); } void pymeth::ResetFunction() { Py_XDECREF(function); function = NULL; if(funname && objects[0] != Py_None) { function = PyObject_GetAttrString(objects[0],(char *)GetString(funname)); // new reference if(!function) PyErr_SetString(PyExc_AttributeError,"Method not found"); } // exception could be set here } void pymeth::SetFunction(const t_symbol *func) { // look for method name in translation table XTable::iterator it = xtable.find(func); funname = it == xtable.end()?func:it->second; ResetFunction(); } void pymeth::LoadModule() { SetFunction(funname); } void pymeth::UnloadModule() { } void pymeth::Load() { ResetFunction(); } void pymeth::Unload() { SetFunction(NULL); } void pymeth::callpy(PyObject *fun,PyObject *args) { PyObject *ret = PyObject_CallObject(fun,args); if(ret) { OutObject(this,0,ret); // exception might be raised here Py_DECREF(ret); } } bool pymeth::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) { if(n == 0 && s != sym_bang) return flext_base::CbMethodResort(n,s,argc,argv); ThrState state = PyLockSys(); bool ret = false; if(n >= 1) { // store args PyObject *&obj = objects[n-1]; Py_DECREF(obj); obj = MakePyArg(s,argc,argv); // steal reference if(n > 1) ret = true; // just store, don't trigger } if(!ret) { if(function) { PyObject *self = PyMethod_Self(function); PyErr_Clear(); if(!self || self->ob_type != objects[0]->ob_type) // type has changed, search for new method ResetFunction(); else if(self != objects[0]) { // type hasn't changed, but object has PyObject *f = function; function = PyMethod_New(PyMethod_GET_FUNCTION(f),objects[0],PyMethod_GET_CLASS(f)); Py_DECREF(f); } } else ResetFunction(); if(function) { Py_INCREF(function); int inlets = CntIn()-1; PyObject *pargs = PyTuple_New(inlets-1); for(int i = 1; i < inlets; ++i) { Py_INCREF(objects[i]); PyTuple_SET_ITEM(pargs,i-1,objects[i]); } gencall(function,pargs); // references are stolen ret = true; } else PyErr_SetString(PyExc_RuntimeError,"No function set"); Report(); } PyUnlock(state); Respond(ret); return ret; } void pymeth::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) { ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); } py/source/main.cpp0000644000175000017500000000041513104443402014663 0ustar zmoelnigzmoelnig/* py/pyext - python external object for PD and MaxMSP Copyright (c)2002-2015 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 "pybase.h" py/source/pyext.h0000644000175000017500000000772513104443402014570 0ustar zmoelnigzmoelnig/* py/pyext - python external object for PD and MaxMSP Copyright (c)2002-2015 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. */ #ifndef __PYEXT_H #define __PYEXT_H #include "pybase.h" class pyext : public pybase , public flext_dsp { FLEXT_HEADER_S(pyext,flext_dsp,Setup) public: pyext(int argc,const t_atom *argv,bool sig = false); static PyObject *pyext__str__(PyObject *,PyObject *args); static PyObject *pyext_outlet(PyObject *,PyObject *args); #if FLEXT_SYS == FLEXT_SYS_PD static PyObject *pyext_tocanvas(PyObject *,PyObject *args); #endif static PyObject *pyext_setattr(PyObject *,PyObject *args); static PyObject *pyext_getattr(PyObject *,PyObject *args); static PyObject *pyext_detach(PyObject *,PyObject *args); static PyObject *pyext_stop(PyObject *,PyObject *args); static PyObject *pyext_isthreaded(PyObject *,PyObject *); static PyObject *pyext_inbuf(PyObject *,PyObject *args); static PyObject *pyext_invec(PyObject *,PyObject *args); static PyObject *pyext_outbuf(PyObject *,PyObject *args); static PyObject *pyext_outvec(PyObject *,PyObject *args); int Inlets() const { return inlets; } int Outlets() const { return outlets; } static pyext *GetThis(PyObject *self); protected: virtual bool Init(); virtual bool Finalize(); virtual void Exit(); virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv); virtual void CbClick(); virtual bool CbDsp(); virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv); bool work(int n,const t_symbol *s,int argc,const t_atom *argv); void m_help(); void m_reload() { Reload(); } void m_reload_(int argc,const t_atom *argv) { initargs(argc,argv); Reload(); } void ms_initargs(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); } 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; int siginlets,sigoutlets; flext::AtomList initargs; virtual void LoadModule(); virtual void UnloadModule(); virtual void Load(); virtual void Unload(); virtual bool DoInit(); virtual void DoExit(); virtual PyObject *GetSig(int ix,bool in); private: static void Setup(t_classid); void SetThis(); void ClearThis(); void ClearBinding(); bool MakeInstance(); bool InitInOut(int &inlets,int &outlets); static PyObject *class_obj,*class_dict; static PyMethodDef attr_tbl[],meth_tbl[]; static const char *pyext_doc; // -------- bind stuff ------------------ static PyObject *pyext_bind(PyObject *,PyObject *args); static PyObject *pyext_unbind(PyObject *,PyObject *args); // --------------------------- bool call(const char *meth,int inlet,const t_symbol *s,int argc,const t_atom *argv); virtual void callpy(PyObject *fun,PyObject *args); static bool stcallpy(PyObject *fun,PyObject *args); #ifndef PY_USE_GIL ThrState pythr; #endif private: static bool boundmeth(flext_base *,t_symbol *sym,int argc,t_atom *argv,void *data); FLEXT_CALLBACK(m_help) FLEXT_CALLBACK(m_reload) FLEXT_CALLBACK_V(m_reload_) FLEXT_CALLBACK(m_dir_) FLEXT_CALLGET_V(mg_dir_) FLEXT_CALLBACK(m_doc_) FLEXT_ATTRGET_V(initargs) FLEXT_CALLSET_V(ms_initargs) FLEXT_CALLBACK_S(m_get) FLEXT_CALLBACK_V(m_set) // callbacks FLEXT_ATTRVAR_I(detach) FLEXT_ATTRVAR_B(pymsg) FLEXT_ATTRVAR_B(respond) FLEXT_CALLBACK_V(m_stop) FLEXT_CALLBACK(m_dir) FLEXT_CALLGET_V(mg_dir) FLEXT_CALLBACK(m_doc) FLEXT_CALLBACK(CbClick) #ifdef FLEXT_THREADS FLEXT_CALLBACK_T(tick) #endif }; #endif py/source/py.cpp0000644000175000017500000002351513104443402014375 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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 "pybase.h" class pyobj : public pybase , public flext_base { FLEXT_HEADER_S(pyobj,flext_base,Setup) public: pyobj(int argc,const t_atom *argv); ~pyobj(); protected: virtual void Exit(); virtual bool CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv); virtual void CbClick(); void m_help(); void m_reload() { Reload(); } void m_reload_(int argc,const t_atom *argv) { args(argc,argv); Reload(); } void m_set(int argc,const t_atom *argv); void m_dir_() { m__dir(function); } void m_doc_() { m__doc(function); } const t_symbol *funname; PyObject *function; bool withfunction; virtual void LoadModule(); virtual void UnloadModule(); virtual void Load(); virtual void Unload(); bool SetFunction(const t_symbol *func); bool ResetFunction(); virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv); PyObject **objects; private: virtual void callpy(PyObject *fun,PyObject *args); static void Setup(t_classid c); FLEXT_CALLBACK(m_help) FLEXT_CALLBACK(m_reload) FLEXT_CALLBACK_V(m_reload_) FLEXT_CALLBACK_V(m_set) FLEXT_CALLBACK(m_dir_) FLEXT_CALLBACK(m_doc_) // callbacks FLEXT_ATTRVAR_I(detach) FLEXT_ATTRVAR_B(pymsg) FLEXT_ATTRVAR_B(respond) FLEXT_CALLBACK_V(m_stop) FLEXT_CALLBACK(m_dir) FLEXT_CALLGET_V(mg_dir) FLEXT_CALLBACK(m_doc) FLEXT_CALLBACK(CbClick) #ifdef FLEXT_THREADS FLEXT_CALLBACK_T(tick) #endif }; FLEXT_LIB_V("py",pyobj) void pyobj::Setup(t_classid c) { 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_CADDMETHOD_(c,0,"set",m_set); FLEXT_CADDMETHOD_(c,0,"edit",CbClick); FLEXT_CADDATTR_VAR1(c,"py",pymsg); FLEXT_CADDATTR_VAR1(c,"respond",respond); } pyobj::pyobj(int argc,const t_atom *argv) : funname(NULL) , function(NULL) , withfunction(false) , objects(NULL) { #ifdef FLEXT_THREADS FLEXT_ADDTIMER(stoptmr,tick); #endif ThrState state = PyLockSys(); int inlets; if(argc && CanbeInt(*argv)) { inlets = GetAInt(*argv); if(inlets < 0) inlets = 1; argv++,argc--; } else // -1 signals non-explicit definition inlets = -1; if(inlets >= 1) { objects = new PyObject *[inlets]; for(int i = 0; i < inlets; ++i) { objects[i] = Py_None; Py_INCREF(Py_None); } } AddInAnything(1+(inlets < 0?1:inlets)); AddOutAnything(); const t_symbol *funnm = NULL; // init script module if(argc) { AddCurrentPath(this); const char *sn = GetAString(*argv); argv++,argc--; if(sn) { char modnm[64]; strcpy(modnm,sn); char *pt = strrchr(modnm,'.'); // search for last dot if(pt && *pt) { funnm = MakeSymbol(pt+1); *pt = 0; } if(*modnm) ImportModule(modnm); else ImportModule(NULL); } else PyErr_SetString(PyExc_ValueError,"Invalid module name"); } Register(GetRegistry(REGNAME)); if(funnm || argc) { if(!funnm) { funnm = GetASymbol(*argv); argv++,argc--; } if(funnm) SetFunction(funnm); else PyErr_SetString(PyExc_ValueError,"Invalid function name"); } if(argc) args(argc,argv); Report(); PyUnlock(state); } pyobj::~pyobj() { ThrState state = PyLockSys(); if(objects) { for(int i = 0; i < CntIn()-1; ++i) Py_DECREF(objects[i]); delete[] objects; } Unregister(GetRegistry(REGNAME)); Report(); PyUnlock(state); } void pyobj::Exit() { pybase::Exit(); flext_base::Exit(); } void pyobj::m_set(int argc,const t_atom *argv) { ThrState state = PyLockSys(); // function name has precedence if(argc >= 2) { const char *sn = GetAString(*argv); ++argv,--argc; if(sn) { // if(!module || !strcmp(sn,PyModule_GetName(module))) { ImportModule(sn); Register(GetRegistry(REGNAME)); } } else PyErr_SetString(PyExc_ValueError,"Invalid module name"); } if(argc) { const t_symbol *fn = GetASymbol(*argv); if(fn) SetFunction(fn); else PyErr_SetString(PyExc_ValueError,"Invalid function name"); } Report(); PyUnlock(state); } void pyobj::m_help() { post(""); post("%s %s - python script object, (C)2002-2012 Thomas Grill",thisName(),PY__VERSION); #ifdef FLEXT_DEBUG post("DEBUG VERSION, 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"); post("\tdir: dump module dictionary"); post("\tdir+: dump function dictionary"); #ifdef FLEXT_THREADS post("\tdetach 0/1/2: detach threads"); post("\tstop {wait time (ms)}: stop threads"); #endif post(""); } bool pyobj::ResetFunction() { // function was borrowed from dict! function = NULL; if(!dict) post("%s - No namespace available",thisName()); else { if(funname) { function = PyDict_GetItemString(dict,(char *)GetString(funname)); // borrowed!!! if(!function && dict == module_dict) // search also in __builtins__ function = PyDict_GetItemString(builtins_dict,(char *)GetString(funname)); // borrowed!!! if(!function) PyErr_SetString(PyExc_AttributeError,"Function not found"); else if(!PyCallable_Check(function)) { function = NULL; PyErr_SetString(PyExc_TypeError,"Attribute is not callable"); } } } // exception could be set here return function != NULL; } bool pyobj::SetFunction(const t_symbol *func) { if(func) { funname = func; withfunction = ResetFunction(); } else { function = NULL,funname = NULL; withfunction = false; } // exception could be set here return withfunction; } void pyobj::LoadModule() { SetFunction(funname); } void pyobj::UnloadModule() { } void pyobj::Load() { ResetFunction(); } void pyobj::Unload() { // SetFunction(NULL); function = NULL; // just clear the PyObject, not the function name } void pyobj::callpy(PyObject *fun,PyObject *args) { PyObject *ret = PyObject_CallObject(fun,args); if(ret) { OutObject(this,0,ret); // exception might be raised here Py_DECREF(ret); } } bool pyobj::CbMethodResort(int n,const t_symbol *s,int argc,const t_atom *argv) { if(n == 0 && s != sym_bang) return flext_base::CbMethodResort(n,s,argc,argv); ThrState state = PyLockSys(); bool ret = false; if(objects && n >= 1) { // store args PyObject *&obj = objects[n-1]; Py_DECREF(obj); obj = MakePyArg(s,argc,argv); // steal reference if(n > 1) ret = true; // just store, don't trigger } if(!ret) { if(withfunction) { if(function) { Py_INCREF(function); PyObject *pargs; if(objects || CntIn() == 1) { int inlets = CntIn()-1; pargs = PyTuple_New(inlets); for(int i = 0; i < inlets; ++i) { Py_INCREF(objects[i]); PyTuple_SET_ITEM(pargs,i,objects[i]); } } else // construct tuple from args // if n == 0, it's a pure bang pargs = MakePyArgs(n?s:NULL,argc,argv); gencall(function,pargs); // references are stolen ret = true; } else PyErr_SetString(PyExc_RuntimeError,"No function set"); } else if(module) { // no function defined as creation argument -> use message tag if(s) { PyObject *func = PyObject_GetAttrString(module,const_cast(GetString(s))); if(func) { PyObject *pargs = MakePyArgs(sym_list,argc,argv); gencall(func,pargs); ret = true; } } else PyErr_SetString(PyExc_RuntimeError,"No function set"); } Report(); } PyUnlock(state); Respond(ret); return ret; } void pyobj::CbClick() { pybase::OpenEditor(); } void pyobj::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) { ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); } py/source/pybuffer.cpp0000644000175000017500000005537213104443402015575 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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 "pybase.h" #undef PY_ARRAYS #if defined(PY_NUMERIC) || defined(PY_NUMPY) || defined(PY_NUMARRAY) #define PY_ARRAYS 1 #endif #ifdef PY_ARRAYS #ifdef PY_NUMARRAY # if FLEXT_OS == FLEXT_OS_MAC # include # else # include # endif static NumarrayType numtype = tAny; inline bool arrsupport() { return numtype != tAny; } #else # if defined(PY_NUMPY) # include # else # if FLEXT_OS == FLEXT_OS_MAC # include # else # include # endif # endif static PyArray_TYPES numtype = PyArray_NOTYPE; inline bool arrsupport() { return numtype != PyArray_NOTYPE; } #endif #endif PyObject *pybase::py_arraysupport(PyObject *self,PyObject *args) { PyObject *ret; #ifdef PY_ARRAYS ret = Py_True; #else ret = Py_False; #endif Py_INCREF(ret); return ret; } // PD defines a T_OBJECT symbol #undef T_OBJECT #if FLEXT_OS == FLEXT_OS_MAC #include "Python/bufferobject.h" #include "Python/structmember.h" #else #include "bufferobject.h" #include "structmember.h" #endif static PyObject *buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { pySamplebuffer *self = (pySamplebuffer *)pySamplebuffer_Type.tp_alloc(&pySamplebuffer_Type, 0); self->sym = NULL; self->buf = NULL; self->dirty = false; return (PyObject *)self; } static void buffer_dealloc(PyObject *obj) { pySamplebuffer *self = (pySamplebuffer *)obj; if(self->buf) { self->buf->Unlock(self->lock); if(self->dirty) self->buf->Dirty(true); delete self->buf; } obj->ob_type->tp_free(obj); } static int buffer_init(PyObject *obj, PyObject *args, PyObject *kwds) { FLEXT_ASSERT(pySamplebuffer_Check(obj)); PyObject *arg = PySequence_GetItem(args,0); // new reference if(!arg) return -1; int ret = 0; pySamplebuffer *self = (pySamplebuffer *)obj; FLEXT_ASSERT(!self->sym && !self->buf); if(pySymbol_Check(arg)) self->sym = pySymbol_AS_SYMBOL(arg); else if(PyString_Check(arg)) self->sym = flext::MakeSymbol(PyString_AS_STRING(arg)); else ret = -1; Py_DECREF(arg); if(self->sym) { flext::buffer *b = new flext::buffer(self->sym); if(b->Ok() && b->Valid()) self->lock = (self->buf = b)->Lock(); else delete b; } return ret; } static PyObject *buffer_repr(PyObject *self) { FLEXT_ASSERT(pySamplebuffer_Check(self)); return (PyObject *)PyString_FromFormat("",pySamplebuffer_AS_STRING(self)); } static long buffer_hash(PyObject *self) { FLEXT_ASSERT(pySamplebuffer_Check(self)); return (long)(((pySamplebuffer *)self)->buf); } static PyObject *buffer_getsymbol(pySamplebuffer* self,void *closure) { if(self->sym) return pySymbol_FromSymbol(self->sym); else { Py_INCREF(Py_None); return Py_None; } } static PyGetSetDef buffer_getseters[] = { {const_cast("symbol"),(getter)buffer_getsymbol, NULL, NULL}, {NULL} /* Sentinel */ }; static PyObject *buffer_dirty(PyObject *obj) { ((pySamplebuffer *)obj)->dirty = true; Py_INCREF(Py_None); return Py_None; } static PyObject *buffer_resize(PyObject *obj,PyObject *args,PyObject *kwds) { flext::buffer *b = ((pySamplebuffer *)obj)->buf; if(b) { int frames,keep = 1,zero = 1; static char const *kwlist[] = {"frames", "keep", "zero", NULL}; if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", (char **)kwlist, &frames, &keep, &zero)) return NULL; b->Frames(frames,keep != 0,zero != 0); Py_INCREF(obj); return obj; } else { PyErr_SetString(PyExc_RuntimeError,"Invalid buffer"); return NULL; } } static PyMethodDef buffer_methods[] = { {"dirty", (PyCFunction)buffer_dirty,METH_NOARGS,"Mark buffer as dirty"}, {"resize", (PyCFunction)buffer_resize,METH_VARARGS|METH_KEYWORDS,"Resize buffer"}, {NULL} /* Sentinel */ }; // support the buffer protocol static Py_ssize_t buffer_readbuffer(PyObject *obj, Py_ssize_t segment, void **ptrptr) { flext::buffer *b = ((pySamplebuffer *)obj)->buf; ptrptr[0] = b->Data(); return b->Channels()*b->Frames()*sizeof(t_sample); } static Py_ssize_t buffer_writebuffer(PyObject *obj, Py_ssize_t segment, void **ptrptr) { flext::buffer *b = ((pySamplebuffer *)obj)->buf; ptrptr[0] = b->Data(); return b->Channels()*b->Frames()*sizeof(t_sample); } static Py_ssize_t buffer_segcount(PyObject *obj, Py_ssize_t *lenp) { flext::buffer *b = ((pySamplebuffer *)obj)->buf; if(lenp) lenp[0] = b->Channels()*b->Frames()*sizeof(t_sample); return 1; } static Py_ssize_t buffer_charbuffer(PyObject *obj, Py_ssize_t segment, #if PY_VERSION_HEX < 0x02050000 const #endif char **ptrptr) { flext::buffer *b = ((pySamplebuffer *)obj)->buf; ptrptr[0] = (char *)b->Data(); return b->Channels()*b->Frames()*sizeof(t_sample); } static PyBufferProcs buffer_as_buffer = { buffer_readbuffer, buffer_writebuffer, buffer_segcount, buffer_charbuffer }; static Py_ssize_t buffer_length(PyObject *s) { pySamplebuffer *self = reinterpret_cast(s); return self->buf?self->buf->Frames():0; } static PyObject *buffer_item(PyObject *s,Py_ssize_t i) { pySamplebuffer *self = reinterpret_cast(s); 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(Py_None); ret = Py_None; } return ret; } #ifndef PY_NUMPY typedef int npy_intp; #endif PyObject *arrayfrombuffer(PyObject *buf,int c,int n) { #ifdef PY_ARRAYS if(arrsupport()) { PyObject *arr; npy_intp shape[2] = {n,c}; #ifdef PY_NUMARRAY arr = (PyObject *)NA_NewAllFromBuffer(c == 1?1:2,shape,numtype,buf,0,0,NA_ByteOrder(),1,1); #else void *data; Py_ssize_t len; int err = PyObject_AsWriteBuffer(buf,&data,&len); if(!err) { FLEXT_ASSERT(len <= n*c*sizeof(t_sample)); // Py_INCREF(buf); // ATTENTION... this won't be released any more!! # ifdef PY_NUMPY arr = PyArray_NewFromDescr(&PyArray_Type,PyArray_DescrNewFromType(numtype),c == 1?1:2,shape,0,(char *)data,NPY_WRITEABLE|NPY_C_CONTIGUOUS,NULL); # else arr = PyArray_FromDimsAndData(c == 1?1:2,shape,numtype,(char *)data); # endif } else { // exception string is already set arr = NULL; } #endif return arr; } else #endif return NULL; } static PyObject *buffer_slice(PyObject *s,Py_ssize_t ilow = 0,Py_ssize_t ihigh = 1<<(sizeof(int)*8-2)) { pySamplebuffer *self = reinterpret_cast(s); PyObject *ret; #ifdef PY_ARRAYS if(arrsupport()) { 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; PyObject *nobj = arrayfrombuffer((PyObject *)self,c,n); if(ilow != 0 || ihigh != n) { ret = PySequence_GetSlice(nobj,ilow,ihigh); Py_DECREF(nobj); } else ret = nobj; } else { Py_INCREF(Py_None); ret = Py_None; } } else #endif { PyErr_SetString(PyExc_RuntimeError,"No array support"); ret = NULL; } return ret; } static int buffer_ass_item(PyObject *s,Py_ssize_t i,PyObject *v) { pySamplebuffer *self = reinterpret_cast(s); 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 array"); 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(PyObject *s,Py_ssize_t ilow,Py_ssize_t ihigh,PyObject *value) { pySamplebuffer *self = reinterpret_cast(s); int ret; #ifdef PY_ARRAYS if(arrsupport()) { 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; #ifdef PY_NUMARRAY PyArrayObject *out = NA_InputArray(value,numtype,NUM_C_ARRAY); const t_sample *src = (t_sample *)NA_OFFSETDATA(out); #else PyArrayObject *out = (PyArrayObject *)PyArray_ContiguousFromObject(value,numtype,1,2); const t_sample *src = (t_sample *)out->data; #endif if(!out) { // exception already set 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]; int cnt = slen < dlen?slen:dlen; flext::buffer::Element *dst = self->buf->Data()+ilow; for(int i = 0; i < cnt; ++i) dst[i] = src[i]; 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 array support"); ret = -1; } return ret; } static PyObject *buffer_concat(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,Py_ssize_t rep) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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 = { buffer_length, /* inquiry sq_length; __len__ */ buffer_concat, /* __add__ */ buffer_repeat, /* __mul__ */ buffer_item, /* intargfunc sq_item; __getitem__ */ buffer_slice, /* intintargfunc sq_slice; __getslice__ */ buffer_ass_item, /* intobjargproc sq_ass_item; __setitem__ */ buffer_ass_slice, /* intintobjargproc sq_ass_slice; __setslice__ */ }; static PyObject *buffer_iter(PyObject *s) { // pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); if(nobj) { PyObject *it = PyObject_GetIter(nobj); Py_DECREF(nobj); return it; } else return NULL; } static PyObject *buffer_add(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op1,PyObject *op2) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s) { // pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); if(nobj) { PyObject *ret = PyNumber_Positive(nobj); Py_DECREF(nobj); return ret; } else return NULL; } static PyObject *buffer_absolute(PyObject *s) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject **pm, PyObject **pw) { if(pySamplebuffer_Check(*pw)) { Py_INCREF(*pm); Py_INCREF(*pw); return 0; } else return 1; } static PyObject *buffer_inplace_add(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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(PyObject *s,PyObject *op1,PyObject *op2) { pySamplebuffer *self = reinterpret_cast(s); PyObject *nobj = buffer_slice(s); 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*/ "Buffer", /*tp_name*/ sizeof(pySamplebuffer), /*tp_basicsize*/ 0, /*tp_itemsize*/ buffer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ buffer_repr, /*tp_repr*/ &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*/ &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 */ buffer_iter, /* tp_iter */ 0, /* tp_iternext */ buffer_methods, /* tp_methods */ 0, /* tp_members */ buffer_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ buffer_init, /* tp_init */ 0, /* tp_alloc */ buffer_new, /* tp_new */ }; // Must have this as a function because the import_array macro in numpy version 1.01 strangely has a return statement included. // Furthermore the import error printout from this macro is ugly, but we accept that for now, waiting for later numpy updates to fix all of this. #ifdef PY_ARRAYS static void __import_array__() { #ifdef PY_NUMARRAY import_libnumarray(); #else import_array(); #endif } #endif void initsamplebuffer() { #ifdef PY_ARRAYS __import_array__(); if(PyErr_Occurred()) // catch import error PyErr_Clear(); else { // numarray support ok #ifdef PY_NUMARRAY numtype = sizeof(t_sample) == 4?tFloat32:tFloat64; #else numtype = sizeof(t_sample) == 4?PyArray_FLOAT:PyArray_DOUBLE; #endif post(""); post("Python array support enabled"); } #endif if(PyType_Ready(&pySamplebuffer_Type) < 0) FLEXT_ASSERT(false); else Py_INCREF(&pySamplebuffer_Type); } py/source/pybuffer.h0000644000175000017500000000340513104443402015230 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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. */ #ifndef __PYBUFFER_H #define __PYBUFFER_H #include #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) #error You need at least flext version 0.5.0 #endif #if FLEXT_OS == FLEXT_OS_MAC #include #else #include #endif #ifdef _MSC_VER #ifdef PY_EXPORTS #define PY_EXPORT __declspec(dllexport) #else #define PY_EXPORT __declspec(dllimport) #endif #else #define PY_EXPORT #endif typedef struct { PyObject_HEAD /* Type-specific fields go here. */ const t_symbol *sym; flext::buffer *buf; flext::buffer::lock_t lock; bool dirty; } pySamplebuffer; PY_EXPORT extern PyTypeObject pySamplebuffer_Type; #define pySamplebuffer_Check(op) PyObject_TypeCheck(op, &pySamplebuffer_Type) #define pySamplebuffer_CheckExact(op) ((op)->ob_type == &pySamplebuffer_Type) PY_EXPORT PyObject *pySamplebuffer_FromSymbol(const t_symbol *sym); inline PyObject *pySamplebuffer_FromString(const char *str) { return pySamplebuffer_FromSymbol(flext::MakeSymbol(str)); } inline PyObject *pySamplebuffer_FromString(PyObject *str) { return pySamplebuffer_FromString(PyString_AsString(str)); } inline const t_symbol *pySamplebuffer_AS_SYMBOL(PyObject *op) { return ((pySamplebuffer *)op)->sym; } inline const t_symbol *pySamplebuffer_AsSymbol(PyObject *op) { return pySamplebuffer_Check(op)?pySamplebuffer_AS_SYMBOL(op):NULL; } inline const char *pySamplebuffer_AS_STRING(PyObject *op) { return flext::GetString(pySamplebuffer_AS_SYMBOL(op)); } #endif py/source/clmeth.cpp0000644000175000017500000002636113104443402015223 0ustar zmoelnigzmoelnig/* py/pyext - python external 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. */ #include "pyext.h" PyMethodDef pyext::meth_tbl[] = { /* {"__init__", pyext::pyext__init__, METH_VARARGS, "Constructor"}, {"__del__", pyext::pyext__del__, METH_VARARGS, "Destructor"}, */ {"__str__", pyext::pyext__str__, METH_VARARGS, "stringify"}, {"_outlet", pyext::pyext_outlet, METH_VARARGS,"Send message to outlet"}, #if FLEXT_SYS == FLEXT_SYS_PD {"_tocanvas", pyext::pyext_tocanvas, METH_VARARGS,"Send message to canvas" }, #endif { "_bind", pyext::pyext_bind, METH_VARARGS,"Bind function to a receiving symbol" }, { "_unbind", pyext::pyext_unbind, METH_VARARGS,"Unbind function from a receiving symbol" }, #ifdef FLEXT_THREADS { "_detach", pyext::pyext_detach, METH_VARARGS,"Set detach flag for called methods" }, { "_stop", pyext::pyext_stop, METH_VARARGS,"Stop running threads" }, #endif { "_invec", pyext::pyext_invec, METH_VARARGS,"Get input vector" }, { "_outvec", pyext::pyext_outvec, METH_VARARGS,"Get output vector" }, {NULL, NULL, 0, NULL} /* Sentinel */ }; PyMethodDef pyext::attr_tbl[] = { { "__setattr__", pyext::pyext_setattr, METH_VARARGS,"Set class attribute" }, { "__getattr__", pyext::pyext_getattr, METH_VARARGS,"Get class attribute" }, { NULL, NULL,0,NULL }, }; const char *pyext::pyext_doc = "py/pyext - python external object for PD and Max/MSP, (C)2002-2008 Thomas Grill\n" "\n" "This is the pyext base class. Available methods:\n" "_outlet(self,ix,args...): Send a message to an indexed outlet\n" #if FLEXT_SYS == FLEXT_SYS_PD "_tocanvas(self,args...): Send a message to the parent canvas\n" #endif "_bind(self,name,func): Bind a python function to a symbol\n" "_unbind(self,name,func): Unbind a python function from a symbol\n" "_isthreaded: Query whether threading is enabled\n" #ifdef FLEXT_THREADS "_detach(self,int): Define whether a called Python method has its own thread\n" "_stop(self): Stop running threads\n" "_shouldexit: Query whether threads should terminate\n" #endif ; /* PyObject* pyext::pyext__init__(PyObject *,PyObject *args) { // post("pyext.__init__ called"); Py_INCREF(Py_None); return Py_None; } PyObject* pyext::pyext__del__(PyObject *,PyObject *args) { // post("pyext.__del__ called"); Py_INCREF(Py_None); return Py_None; } */ PyObject* pyext::pyext__str__(PyObject *,PyObject *args) { PyObject *self; if(!PyArg_ParseTuple(args, "O:pyext__str__",&self)) { // handle error ERRINTERNAL(); return NULL; } return PyString_FromFormat("",self); } PyObject* pyext::pyext_setattr(PyObject *,PyObject *args) { PyObject *self,*name,*val; if(!PyArg_ParseTuple(args, "OOO:pyext_setattr", &self,&name,&val)) { // handle error ERRINTERNAL(); return NULL; } bool handled = false; /* if(PyString_Check(name)) { char* sname = PyString_AsString(name); if (sname) { // post("pyext::setattr %s",sname); } } */ if(!handled) { if(PyInstance_Check(self)) PyDict_SetItem(((PyInstanceObject *)self)->in_dict, name,val); else ERRINTERNAL(); } Py_INCREF(Py_None); return Py_None; } PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) { PyObject *self,*name,*ret = NULL; if(!PyArg_ParseTuple(args, "OO:pyext_getattr", &self,&name)) { // handle error ERRINTERNAL(); } if(PyString_Check(name)) { char* sname = PyString_AS_STRING(name); if(sname) { #ifdef FLEXT_THREADS if(!strcmp(sname,"_shouldexit")) { pyext *ext = GetThis(self); if(ext) ret = PyLong_FromLong(ext->shouldexit?1:0); else { // return true for _shouldexit if association has been removed Py_INCREF(Py_True); ret = Py_True; } } else #endif if(!strcmp(sname,"_isthreaded")) { #ifdef FLEXT_THREADS Py_INCREF(Py_True); ret = Py_True; #else Py_INCREF(Py_False); ret = Py_False; #endif } } } if(!ret) { #if PY_VERSION_HEX >= 0x02020000 ret = PyObject_GenericGetAttr(self,name); // new reference (?) #else if(PyInstance_Check(self)) // borrowed reference ret = PyDict_GetItem(((PyInstanceObject *)self)->in_dict,name); #endif } return ret; } //! Send message to outlet PyObject *pyext::pyext_outlet(PyObject *,PyObject *args) { bool ok = false; // should always be a tuple! FLEXT_ASSERT(PyTuple_Check(args)); int sz = PyTuple_GET_SIZE(args); // borrowed references! PyObject *self,*outl; if( sz >= 2 && (self = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(self) && (outl = PyTuple_GET_ITEM(args,1)) != NULL && PyInt_Check(outl) ) { pyext *ext = GetThis(self); if(!ext) { PyErr_SetString(PyExc_RuntimeError,"pyext - _outlet: instance not associated with pd object"); return NULL; } PyObject *val; #if 0 if(sz == 3) { val = PyTuple_GET_ITEM(args,2); // borrow reference Py_INCREF(val); tp = PySequence_Check(val); } else tp = false; if(!tp) val = PySequence_GetSlice(args,2,sz); // new ref #else if(sz == 3) { val = PyTuple_GET_ITEM(args,2); // borrow reference Py_INCREF(val); } else val = PyTuple_GetSlice(args,2,sz); // new ref #endif int o = PyInt_AS_LONG(outl); if(o >= 1 && o <= ext->Outlets()) { // offset outlet by signal outlets o += ext->sigoutlets; if(ext->OutObject(ext,o-1,val)) ok = true; else PyErr_SetString(PyExc_ValueError,"pyext - _outlet: invalid arguments"); } else PyErr_SetString(PyExc_ValueError,"pyext - _outlet: index out of range"); Py_DECREF(val); } else PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _outlet(self,outlet,args...)"); if(!ok) return NULL; Py_INCREF(Py_None); return Py_None; } #ifdef FLEXT_THREADS //! Detach threads PyObject *pyext::pyext_detach(PyObject *,PyObject *args) { PyObject *self; int val; if(!PyArg_ParseTuple(args, "Oi:pyext_detach",&self,&val)) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _detach(self,[0/1/2])"); return NULL; } else if(val < 0 || val > 2) { PyErr_SetString(PyExc_ValueError,"pyext - _detach must be in the range 0..2"); return NULL; } else { pyext *ext = GetThis(self); if(!ext) { PyErr_SetString(PyExc_RuntimeError,"pyext - _detach: instance not associated with pd object"); return NULL; } ext->detach = val; } Py_INCREF(Py_None); return Py_None; } //! Stop running threads PyObject *pyext::pyext_stop(PyObject *,PyObject *args) { PyObject *self; int val = -1; if(!PyArg_ParseTuple(args, "O|i:pyext_stop",&self,&val)) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _stop(self,{wait time})"); return NULL; } else if(val < 0) { PyErr_SetString(PyExc_ValueError,"pyext - _stop time must be >= 0"); return NULL; } else { pyext *ext = GetThis(self); if(!ext) { PyErr_SetString(PyExc_RuntimeError,"pyext - _stop: instance not associated with pd object"); return NULL; } int cnt; t_atom at; if(val >= 0) cnt = 1,flext::SetInt(at,val); else cnt = 0; ext->m_stop(cnt,&at); } Py_INCREF(Py_None); return Py_None; } #endif #if FLEXT_SYS == FLEXT_SYS_PD //! Send message to canvas PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) { FLEXT_ASSERT(PyTuple_Check(args)); int sz = PyTuple_GET_SIZE(args); bool ok = false; PyObject *self; // borrowed ref if( sz >= 1 && (self = PyTuple_GET_ITEM(args,0)) != NULL && PyInstance_Check(self) ) { pyext *ext = GetThis(self); if(!ext) { PyErr_SetString(PyExc_RuntimeError,"pyext - _tocanvas: instance not associated with pd object"); return NULL; } PyObject *val; bool tp = sz == 2 && PySequence_Check( val = PyTuple_GET_ITEM(args,1) // borrowed ref ); if(!tp) val = PyTuple_GetSlice(args,1,sz); // new ref flext::AtomListStatic<16> lst; const t_symbol *sym = GetPyArgs(lst,val); if(sym) { t_glist *gl = ext->thisCanvas(); if(gl) { // \TODO find a flext-based non-locking method sys_lock(); pd_forwardmess((t_class **)gl,lst.Count(),lst.Atoms()); sys_unlock(); } #ifdef FLEXT_DEBUG else post("pyext - no parent canvas?!"); #endif ok = true; } else post("py/pyext - No data to send"); if(!tp) Py_DECREF(val); } if(!ok) { PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _tocanvas(self,args...)"); return NULL; } Py_INCREF(Py_None); return Py_None; } #endif PyObject *pyext::pyext_invec(PyObject *,PyObject *args) { PyObject *self; int val = -1; if(!PyArg_ParseTuple(args, "O|i:pyext_invec",&self,&val)) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _invec(self,inlet)"); return NULL; } else if(val < 0) { PyErr_SetString(PyExc_ValueError,"pyext - _invec: index out of range"); return NULL; } else { pyext *ext = GetThis(self); if(ext) { PyObject *b = ext->GetSig(val,true); if(b) return b; } else { PyErr_SetString(PyExc_RuntimeError,"pyext - _invec: instance not associated with pd object"); return NULL; } } Py_INCREF(Py_None); return Py_None; } PyObject *pyext::pyext_outvec(PyObject *,PyObject *args) { PyObject *self; int val = -1; if(!PyArg_ParseTuple(args, "O|i:pyext_outvec",&self,&val)) { // handle error PyErr_SetString(PyExc_SyntaxError,"pyext - Syntax: _outvec(self,inlet)"); return NULL; } else if(val < 0) { PyErr_SetString(PyExc_ValueError,"pyext - _outvec: index out of range"); return NULL; } else { pyext *ext = GetThis(self); if(ext) { PyObject *b = ext->GetSig(val,false); if(b) return b; } else { PyErr_SetString(PyExc_RuntimeError,"pyext - _outvec: instance not associated with pd object"); return NULL; } } Py_INCREF(Py_None); return Py_None; } py/source/pysymbol.cpp0000644000175000017500000001730113104443402015617 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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 "pyprefix.h" #include "pysymbol.h" inline pySymbol *symbol_newsym(const t_symbol *sym) { pySymbol *self = (pySymbol *)pySymbol_Type.tp_alloc(&pySymbol_Type, 0); if(self) self->sym = sym; return self; } static PyObject *symbol_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { return (PyObject *)symbol_newsym(flext::sym__); } static int symbol_init(PyObject *self, PyObject *args, PyObject *kwds) { FLEXT_ASSERT(pySymbol_Check(self)); PyObject *arg = PySequence_GetItem(args,0); // new reference if(!arg) return -1; int ret = 0; if(pySymbol_Check(arg)) ((pySymbol *)self)->sym = pySymbol_AS_SYMBOL(arg); else if(PyString_Check(arg)) ((pySymbol *)self)->sym = flext::MakeSymbol(PyString_AS_STRING(arg)); else { PyErr_SetString(PyExc_TypeError,"string or symbol argument expected"); ret = -1; } Py_DECREF(arg); return ret; } static PyObject *symbol_str(PyObject *self) { FLEXT_ASSERT(pySymbol_Check(self)); return (PyObject *)PyString_FromString(pySymbol_AS_STRING(self)); } static PyObject *symbol_repr(PyObject *self) { FLEXT_ASSERT(pySymbol_Check(self)); return (PyObject *)PyString_FromFormat("",pySymbol_AS_STRING(self)); } static PyObject *symbol_richcompare(PyObject *a,PyObject *b,int cmp) { if(pySymbol_Check(a) && pySymbol_Check(b)) { const t_symbol *asym = pySymbol_AS_SYMBOL(a); const t_symbol *bsym = pySymbol_AS_SYMBOL(b); int res = asym == bsym?0:strcmp(flext::GetString(asym),flext::GetString(bsym)); bool ret; switch(cmp) { case Py_LT: ret = res < 0; break; case Py_LE: ret = res <= 0; break; case Py_EQ: ret = res == 0; break; case Py_NE: ret = res != 0; break; case Py_GE: ret = res >= 0; break; case Py_GT: ret = res > 0; break; default: FLEXT_ASSERT(false); } return PyBool_FromLong(ret); } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } static long symbol_hash(PyObject *self) { FLEXT_ASSERT(pySymbol_Check(self)); return (long)pySymbol_AS_SYMBOL(self); } static Py_ssize_t symbol_length(PyObject *s) { pySymbol *self = reinterpret_cast(s); return strlen(flext::GetString(self->sym)); } static PyObject *symbol_item(PyObject *s,Py_ssize_t i) { pySymbol *self = reinterpret_cast(s); const char *str = flext::GetString(self->sym); int len = strlen(str); if(i < 0) i += len; if(i >= 0 && i < len) return PyString_FromStringAndSize(str+i,1); else { Py_INCREF(Py_None); return Py_None; } } static PyObject *symbol_slice(PyObject *s,Py_ssize_t ilow = 0,Py_ssize_t ihigh = 1<<(sizeof(int)*8-2)) { pySymbol *self = reinterpret_cast(s); const char *str = flext::GetString(self->sym); int len = strlen(str); if(ilow < 0) { ilow += len; if(ilow < 0) ilow = 0; } if(ihigh < 0) ihigh += len; if(ihigh >= len) ihigh = len-1; return PyString_FromStringAndSize(str+ilow,ilow <= ihigh?ihigh-ilow+1:0); } static PyObject *symbol_concat(PyObject *s,PyObject *op) { // pySymbol *self = reinterpret_cast(s); PyObject *nobj = symbol_slice(s); // take all if(nobj) { PyObject *ret = PySequence_Concat(nobj,op); Py_DECREF(nobj); return ret; } else return NULL; } static PyObject *symbol_repeat(PyObject *s,Py_ssize_t rep) { // pySymbol *self = reinterpret_cast(s); PyObject *nobj = symbol_slice(s); // take all if(nobj) { PyObject *ret = PySequence_Repeat(nobj,rep); Py_DECREF(nobj); return ret; } else return NULL; } static PySequenceMethods symbol_as_seq = { symbol_length, /* inquiry sq_length; __len__ */ symbol_concat, /* __add__ */ symbol_repeat, /* __mul__ */ symbol_item, /* intargfunc sq_item; __getitem__ */ symbol_slice, /* intintargfunc sq_slice; __getslice__ */ NULL, /* intobjargproc sq_ass_item; __setitem__ */ NULL, /* intintobjargproc sq_ass_slice; __setslice__ */ }; static PyObject *symbol_iter(PyObject *s) { // pySymbol *self = reinterpret_cast(s); PyObject *nobj = symbol_slice(s); if(nobj) { PyObject *it = PyObject_GetIter(nobj); Py_DECREF(nobj); return it; } else return NULL; } PyTypeObject pySymbol_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "Symbol", /*tp_name*/ sizeof(pySymbol), /*tp_basicsize*/ 0, /*tp_itemsize*/ 0, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ symbol_repr, /*tp_repr*/ 0, /*tp_as_number*/ &symbol_as_seq, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ symbol_hash, /*tp_hash */ 0, /*tp_call*/ symbol_str, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT /*| Py_TPFLAGS_BASETYPE*/, /*tp_flags*/ "Symbol objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ symbol_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ symbol_iter, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ symbol_init, /* tp_init */ 0, /* tp_alloc */ symbol_new, /* tp_new */ }; pySymbol *pySymbol__; pySymbol *pySymbol_bang; pySymbol *pySymbol_list; pySymbol *pySymbol_symbol; pySymbol *pySymbol_float; pySymbol *pySymbol_int; void initsymbol() { if(PyType_Ready(&pySymbol_Type) < 0) return; Py_INCREF(&pySymbol_Type); // initialize predefined objects pySymbol__ = symbol_newsym(flext::sym__); pySymbol_bang = symbol_newsym(flext::sym_bang); pySymbol_list = symbol_newsym(flext::sym_list); pySymbol_symbol = symbol_newsym(flext::sym_symbol); pySymbol_float = symbol_newsym(flext::sym_float); pySymbol_int = symbol_newsym(flext::sym_int); } PyObject *pySymbol_FromSymbol(const t_symbol *sym) { pySymbol *op; if(sym == flext::sym__) Py_INCREF(op = pySymbol__); else if(sym == flext::sym_bang) Py_INCREF(op = pySymbol_bang); else if(sym == flext::sym_list) Py_INCREF(op = pySymbol_list); else if(sym == flext::sym_symbol) Py_INCREF(op = pySymbol_symbol); else if(sym == flext::sym_float) Py_INCREF(op = pySymbol_float); else if(sym == flext::sym_int) Py_INCREF(op = pySymbol_int); else op = symbol_newsym(sym); return (PyObject *)op; } py/source/pyatom.cpp0000644000175000017500000000230213104443402015245 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and Max/MSP Copyright (c)2002-2015 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 "pyatom.h" #include #define INTV 0.01 typedef std::map ObjMap; static ObjMap objmap; static size_t collix = 0,curix = 0; static double last = 0; size_t PyAtom::Register(PyObject *obj) { Collect(); Py_INCREF(obj); objmap[++curix] = obj; #ifdef _DEBUG // post("REG %p (%i)\n",obj,objmap.size()); #endif return curix; } PyObject *PyAtom::Retrieve(size_t id) { ObjMap::iterator it = objmap.find(id); PyObject *ret = it == objmap.end()?NULL:it->second; Collect(); return ret; } void PyAtom::Collect() { for(;;) { ObjMap::iterator it = objmap.begin(); if(it == objmap.end() || it->first > collix) break; PyObject *obj = it->second; Py_DECREF(obj); objmap.erase(it); #ifdef _DEBUG // post("DEL %p\n",obj); #endif } // schedule next collect time double tm = flext::GetTime(); if(tm > last+INTV) last = tm,collix = curix; } py/source/pybase.cpp0000644000175000017500000006010713104443402015226 0ustar zmoelnigzmoelnig/* py/pyext - python external object for PD and MaxMSP Copyright (c)2002-2015 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 "pybase.h" #include #if FLEXT_OS == FLEXT_OS_WIN #include #elif FLEXT_OS == FLEXT_OS_MAC #include #endif static PyMethodDef StdOut_Methods[] = { { "write", pybase::StdOut_Write, 1 }, { NULL, NULL, } }; static PyObject *gcollect = NULL; #ifdef FLEXT_THREADS class ThrCmp { public: inline bool operator()(const flext::thrid_t &a,const flext::thrid_t &b) const { if(sizeof(a) == sizeof(size_t)) return *(size_t *)&a < *(size_t *)&b; else return memcmp(&a,&b,sizeof(a)) < 0; } }; int pybase::lockcount = 0; #ifndef PY_USE_GIL static PyInterpreterState *pymain = NULL; typedef std::map PyThrMap; static PyThrMap pythrmap; ThrState pybase::pythrsys = NULL; ThrState pybase::FindThreadState() { flext::thrid_t id = flext::GetThreadId(); PyThrMap::iterator it = pythrmap.find(id); if(it == pythrmap.end()) { // Make new thread state ThrState st = PyThreadState_New(pymain); pythrmap[id] = st; return st; } else return it->second; } void pybase::FreeThreadState() { flext::thrid_t id = flext::GetThreadId(); PyThrMap::iterator it = pythrmap.find(id); if(it != pythrmap.end()) { // clear out any cruft from thread state object PyThreadState_Clear(it->second); // delete my thread state object PyThreadState_Delete(it->second); // delete from map pythrmap.erase(it); } } #endif // PY_USE_GIL PyFifo pybase::qufifo; flext::ThrCond pybase::qucond; #endif PyObject *pybase::module_obj = NULL; PyObject *pybase::module_dict = NULL; PyObject *pybase::builtins_obj = NULL; PyObject *pybase::builtins_dict = NULL; const t_symbol *pybase::sym_fint = NULL; const t_symbol *pybase::sym_response = NULL; // ----------------------------------------------------------------------------------------------------------- void initsymbol(); void initsamplebuffer(); void initbundle(); void pybase::lib_setup() { post(""); post("------------------------------------------------"); post("py/pyext %s - python script objects",PY__VERSION); post("(C)2002-2015 Thomas Grill - http://grrrr.org/ext"); post(""); post("using Python %s",Py_GetVersion()); #ifdef FLEXT_DEBUG post(""); post("DEBUG version compiled on %s %s",__DATE__,__TIME__); #endif // ------------------------------------------------------------- sym_response = flext::MakeSymbol("response"); #if FLEXT_SYS == FLEXT_SYS_PD sym_fint = sym_float; #else sym_fint = sym_int; #endif // ------------------------------------------------------------- Py_Initialize(); #ifdef FLEXT_DEBUG // Py_DebugFlag = 1; // Py_VerboseFlag = 1; #else Py_OptimizeFlag = 1; #endif #ifdef FLEXT_THREADS // enable thread support and acquire the global thread lock PyEval_InitThreads(); #ifndef PY_USE_GIL // get thread state pythrsys = PyThreadState_Get(); // get main interpreter state pymain = pythrsys->interp; // add thread state of main thread to map pythrmap[GetThreadId()] = pythrsys; #endif // PY_USE_GIL #endif // sys.argv must be set to empty tuple const char *nothing = ""; PySys_SetArgv(0,const_cast(¬hing)); // register/initialize pyext module only once! module_obj = Py_InitModule(const_cast(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(const_cast("stdout"), StdOut_Methods); PySys_SetObject(const_cast("stdout"), py_out); py_out = Py_InitModule(const_cast("stderr"), StdOut_Methods); PySys_SetObject(const_cast("stderr"), py_out); // get garbage collector function PyObject *gcobj = PyImport_ImportModule("gc"); if(gcobj) { gcollect = PyObject_GetAttrString(gcobj,"collect"); Py_DECREF(gcobj); } builtins_obj = PyImport_ImportModule("__builtin__"); builtins_dict = PyModule_GetDict(builtins_obj); // borrowed reference // add symbol type initsymbol(); PyModule_AddObject(module_obj,"Symbol",(PyObject *)&pySymbol_Type); // pre-defined symbols PyModule_AddObject(module_obj,"_s_",(PyObject *)pySymbol__); PyModule_AddObject(module_obj,"_s_bang",(PyObject *)pySymbol_bang); PyModule_AddObject(module_obj,"_s_list",(PyObject *)pySymbol_list); PyModule_AddObject(module_obj,"_s_symbol",(PyObject *)pySymbol_symbol); PyModule_AddObject(module_obj,"_s_float",(PyObject *)pySymbol_float); PyModule_AddObject(module_obj,"_s_int",(PyObject *)pySymbol_int); // add samplebuffer type initsamplebuffer(); PyModule_AddObject(module_obj,"Buffer",(PyObject *)&pySamplebuffer_Type); // add message bundle type initbundle(); PyModule_AddObject(module_obj,"Bundle",(PyObject *)&pyBundle_Type); // ------------------------------------------------------------- #if FLEXT_SYS == FLEXT_SYS_PD && defined(PD_DEVEL_VERSION) && defined(PY_USE_INOFFICIAL) // add PD paths char *dir; for(int i = 0; (dir = namelist_get(sys_searchpath,i)) != NULL; ++i) { AddToPath(dir); } #endif // ------------------------------------------------------------- FLEXT_SETUP(pyobj); FLEXT_SETUP(pymeth); FLEXT_SETUP(pyext); #ifndef PY_NODSP FLEXT_DSP_SETUP(pydsp); #endif #ifdef FLEXT_THREADS // release global lock PyEval_ReleaseLock(); // launch thread worker LaunchThread(quworker,NULL); // launch python worker LaunchThread(pyworker,NULL); #endif post("------------------------------------------------"); post(""); } FLEXT_LIB_SETUP(py,pybase::lib_setup) // ----------------------------------------------------------------------------------------------------------- pybase::pybase() : module(NULL) , dict(NULL) #ifdef FLEXT_THREADS , thrcount(0) , shouldexit(false),stoptick(0) #endif , detach(0) , pymsg(false) { ThrLock lock; Py_INCREF(module_obj); } pybase::~pybase() { ThrLock lock; Py_XDECREF(module_obj); } void pybase::Exit() { #ifdef FLEXT_THREADS erasethreads(); 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(PY_STOP_TICK*0.001f); if(thrcount) { // Wait forever post("py/pyext - Waiting for thread termination!"); while(thrcount) Sleep(PY_STOP_TICK*0.001f); post("py/pyext - Okay, all threads have terminated"); } } #endif } void pybase::GetDir(PyObject *obj,AtomList &lst) { if(obj) { ThrLock lock; PyObject *pvar = PyObject_Dir(obj); if(!pvar) PyErr_Print(); // no method found else { const t_symbol *sym = GetPyArgs(lst,pvar); if(!sym) post("py/pyext - Argument list could not be created"); else FLEXT_ASSERT(sym == sym_list); Py_DECREF(pvar); } } } void pybase::m__dir(PyObject *obj) { AtomList lst; GetDir(obj,lst); // dump dir to attribute outlet DumpOut(NULL,lst.Count(),lst.Atoms()); } void pybase::m__doc(PyObject *obj) { if(obj) { ThrLock lock; PyObject *docf = PyDict_GetItemString(obj,"__doc__"); // borrowed!!! if(docf && PyString_Check(docf)) { post(""); const char *s = PyString_AS_STRING(docf); // FIX: Python doc strings can easily be larger than 1k characters // -> split into separate lines for(;;) { char *nl = strchr((char *)s,'\n'); // the cast is for Borland C++ if(!nl) { // no more newline found post(s); break; } else { char buf[1024]; // copy string before newline to temp buffer and post unsigned int l = nl-s; if(l >= sizeof(buf)) l = sizeof buf-1; strncpy(buf,s,l); // copy all but newline buf[l] = 0; post(buf); s = nl+1; // set after newline } } } } } void pybase::OpenEditor() { if(!module) return; const char *mname = PyModule_GetFilename(module); if(!mname) { PyErr_Clear(); return; } char fname[1024]; strcpy(fname,mname); // replacing .pyc or .pyo for source file name char *dt = strrchr(fname,'.'); if(dt && !strncmp(dt,".py",2)) strcpy(dt,".py"); // this should open the editor.... #if FLEXT_OS == FLEXT_OS_WIN int err = (int)ShellExecute(NULL,"edit",fname,NULL,NULL,SW_SHOW); if(err == SE_ERR_NOASSOC) { // no association found - try notepad err = (int)ShellExecute(NULL,NULL,"notepad.exe",fname,NULL,SW_SHOW); } else if(err == ERROR_FILE_NOT_FOUND || err == SE_ERR_FNF) post("py/pyext - File not %s found",fname); else if(err <= 32) post("py/pyext - Unknown error opening %s",fname); #elif FLEXT_OS == FLEXT_OS_MAC FSRef ref; OSStatus err = FSPathMakeRef((unsigned char *)fname,&ref,NULL); if(err) post("py/pyext - Error interpreting path %s",fname); else { FSRef editor; err = LSGetApplicationForItem(&ref,kLSRolesEditor,&editor,NULL); if(err) { // Can't find associated application... try Textedit err = FSPathMakeRef((unsigned char *)"/Applications/TextEdit.app",&editor,NULL); if(err) post("py/pyext - Can't find Textedit application"); } if(!err) { LSLaunchFSRefSpec lspec; lspec.appRef = &editor; lspec.numDocs = 1; lspec.itemRefs = &ref; lspec.passThruParams = NULL; lspec.launchFlags = kLSLaunchDefaults; lspec.asyncRefCon = NULL; err = LSOpenFromRefSpec(&lspec,NULL); if(err) post("py/pyext - Couldn't launch editor"); } } #else // thanks to Tim Blechmann char *editor = getenv("EDITOR"); if(!editor) { // || !strcmp(editor, "/usr/bin/nano") || !strcmp(editor, "/usr/bin/pico") || !strcmp(editor, "/usr/bin/vi")) { // no environment variable or console text editor found ... use idle instead (should have come with Python) editor = "idle"; } pid_t child = fork(); if(!child) { char cmd[80]; strcpy(cmd,editor); strcat(cmd," "); strcat(cmd,fname); execl("/bin/sh", "sh", "-c", cmd, (char *) NULL); } #endif } void pybase::SetArgs() { // script arguments int argc = args.Count(); const t_atom *argv = args.Atoms(); char **sargv = new char *[argc+1]; for(int i = 0; i <= argc; ++i) { sargv[i] = new char[256]; if(!i) strcpy(sargv[i],"py/pyext"); else GetAString(argv[i-1],sargv[i],255); } // the arguments to the module are only recognized once! (at first use in a patcher) PySys_SetArgv(argc+1,sargv); for(int j = 0; j <= argc; ++j) delete[] sargv[j]; delete[] sargv; } #if FLEXT_SYS == FLEXT_SYS_PD static void fileclose(int fd) { #if PD_MAJOR_VERSION > 0 || PD_MINOR_VERSION >= 43 sys_close(fd); #elif FLEXT_OS == FLEXT_OS_WIN #error Pd version < 0.43 not supported for Windows #else close(fd); #endif } #endif static bool getmodulesub(const char *mod,char *dir,int len,const char *ext) { #if FLEXT_SYS == FLEXT_SYS_PD char *name; int fd = open_via_path("",mod,ext,dir,&name,len,0); if(fd >= 0) { fileclose(fd); FLEXT_ASSERT(name && *name); } else { // look for mod/__init__.py std::string tmp(mod); int l = tmp.size(); tmp += "/__init__"; fd = open_via_path("",tmp.c_str(),ext,dir,&name,len,0); if(fd >= 0) { fileclose(fd); FLEXT_ASSERT(name && *name); // we must remove the module name from dir char *t = dir+strlen(dir)-l; FLEXT_ASSERT(!strcmp(mod,t) && t[-1] == '/'); t[-1] = 0; } else name = NULL; } // if dir is current working directory... name points to dir if(dir == name) strcpy(dir,"."); return name != NULL; #elif FLEXT_SYS == FLEXT_SYS_MAX short path; long type; char smod[1024]; strcpy(smod,mod); strcat(smod,ext); bool ok = !locatefile_extended(smod,&path,&type,&type,0); if(ok) // convert pathname to unix style path_topathname(path,NULL,smod); else { // do path/file.ext combinations work at all under Max? strcpy(smod,mod); short path; type = 'fold'; ok = !locatefile_extended(smod,&path,&type,&type,1); if(ok) { // convert pathname to unix style (including trailing slash) path_topathname(path,NULL,smod); char *end = smod+strlen(smod); strcpy(end,mod); strcat(end,"/__init__"); strcat(end,ext); // check if file is really existing: try to open it FILE *f = fopen(smod,"r"); if(f) { *end = 0; // clear module part ... we only need base path fclose(f); } else ok = false; } } if(ok) { // convert path into slash style needed for Python #if 0 // Max API function uses Volume:/Path notation path_nameconform(smod,dir,PATH_STYLE_SLASH,PATH_TYPE_ABSOLUTE); #else #if FLEXT_OS == FLEXT_OS_WIN char *colon = NULL; #else char *colon = strchr(smod,':'); #endif if(colon) { *colon = 0; strcpy(dir,"/Volumes/"); strcat(dir,smod); strcat(dir,colon+1); } else strcpy(dir,smod); #endif return true; } else // not found return false; #else #pragma message("Not implemented"); return false; #endif } static bool getmodulepath(const char *mod,char *dir,int len) { return getmodulesub(mod,dir,len,".py") || getmodulesub(mod,dir,len,".pyc") || getmodulesub(mod,dir,len,".pyo"); } bool pybase::ImportModule(const char *name) { if(name) { if(modname == name) { // module with the same name is already loaded if(module) return true; } else modname = name; } else modname.clear(); UnimportModule(); return ReloadModule(); } void pybase::UnimportModule() { if(module) { FLEXT_ASSERT(dict && module_obj && module_dict); Py_DECREF(module); // reference count to module is not 0 here, altough probably the last instance was unloaded // Python retains one reference to the module all the time // we don't care module = NULL; dict = NULL; } } bool pybase::ReloadModule() { SetArgs(); PyObject *newmod; if(modname.length()) { if(module) newmod = PyImport_ReloadModule(module); else { // search in module path (TODO: check before if module is already present to avoid costly searching) char dir[1024]; if(getmodulepath(modname.c_str(),dir,sizeof(dir))) AddToPath(dir); // else // PyErr_SetString(PyExc_ImportError,"Module not found in path"); #if 1 // strip off eventual subpath from module name // it should already have been considered in the above AddToPath call size_t p = modname.rfind('/'); const char *m; if(p == std::string::npos) m = modname.c_str(); else { // reuse dir buffer... strcpy(dir,modname.c_str()+p+1); m = dir; } // module could also be loaded ok, even if it's not in the path (e.g. for internal stuff) newmod = PyImport_ImportModule((char *)m); #else newmod = PyImport_ImportModule((char *)modname.c_str()); #endif } } else { // if no module name given, take py module newmod = module_obj; Py_INCREF(newmod); } if(!newmod) { // unload faulty module UnimportModule(); return false; } else { Py_XDECREF(module); module = newmod; dict = PyModule_GetDict(module); // borrowed return true; } } void pybase::AddToPath(const char *dir) { if(dir && *dir) { PyObject *pobj = PySys_GetObject(const_cast("path")); if(pobj && PyList_Check(pobj)) { PyObject *ps = PyString_FromString(dir); if(!PySequence_Contains(pobj,ps)) PyList_Append(pobj,ps); // makes new reference Py_DECREF(ps); } PySys_SetObject(const_cast("path"),pobj); // steals reference to pobj } } void pybase::AddCurrentPath(flext_base *o) { char dir[1024]; // add dir of current patch to path o->GetCanvasDir(dir,sizeof(dir)); if(*dir) AddToPath(dir); // add current dir to path #if FLEXT_SYS == FLEXT_SYS_PD AddToPath(GetString(canvas_getcurrentdir())); #elif FLEXT_SYS == FLEXT_SYS_MAX short path = path_getdefault(); path_topathname(path,NULL,dir); AddToPath(dir); #endif } bool pybase::OutObject(flext_base *ext,int o,PyObject *obj) { flext::AtomListStatic<16> lst; const t_symbol *sym = pymsg?GetPyAtom(lst,obj):GetPyArgs(lst,obj); if(sym) { // call to outlet _outside_ the Mutex lock! // otherwise (if not detached) deadlock will occur ext->ToOutAnything(o,sym,lst.Count(),lst.Atoms()); return true; } else return false; } void pybase::Reload() { ThrLock lock; PyObject *reg = GetRegistry(REGNAME); if(reg) { PyObject *key; Py_ssize_t pos = 0; while(PyDict_Next(reg,&pos,&key,NULL)) { pybase *th = (pybase *)PyLong_AsLong(key); FLEXT_ASSERT(th); th->Unload(); } UnloadModule(); } bool ok = ReloadModule(); if(ok) { LoadModule(); if(reg) { SetRegistry(REGNAME,reg); PyObject *key; Py_ssize_t pos = 0; while(PyDict_Next(reg,&pos,&key,NULL)) { pybase *th = (pybase *)PyLong_AsLong(key); FLEXT_ASSERT(th); th->Load(); } } else Load(); } Report(); } static PyObject *output = NULL; // post to the console PyObject* pybase::StdOut_Write(PyObject* self, PyObject* args) { // should always be a tuple FLEXT_ASSERT(PyTuple_Check(args)); const int sz = PyTuple_GET_SIZE(args); for(int i = 0; i < sz; ++i) { PyObject *val = PyTuple_GET_ITEM(args,i); // borrowed reference PyObject *str = PyObject_Str(val); // new reference char *cstr = PyString_AS_STRING(str); char *lf = strchr(cstr,'\n'); // line feed in string if(!lf) { // no -> just append if(output) PyString_ConcatAndDel(&output,str); // str is decrefd else output = str; // take str reference } else { // yes -> append up to line feed, reset output buffer to string remainder PyObject *part = PyString_FromStringAndSize(cstr,lf-cstr); // new reference if(output) PyString_ConcatAndDel(&output,part); // str is decrefd else output = part; // take str reference // output concatenated string post(PyString_AS_STRING(output)); Py_DECREF(output); output = PyString_FromString(lf+1); // new reference } } Py_INCREF(Py_None); 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 pybase::gencall(PyObject *pmeth,PyObject *pargs) { bool ret = false; // Now call method switch(detach) { case 0: ret = docall(pmeth,pargs); Py_DECREF(pargs); Py_DECREF(pmeth); break; #ifdef FLEXT_THREADS case 1: // put call into queue ret = qucall(pmeth,pargs); break; case 2: // each call a new thread if(!shouldexit) { thr_params *p = new thr_params; p->cl = (flext_base *)this; p->var->_ext = new work_data(pmeth,pargs); ret = LaunchThread(thrworker,p); if(!ret) post("py/pyext - Failed to launch thread!"); } break; #endif default: post("py/pyext - Unknown detach mode"); } return ret; } void pybase::exchandle() { #if 0 // want to use that, but exception keeps a reference to the object // might be a Python bug! PyErr_Print(); #else // must use that instead... clear the exception PyObject *type,*value,*traceback; PyErr_Fetch(&type,&value,&traceback); PyErr_NormalizeException(&type,&value,&traceback); PyErr_Display(type,value,traceback); Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(traceback); #endif } #ifdef FLEXT_THREADS void pybase::thrworker(thr_params *p) { FLEXT_ASSERT(p); pybase *th = (pybase *)p->cl; work_data *w = (work_data *)p->var->_ext; ++th->thrcount; // \todo this should be atomic { ThrLock lock; // call worker th->docall(w->fun,w->args); delete w; } --th->thrcount; // \todo this should be atomic } /*! This thread function basically keeps alive the Python interpreter in the background It's good for threads that have been started from scripted functions */ void pybase::pyworker(thr_params *) { ThrLock lock; PyObject *timemod = PyImport_ImportModule("time"); PyObject *sleep = PyObject_GetAttrString(timemod,"sleep"); PyObject *args = PyTuple_New(1); PyTuple_SET_ITEM(args,0,PyFloat_FromDouble(1)); for(;;) { PyObject *res = PyObject_CallObject(sleep,args); Py_DECREF(res); } } void pybase::quworker(thr_params *) { FifoEl *el; ThrState my = FindThreadState(); for(;;) { while((el = qufifo.Get())) { ++el->th->thrcount; // \todo this should be atomic { ThrLock lock(my); el->th->docall(el->fun,el->args); Py_XDECREF(el->fun); Py_XDECREF(el->args); } --el->th->thrcount; // \todo this should be atomic qufifo.Free(el); } qucond.Wait(); } // we never end if(false) { ThrLock lock(my); // unref remaining Python objects while((el = qufifo.Get())) { Py_XDECREF(el->fun); Py_XDECREF(el->args); qufifo.Free(el); } } } void pybase::erasethreads() { PyFifo tmp; FifoEl *el; while((el = qufifo.Get())) { if(el->th == this) { Py_XDECREF(el->fun); Py_XDECREF(el->args); qufifo.Free(el); } else tmp.Put(el); } // Push back while((el = tmp.Get())) qufifo.Put(el); } #endif bool pybase::collect() { if(gcollect) { PyObject *ret = PyObject_CallObject(gcollect,NULL); if(ret) { #ifdef FLEXT_DEBUG int refs = PyInt_AsLong(ret); if(refs) post("py/pyext - Garbage collector reports %i unreachable objects",refs); #endif Py_DECREF(ret); return false; } } return true; } py/source/pybase.h0000644000175000017500000001604713104443402014677 0ustar zmoelnigzmoelnig/* py/pyext - python script object for PD and MaxMSP Copyright (c)2002-2015 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. */ #ifndef __PYBASE_H #define __PYBASE_H #include "main.h" #include "pysymbol.h" #include "pybuffer.h" #include "pybundle.h" #ifdef FLEXT_THREADS # ifdef PY_USE_GIL typedef PyGILState_STATE ThrState; # else typedef PyThreadState *ThrState; # endif #else typedef int ThrState; // dummy #endif class pybase : public flext { public: pybase(); virtual ~pybase(); void Exit(); static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1); static PyObject *MakePyArg(const t_symbol *s,int argc,const t_atom *argv); static const t_symbol *GetPyArgs(AtomList &lst,PyObject *pValue,int offs = 0); static const t_symbol *GetPyAtom(AtomList &lst,PyObject *pValue); static void lib_setup(); protected: virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv) = 0; 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); } std::string modname; // module name PyObject *module,*dict; // object module and associated dictionary static const char *py_doc; void GetDir(PyObject *obj,AtomList &lst); AtomList args; void AddCurrentPath(flext_base *o); void SetArgs(); bool OutObject(flext_base *ext,int o,PyObject *obj); // reload module and all connected objects void Reload(); bool ImportModule(const char *name); void UnimportModule(); bool ReloadModule(); // Get module registry PyObject *GetRegistry(const char *regname); // Set module registry void SetRegistry(const char *regname,PyObject *reg); // Register object void Register(PyObject *reg); // Unregister object void Unregister(PyObject *reg); virtual void LoadModule() = 0; virtual void UnloadModule() = 0; virtual void Load() = 0; virtual void Unload() = 0; void OpenEditor(); void Respond(bool b) { if(respond) { t_atom a; SetBool(a,b); DumpOut(sym_response,1,&a); } } void Report() { while(PyErr_Occurred()) PyErr_Print(); } static bool IsAnything(const t_symbol *s) { return s && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; } static bool IsAtom(const t_symbol *s) { return s == sym_float || s == sym_int || s == sym_symbol || s == sym_pointer; } // enum retval { nothing,atom,sequ }; // --- module stuff ----- static PyObject *module_obj,*module_dict; static PyObject *builtins_obj,*builtins_dict; static PyMethodDef func_tbl[],attr_tbl[]; static PyObject *py__doc__(PyObject *,PyObject *args); static PyObject *py_send(PyObject *,PyObject *args); #ifdef FLEXT_THREADS static PyObject *py_priority(PyObject *,PyObject *args); #endif static PyObject *py_arraysupport(PyObject *,PyObject *args); static PyObject *py_samplerate(PyObject *,PyObject *args); static PyObject *py_blocksize(PyObject *,PyObject *args); static PyObject *py_searchpaths(PyObject *,PyObject *args); static PyObject *py_helppaths(PyObject *,PyObject *args); #if FLEXT_SYS == FLEXT_SYS_PD static PyObject *py_getvalue(PyObject *,PyObject *args); static PyObject *py_setvalue(PyObject *,PyObject *args); #endif static PyObject *py_list(PyObject *,PyObject *args); static PyObject *py_tuple(PyObject *,PyObject *args); // ----thread stuff ------------ virtual void m_stop(int argc,const t_atom *argv); bool respond; #ifdef FLEXT_THREADS int thrcount; bool shouldexit; int stoptick; Timer stoptmr; void tick(void *); #endif int detach; bool pymsg; bool gencall(PyObject *fun,PyObject *args); bool docall(PyObject *fun,PyObject *args) { callpy(fun,args); if(PyErr_Occurred()) { exchandle(); return false; } else return true; } virtual void callpy(PyObject *fun,PyObject *args) = 0; void exchandle(); static bool collect(); protected: #ifdef FLEXT_THREADS static void thrworker(thr_params *data); bool qucall(PyObject *fun,PyObject *args) { FifoEl *el = qufifo.New(); el->Set(this,fun,args); qufifo.Put(el); qucond.Signal(); return true; } static void quworker(thr_params *); static void pyworker(thr_params *); void erasethreads(); static PyFifo qufifo; static ThrCond qucond; #ifndef PY_USE_GIL static ThrState pythrsys; #endif #endif static const t_symbol *sym_fint; // float or int symbol, depending on native number message type static const t_symbol *sym_response; static const t_symbol *getone(t_atom &at,PyObject *arg); static const t_symbol *getlist(t_atom *lst,PyObject *seq,int cnt,int offs = 0); public: static void AddToPath(const char *dir); #ifdef FLEXT_THREADS // this is especially needed when one py/pyext object calls another one // we don't want the message to be queued, but otoh we have to avoid deadlock // (recursive calls can only happen in the system thread) static int lockcount; #ifdef PY_USE_GIL static inline ThrState FindThreadState() { return ThrState(); } static inline ThrState PyLock(ThrState = ThrState()) { return PyGILState_Ensure(); } static inline ThrState PyLockSys() { return PyLock(); } static inline void PyUnlock(ThrState st) { PyGILState_Release(st); } #else // PY_USE_GIL static ThrState FindThreadState(); static void FreeThreadState(); static ThrState PyLock(ThrState st = FindThreadState()) { if(st != pythrsys || !lockcount++) PyEval_AcquireLock(); return PyThreadState_Swap(st); } #if 1 static inline ThrState PyLockSys() { return PyLock(); } #else static ThrState PyLockSys() { if(!lockcount++) PyEval_AcquireLock(); return PyThreadState_Swap(pythrsys); } #endif static void PyUnlock(ThrState st) { ThrState old = PyThreadState_Swap(st); if(old != pythrsys || !--lockcount) PyEval_ReleaseLock(); } #endif // PY_USE_GIL #else // FLEXT_THREADS static inline ThrState PyLock(ThrState = NULL) { return NULL; } static inline ThrState PyLockSys() { return NULL; } static inline void PyUnlock(ThrState st) {} #endif class ThrLock { public: ThrLock(): state(PyLock()) {} ThrLock(const ThrState &st): state(PyLock(st)) {} ThrLock(const ThrLock &t): state(PyLock(t.state)) {} ~ThrLock() { PyUnlock(state); } ThrState state; }; class ThrLockSys { public: ThrLockSys(): state(PyLockSys()) {} ~ThrLockSys() { PyUnlock(state); } ThrState state; }; static PyObject* StdOut_Write(PyObject* Self, PyObject* Args); }; #endif py/readme.txt0000644000175000017500000002371713104443402013743 0ustar zmoelnigzmoelnigpy/pyext - python script objects for PD and Max/MSP Copyright ©2002-2012 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. Donations for further development of the package are highly appreciated. Visit https://www.paypal.com/xclick/business=gr%40grrrr.org&item_name=pyext&no_note=1&tax=0¤cy_code=EUR ---------------------------------------------------------------------------- You need to have Python installed on your system for the py/pyext external to work. For Windows pick an up-to-date package from http://www.python.org . For linux use the package manager. For OS X keep things as the are - it has Python installed by default. The py/pyext package should run with Python version >= 2.1. It has been tested with versions 2.2 to 2.7 The default build setting using PY_USE_GIL requires Python version >= 2.3. Check out the sample patches and scripts ---------------------------------------------------------------------------- INSTALLATION ============ PD version >= 0.38 - Add "py" to the Startup items ("binaries to load") and add the folder "scripts" to the pd search path. PD version < 0.38 - Load it as a library with e.g. "pd -lib py -path scripts" Under Windows, py/pyext needs at least PD 0.43 Max/MSP - Copy py-objectmappings.txt into the init folder and py.mxe (Windows) or py.mxo (OSX) into the externals folder. ---------------------------------------------------------------------------- DESCRIPTION =========== With the py object you can load python modules and execute the functions therein. With the pyext you can use python classes to represent full-featured pd/Max message objects. Multithreading (detached methods) is supported for both objects. You can send messages to named objects or receive (with pyext) with Python methods. Known bugs: - The TCL/TK help patch is not usable under OSX. - With standard PD 0.37, threaded py scripts will cause "Stack overflows" under some circumstances -> use PD 0.38 or the devel_0_37 cvs branch instead - It has been reported that pyext crashes on AMD64 with SSE enabled (for these CPUs, disable the respective compiler flags) ---------------------------------------------------------------------------- BUILDING from source ==================== You will need the flext C++ layer for PD and Max/MSP externals to compile this. See http://grrrr.org/ext/flext Download, install and compile the package. Afterwards you can proceed with building this external. pd/Max - Windows - Microsoft Visual C, Borland C++, MinGW: ---------------------------------------------------------- Start a command shell with your eventual build environment (e.g. run vcvars32.bat for Microsoft Visual Studio) then run ..\flext\build.bat (you would have to substitute ..\flext with the respective path to the flext package) pd/Max - OSX/Linux - GCC: ------------------------- From a shell run bash ../flext/build.sh (you would have to substitute ../flext with the respective path to the flext package) ---------------------------------------------------------------------------- Python array support for py/pyext@Max/MSP: In the Max/MSP SDK change the file 4.5 headers\c74support\max-includes\ext_types.h, line 45 from typedef unsigned long UInt32; typedef signed long SInt32; to typedef unsigned int UInt32; typedef signed int SInt32; to avoid a compile-time type definition clash. ---------------------------------------------------------------------------- Version history: 0.2.2: - FIX: pyext._send(receiversym) sent an empty list to receiversym, now it sends a bang message (equivalent to pyext._send(receiversym,"bang",()) ). Thanks to Yvan Volochine for spotting that. - FIX: A bug in Pd < 0.43 under Windows causes various errors on loading the modules. This is fixed, py/pyext for Windows now needs Pd 0.43 0.2.1: - FIX: some simplifications in py and pyext - ADD: Python objects can be sent/received through outlets/inlets - ADD: py can have multiple inlets for multiple function arguments (right inlets are non-triggering) - ADD: allow module.function syntax for py and pyext - FIX: pyext: cleanup float vs. int ... first decision is made by tag, afterwards a conversion is tried - ADD: pym: object-oriented object... Python methods for any object type - ADD: py: allow all callables (also object constructors and builtins) - ADD: py: enable Python built-in functions (like range, str etc.) - ADD: sequence protocol for symbol type - FIX: cleanup for outbound messages (e.g. symbol atoms instead of one-element general messages) - FIX: better exception handling (no longer leaves reference to function object) and cleared misleading error message - FIX: better definition of output values for atoms, lists and anythings - FIX: much better detached method handling (one thread for all object instances!) - ADD: open module file in editor on "edit" message (or shift-click (PD) or double click (Max)) - FIX: _inlets and _outlets default to 0 if not given - ADD: enable optimization of Python code in reease build - CHG: _isthreaded is now a data member instead of a method - FIX: more safety for calls where association python-pd has already been removed - ADD: __str__ method for pyext, to enable print self calls - ADD: enable symbol binding for all callables (not only functions and methods) - ADD: Buffer.resize(frames,keep=1,zero=1) method - ADD: py.Bundle class to support flext message bundles - ADD: enable usage of compiled-only modules (.py[co]) - ADD: enable usage of module packages (with module/__init__.py[co]) - ADD: make use of the PyGILState_*() functions - ADD: always run the Python interpreter in the background (to keep alive Python threads) - ADD: added PY_USE_INOFFICIAL to enable usage of s_stuff.h PD header, to have access to search and help paths - ADD: pyext: _init method is now called after __init__ (after inlets/outlets have been created) - FIX: buffer protocol adapted to Python 2.5 - FIX: subpath support for modules (tested for Pd) 0.2.0: - ADD: handling of Python threads - FIX: output of single atoms instead of 1-element lists - ADD: new detach mechanism (call queue) - ADD: support for Max/MSP @ OSX and Windows - DEL: eliminated meaningless inchannels and outchannels methods - ADD: enabled "int"-tags for pyext class functions - ADD: py: when no function is given on the command line, let it be selected by message tag - FIX: __init__ wasn't called on reload - FIX: bound instance methods weren't correctly decref'd - 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: buffer handling with optional numarray support (if present) - ADD: new objects for dsp processing: pyext~,pyx~,pyext.~,pyx.~ - FIX: correctly report Python errors while contructing the object 0.1.4: - ADD: better (and independent) handling of inlet and outlet count (as class variables or dynamically initialized in __init__) - FIX: many memory leaks associated to ***GetItem stuff (big thanks to sven!) - FIX: set "this" memory in object after reloading script - ADD: _getvalue,_setvalue to access PD values - FIX: don't shout when Python script returns PyNone - ADD: alias creation names pyext. and pyx. take the script name also for the class name 0.1.3: - FIX: class variables are now set atomic if parameter list has only 1 element - ADD: introduced shortcut "pyx" for pyext. - ADD: arguments to the pyext class are now exposed as attributes "args" - FIX: parameters to Python functions are treated as integers when they can be. - ADD: inlet and outlet count can be given for pyext, python _inlet and _outlet members are ignored then - FIX: crash if script or class names are non-strings - FIX: long multi-line doc strings are now printed correctly - FIX: message "doc+" for class/instance __doc__ now working - FIX: improved/debugged handling of reference counts - FIX: _pyext._send will now send anythings if feasible - CHANGE: no more finalization - it's really not necessary... - FIX: calling from unregistered threads (like flext helper thread) now works 0.1.2: - CHANGE: updates for flext 0.4.1 - method registering within class scope - FIX: bugs in bound.cpp (object_free calls) - FIX: bug with threaded methods along with flext bug fix. - ADD: map Python threads to system threads - ADD: shut down the Python interpreter appropriately - CHANGE: use flext timer and bind functionality - ADD: attribute functionality - ADD: dir and dir+ methods for Python dictionary listing - ADD: get and set methods for Python class attributes 0.1.1: - CHANGE: updates for flext 0.4.0 - FIX: crash when module couldn't be loaded - FIX: GetBound method (modmeth.cpp, line 138) doesn't exist in flext any more - FIX: deadlock occured when connecting two py/pyext boxes in non-detached mode - ADD: current path and path of the canvas is added to the python path - FIX: path is not added to python path if already included 0.1.0: - completely reworked all code - added class functionality for full-featured objects and renamed the merge to pyext - enabled threads and made everything thread-safe ... phew! - using flext 0.3.2 - pyext now gets full python path - python's argv[0] is now "py" or "pyext" - etc.etc. 0.0.2: - fixed bug when calling script with no function defined (thanks to Ben Saylor) - cleaner gcc makefile 0.0.1: - using flext 0.2.1 --------------------------------------------------------------------------- TODO list: bugs: - crashes with long Python printouts general: - Documentation and better example patches - better error reporting for runtime errors - we should pre-scan and cache class methods features: - enable multiple interpreters? ( -> not possible within one thread) - options to fully detach a script (included initialization and finalization) - stop individual threads - support named (keyword) arguments (like attributes for messages) tests: - compile-time check for python threading support