I am a fairly experienced python user, but I have no experience with OSC protocol, MAX and SuperCollider.
I am helping a friend in building a python code that should do the following:
What it is not clear to me is what concerns the 1 and 3 points.
PART 0
I import the following libraries
from pythonosc import dispatcher
from pythonosc import osc_server
from pythonosc import udp_client
PART 1
I tried to setup a simple server for point 1, since I am only receiving one string at a time from MAX:
def listen2Max(ip,port):
'''
set up server
'''
# dispatcher to receive message
dispatcher = dispatcher.Dispatcher()
dispatcher.map("/filter", print)
# server to listen
server = osc_server.ThreadingOSCUDPServer((ip,port), dispatcher)
print("Serving on {}".format(server.server_address))
server.serve_forever()
but i do not know what to return
in this function, also I do not get the use of "/filter"
in the map
. Is it something that must be specified in MAX?
PART 2
This is actually my strong suit: I take the string message returned by my listen2Max function, do some py stuff and prepare a message called mymove
to be sent to SuperCollider
PART 3
For point 3 I set up a simple client to communicate the string var mymove
to SuperCollider
def talk2SC(ip,port,mymove):
'''
set up client
'''
client = udp_client.SimpleUDPClient(ip,port)
client.send_message("/filter", mymove)
Should it work like that?
This is the code that gets (at least part of) the job done.
Bear in mind that, in this case, Max sends strings to python. The messages I get are something like this: O-O e8g8 8 1
import argparse
from pythonosc import dispatcher
from pythonosc import osc_server
from pythonosc import udp_client
def main(path: str, *osc_arguments):
msg = osc_arguments[-1]
print("input message: {}".format(msg))
msgOUT = msg+'whatever'
# output
print("output message: {}".format(msgOUT))
ipOUT = osc_arguments[0][0]
portOUT = osc_arguments[0][1]
pathOUT= osc_arguments[0][2]
talk2SC(ipOUT,portOUT,pathOUT,msgOUT)
def listen2Max(addrIN,addrOUT):
'''
set up server
'''
# input address
ipIN = addrIN[0]
portIN = addrIN[1]
pathIN = addrIN[2]
# output address
portOUT = addrOUT[0]
pathOUT = addrOUT[1]
# dispatcher to receive message
disp = dispatcher.Dispatcher()
disp.map(pathIN, main, ipIN, portOUT, pathOUT)
# server to listen
server = osc_server.ThreadingOSCUDPServer((ipIN,portIN), disp)
print("Serving on {}".format(server.server_address))
server.serve_forever()
def talk2SC(ip,port,path,mymove):
'''
set up client
'''
client = udp_client.SimpleUDPClient(ip,port)
client.send_message(path, mymove)
if __name__ == "__main__":
# generate parser
parser = argparse.ArgumentParser(prog='scacchiOSC', formatter_class=argparse.RawDescriptionHelpFormatter, description='Interprete di messaggi OSC da Max\n')
parser.add_argument("-II","--ipIN", type=str, default="127.0.0.1", help="The ip to listen on")
parser.add_argument("-PI", "--portIN", type=int, default=5005, help="The port to listen on")
parser.add_argument("-UI", "--uripathIN", type=str, default="/filter", help="MAX's URI path")
parser.add_argument("-PO", "--portOUT", type=int, default=5006, help="The port to send messages to")
parser.add_argument("-UO", "--uripathOUT", type=str, default="/filter", help="output URI path")
args = parser.parse_args()
# wrap up inputs
outputAddress = [args.portOUT, args.uripathOUT]
inputAddress = [args.ipIN, args.portIN, args.uripathIN]
# listen to max
listen2Max(inputAddress, outputAddress)
This code gets messages from a client like this:
from pythonosc import dispatcher
from pythonosc import osc_server
from pythonosc import udp_client
from typing import List, Any
def talk2SC(ip,port,path):
'''
set up client
'''
# maxmsg = 'Nxe6 f4e6'
maxmsg = 'e4 e2e4'
client = udp_client.SimpleUDPClient(ip,port)
client.send_message(path, maxmsg)
if __name__ == '__main__':
talk2SC("127.0.0.1",5005,"/filter")
and sends messages to a server like this:
from pythonosc import dispatcher
from pythonosc import osc_server
from pythonosc import udp_client
from typing import List, Any
def main(address: str, *osc_arguments):
'''
prende il messaggio di MAX e lo traduce aggiornando la scacchiera
'''
# read message
msg = osc_arguments[0]
# initialize board
print(osc_arguments)
# outputc
def listen2Max(ip,port,path):
'''
set up server
'''
# dispatcher to receive message
disp = dispatcher.Dispatcher()
handler = disp.map(path, main)
# print(handler)
# server to listen
server = osc_server.ThreadingOSCUDPServer((ip,port), disp)
print("Serving on {}".format(server.server_address))
server.serve_forever()
if __name__ == '__main__':
listen2Max("127.0.0.1",5006,"/chmove")
The tricky part is to make it communicate with Max. Luckily enough I found an answer here:
/path "O-O e8g8 8 1"
/path
If one wants python to listen to each and every path, one could change the default path in the parser item and use "*"
as default. Then
parser.add_argument("-UI", "--uripathIN", type=str, default="*", help="MAX's URI path")
Now, I just have to fix the SuperCollider part.