OSCBasics
Client Server Basics
Using the build-in PF client-server system
When you want to send and receive data that is not suitable for Open Sound Control, you can work with PF's build in client-server system.
The PF protocol
This is not really a protocol in the sense of 'yet another protocol', but it is PF's native source file format. It works largely like lisp works: everything thats 'readable' is also 'writable'. The words to use are:
read-atom ( stream -- atom ) read an atom from a stream write-atom ( atom stream -- ) write an atom to a stream
Client Sockets
You can connect to a TCP server. To test this, use the following unix command to set up a testing server:
netcat -l -p 12345
To create an output connection stream, start pf and type:
(localhost 12345) "w" open-connect
Replacing "w" by "r" gives an input connection.
Server sockets
A server socket is basicly a device to create new connected streams whenever a client starts a connection. Start the connection like this:
("" 12345) "r" open-listen # create stream
constant SERVER # store it in a constant
SERVER "r" open-accept # create the connection
For more information about networking in PF, you can read the networking.txt in libpf's doc section.
An example using input-select
Every time you read (or open-accept) from a stream, and there is no input data (or input connection) present, PF will block until data is received. To avoid PF from blocking all other running processes, there is the word 'select-input'. This function takes a list of streams, and a timeout in milliseconds. So if there is no input, it simply times out, without blocking your other processes. input-select splits the input list into two lists: the top one has all the inactive streams, while the 2nd list has all the active streams. To see it in action, try running these 2 scripts (start the server first, then the client):
The server:
load-opengl
200 200 display
2d
animation
0. variable! flag
0 :: 1 + ; counter count
0. variable! STREAMS
("" 12345) "r" open-listen # create stream
constant SERVER # store stream in constant
SERVER "r" open-accept # start the connection
dup 1 pack STREAMS ! # put stream in a list
constant CONNECTION # and store it in a constant
: handle-stream
CONNECTION read-atom . ; # prints incoming data
: catch
STREAMS @ 0.0 select-input # 0 milliseconds timeout
drop ' handle-stream for-each ; # drop inactive streams and handle
# all active streams in list
: anim
catch # executes catch
1. rand square # pf executes other words
;
:: anim ; is drawer
The client:
load-opengl
200 200 display
2d
animation
0. variable! flag
0 :: 1 + ; counter count
(localhost 12345) "w" open-connect # start (writing) connection
constant network # store it in a constant
: send
flag @ 100 mod 0 = if # every 100 frames a random
10. rand network write-atom # number gets send
then ;
: anim
count flag ! # update counter
send # send gets executed
0.01 square ; # pf executes other words
:: anim ; is drawer
