Beispiel #1
0
    def __init__(self, port=30321, gui=True, open="python-interface-help.pd", cmd=None, path=["patches"], extra=None):
        """
        port - what port to connect to Pd on.
        nogui - boolean: whether to start Pd with or without a gui. Defaults to nogui=True
        open - string: full path to a .pd file to open on startup.
        cmd - message to send to Pd on startup.
        path - an array of paths to add to Pd startup path.
        extra - a string containing extra command line arguments to pass to Pd.
        """
        self.connectCallback = None
        
        if sys.platform == "win32":
            pdexe = "pd\\bin\\pd.exe"
        elif sys.platform == "linux2":
            pdexe = "pd"
        elif sys.platform == "darwin":
            pdexe = "./Pd.app/Contents/Resources/bin/pd"
        else:
            raise PdException("Unknown Pd executable location on your platform ('%s')." % sys.platform)
        args = [pdexe]
        
        args.append("-stderr")
        
        if not gui:
            args.append("-nogui")
        
        for p in path:
            args.append("-path")
            args.append(p)
        
        if extra:
            args += extra.split(" ")
        
        if open:
            args.append("-open")
            args.append(open)

        args.append("-send")
        args.append("startup port " + str(port))
        
        if cmd:
            args.append(cmd)
        
        self.argLine = " ".join(args)

        try:
            self.pd = Popen(args, stdin=None, stderr=PIPE, stdout=PIPE, close_fds=(sys.platform != "win32"))
        except OSError:
            raise PdException("Problem running `%s` from '%s'" % (pdexe, getcwd()))
        
        
        self.port    = port
        self._map    = {}
        self._pdComs = PdComs(self, localaddr=("127.0.0.1", port), map=self._map)
Beispiel #2
0
    def __init__(self,
                 port=30321,
                 nogui=True,
                 open="python-interface-help.pd",
                 cmd=None,
                 path=["patches"],
                 extra=None,
                 stderr=True):
        """
		port - what port to connect to [netreceive] on.
		nogui - boolean: whether to start Pd with or without a gui. Defaults to nogui=True
		open - string: full path to a .pd file to open on startup.
		cmd - message to send to Pd on startup.
		path - an array of paths to add to Pd startup path.
		extra - a string containing extra command line arguments to pass to Pd.
		"""
        self.connectCallback = None

        if sys.platform == "win32":
            pdexe = "pd\\bin\\pd.exe"
        elif sys.platform == "linux2":
            pdexe = "pd"
        elif sys.platform == "darwin":
            pdexe = "./Pd.app/Contents/Resources/bin/pd"
        else:
            raise PdException(
                "Unknown Pd executable location on your platform ('%s')." %
                sys.platform)
        args = [pdexe]

        if stderr:
            args.append("-stderr")

        if nogui:
            args.append("-nogui")

        if open:
            args.append("-open")
            args.append(open)

        if cmd:
            args.append("-send")
            args.append(cmd)

        for p in path:
            args.append("-path")
            args.append(p)

        if extra:
            args += extra.split(" ")

        #print "COMMAND:", " ".join(args)
        try:
            self.pd = Popen(args,
                            stdin=None,
                            stderr=PIPE,
                            stdout=PIPE,
                            close_fds=(sys.platform != "win32"))
        except OSError:
            raise PdException("Problem running `%s` from '%s'" %
                              (pdexe, getcwd()))

        if port:
            self.port = port

        self._map = {}
        self._pdSend = PdSend(map=self._map)
        self._pdReceive = PdReceive(self, map=self._map)
Beispiel #3
0
class Pd:
    """
        Start Pure Data in a subprocess.
        
        >>> from time import time, sleep
        >>> from os import path, getcwd
        >>> 
        >>> start = time()
        >>> # launching pd
        >>> pd = Pd(nogui=False)
        >>> pd.Send(["test message", 1, 2, 3])
        >>> 
        >>> def Pd_hello(self, message):
        ...     print "Pd called Pd_hello(%s)" % message
        ...
        >>> pd.Pd_hello = Pd_hello
        >>> 
        >>> sentexit = False
        >>> # running a bunch of stuff for up to 20 seconds
        >>> while time() - start < 20 and pd.Alive():
        ...     if time() - start > 0.5 and not sentexit:
        ...         pd.Send(["exit"])
        ...         sentexit = True
        ...     pd.Update()
        ...
        ...
        Pd called Pd_hello(['this', 'is', 'my', 'message', 'to', 'python'])
        untrapped message: ['this', 'is', 'another', 'message']
        untrapped stderr output: "connecting to port 30322"
        untrapped stderr output: "python-connected: 0"
        untrapped stderr output: "python-connected: 1"
        untrapped stderr output: "from-python: test message 1 2 3"
        untrapped stderr output: "closing audio..."
        untrapped stderr output: "pd_gui: pd process exited"
        untrapped stderr output: "closing MIDI..."...
        Pd died!
        >>> pd.Exit()
    """
    errorCallbacks = {}
    def __init__(self, port=30321, gui=True, open="python-interface-help.pd", cmd=None, path=["patches"], extra=None):
        """
        port - what port to connect to Pd on.
        nogui - boolean: whether to start Pd with or without a gui. Defaults to nogui=True
        open - string: full path to a .pd file to open on startup.
        cmd - message to send to Pd on startup.
        path - an array of paths to add to Pd startup path.
        extra - a string containing extra command line arguments to pass to Pd.
        """
        self.connectCallback = None
        
        if sys.platform == "win32":
            pdexe = "pd\\bin\\pd.exe"
        elif sys.platform == "linux2":
            pdexe = "pd"
        elif sys.platform == "darwin":
            pdexe = "./Pd.app/Contents/Resources/bin/pd"
        else:
            raise PdException("Unknown Pd executable location on your platform ('%s')." % sys.platform)
        args = [pdexe]
        
        args.append("-stderr")
        
        if not gui:
            args.append("-nogui")
        
        for p in path:
            args.append("-path")
            args.append(p)
        
        if extra:
            args += extra.split(" ")
        
        if open:
            args.append("-open")
            args.append(open)

        args.append("-send")
        args.append("startup port " + str(port))
        
        if cmd:
            args.append(cmd)
        
        self.argLine = " ".join(args)

        try:
            self.pd = Popen(args, stdin=None, stderr=PIPE, stdout=PIPE, close_fds=(sys.platform != "win32"))
        except OSError:
            raise PdException("Problem running `%s` from '%s'" % (pdexe, getcwd()))
        
        
        self.port    = port
        self._map    = {}
        self._pdComs = PdComs(self, localaddr=("127.0.0.1", port), map=self._map)
    
    #Internaly called functions
    def Dead(self):
        self.pd = None
        self.PdDied()
    
    def CheckStart(self, msg):
        if "_Start() called" in msg:
            self.PdStarted()
    
    #User callable functions
    def Update(self):
        poll(map=self._map)
        stdin = self.pd.recv()
        stderr = self.pd.recv_err()
        if stdin:
            [self.CheckStart(t) for t in cr.split(stdin) if t]
        if stderr:
            [self.Error(t) for t in cr.split(stderr) if t]
    
    def Send(self, msg):
        """
        Send an array of data to Pd.
        It will arrive at the [python-interface] object as a space delimited list.
        
        p.Send(["my", "test", "yay"])
        """
        self._pdComs.Send(msg)
    
    def Alive(self):
        """
        Check whether the Pd subprocess is still alive.
        """
        return bool(self.pd and self.pd.poll() != 0)
    
    def Exit(self):
        """
        Kill the Pd process right now.
        """
        if self.Alive():
            #self.close()
            if sys.platform == "win32":
                # Kill the process using pywin32
                import win32api
                win32api.TerminateProcess(int(self.pd._handle), -1)
            else:
                # kill the process using os.kill
                from os import kill
                kill(self.pd.pid, signal.SIGINT)
        if self.pd:
            self.pd.wait()
    
    #Functions to override
    def PdMessage(self, data):
        """
        Override this method to receive messages from Pd.
        """
        print "untrapped message:", data
    
    def Error(self, error):
        """
        Override this to catch anything sent by Pd to stderr (e.g. [print] objects).
        """
        errors = error.split(" ")
        method = getattr(self, 'Error_' + errors[0], None)
        if method:
            method(errors)
        elif error in self.errorCallbacks:
            self.errorCallbacks[error]()
        else:
            print 'untrapped stderr output: "' + error + '"'
    
    def PdStarted(self):
        """
        Override this to catch the definitive start of Pd.
        """
        print "Pd started!"
    
    def PdDied(self):
        """
        Override this to catch the Pd subprocess exiting.
        """
        print "Pd died!"
        
    def ComError(self, data):
        """
        Override this to catch errors during communication with PD.
        """
        print "Pd died!"
Beispiel #4
0
class Pd:
    """
		Start Pure Data in a subprocess.
		
		>>> from time import time, sleep
		>>> from os import path, getcwd
		>>> 
		>>> start = time()
		>>> # launching pd
		>>> pd = Pd(nogui=False)
		>>> pd.Send(["test message", 1, 2, 3])
		>>> 
		>>> def Pd_hello(self, message):
		... 	print "Pd called Pd_hello(%s)" % message
		...
		>>> pd.Pd_hello = Pd_hello
		>>> 
		>>> sentexit = False
		>>> # running a bunch of stuff for up to 20 seconds
		>>> while time() - start < 20 and pd.Alive():
		... 	if time() - start > 0.5 and not sentexit:
		... 		pd.Send(["exit"])
		... 		sentexit = True
		... 	pd.Update()
		...
		...
		Pd called Pd_hello(['this', 'is', 'my', 'message', 'to', 'python'])
		untrapped message: ['this', 'is', 'another', 'message']
		untrapped stderr output: "connecting to port 30322"
		untrapped stderr output: "python-connected: 0"
		untrapped stderr output: "python-connected: 1"
		untrapped stderr output: "from-python: test message 1 2 3"
		untrapped stderr output: "closing audio..."
		untrapped stderr output: "pd_gui: pd process exited"
		untrapped stderr output: "closing MIDI..."...
		Pd died!
		>>> pd.Exit()
	"""
    errorCallbacks = {}

    def __init__(self,
                 port=30321,
                 nogui=True,
                 open="python-interface-help.pd",
                 cmd=None,
                 path=["patches"],
                 extra=None,
                 stderr=True):
        """
		port - what port to connect to [netreceive] on.
		nogui - boolean: whether to start Pd with or without a gui. Defaults to nogui=True
		open - string: full path to a .pd file to open on startup.
		cmd - message to send to Pd on startup.
		path - an array of paths to add to Pd startup path.
		extra - a string containing extra command line arguments to pass to Pd.
		"""
        self.connectCallback = None

        if sys.platform == "win32":
            pdexe = "pd\\bin\\pd.exe"
        elif sys.platform == "linux2":
            pdexe = "pd"
        elif sys.platform == "darwin":
            pdexe = "./Pd.app/Contents/Resources/bin/pd"
        else:
            raise PdException(
                "Unknown Pd executable location on your platform ('%s')." %
                sys.platform)
        args = [pdexe]

        if stderr:
            args.append("-stderr")

        if nogui:
            args.append("-nogui")

        if open:
            args.append("-open")
            args.append(open)

        if cmd:
            args.append("-send")
            args.append(cmd)

        for p in path:
            args.append("-path")
            args.append(p)

        if extra:
            args += extra.split(" ")

        #print "COMMAND:", " ".join(args)
        try:
            self.pd = Popen(args,
                            stdin=None,
                            stderr=PIPE,
                            stdout=PIPE,
                            close_fds=(sys.platform != "win32"))
        except OSError:
            raise PdException("Problem running `%s` from '%s'" %
                              (pdexe, getcwd()))

        if port:
            self.port = port

        self._map = {}
        self._pdSend = PdSend(map=self._map)
        self._pdReceive = PdReceive(self, map=self._map)

    def Update(self):
        poll(map=self._map)
        stdin = self.pd.recv()
        stderr = self.pd.recv_err()
        if stdin:
            [self.CheckStart(t) for t in cr.split(stdin) if t]
        if stderr:
            [self.Error(t) for t in cr.split(stderr) if t]

    def Send(self, msg):
        """
		Send an array of data to Pd.
		It will arrive at the [python-interface] object as a space delimited list.
		
		p.Send(["my", "test", "yay"])
		"""
        self._pdSend.Send(msg)

    def PdMessage(self, data):
        """
		Override this method to receive messages from Pd.
		"""
        print "untrapped message:", data

    def Connect(self, addr):
        self._pdSend.Connect((addr[0], self.port))

    def CheckStart(self, msg):
        if "_Start() called" in msg:
            self.PdStarted()

    def Error(self, error):
        """
		Override this to catch anything sent by Pd to stderr (e.g. [print] objects).
		"""
        errors = error.split(" ")
        method = getattr(self, 'Error_' + errors[0], None)
        if method:
            method(errors)
        elif error in self.errorCallbacks:
            self.errorCallbacks[error]()
        else:
            print 'untrapped stderr output: "' + error + '"'

    def Dead(self):
        self.pd = None
        self.PdDied()

    def PdStarted(self):
        """ Override this to catch the definitive start of Pd. """
        pass

    def PdDied(self):
        """
		Override this to catch the Pd subprocess exiting.
		"""
        print "Pd died!"

    def Alive(self):
        """
		Check whether the Pd subprocess is still alive.
		"""
        return bool(self.pd and self.pd.poll() != 0)

    def Exit(self):
        """
		Kill the Pd process right now.
		"""
        if self.Alive():
            #self.close()
            if sys.platform == "win32":
                # Kill the process using pywin32
                import win32api
                win32api.TerminateProcess(int(self.pd._handle), -1)
            else:
                # kill the process using os.kill
                from os import kill
                kill(self.pd.pid, signal.SIGINT)
        if self.pd:
            self.pd.wait()