OSC: multiple surfaces

I’m writing a program to act as two control surfaces at the same time. Ardour’s OSC support and documentation is excellent but I can’t figure out how to do this. It sounds like it’s possible…

Under “port”:

There can only be one port setting per host. If that setting is auto , than more than one controller can be run on that host, but if a manual port is set there can only be one. In the case of auto mode, the control surface must set it’s receive port to be the same as it’s send port. If that is not possible, then manual port mode must be used. This allows a smart controller to use a number of ports on the same ip while a smartphone set up as a personal monitor control can use the default manual port.

Following that I tried this:
Send two /set_surface commands, one on port 3820 and the other on 3821, using the port=0 argument in both, then set up my two listeners to listen on those same ports.

In Preferences > Control Surfaces > OSC > Debug, if I do a “Print surface info to Log window” then it shows no surfaces at all. And my listeners don’t receive anything, which makes sense given the previous sentence.

I think I’m missing an important part of the puzzle here. Any help?

I think this is where I’m going wrong, what “send port” means. I took it to mean the port I’m sending to, which is to Ardour and therefore will always be 3819. Hence my earlier attempts to send to 3820 or 3821 were incorrect.

So I’m now thinking that “send port” means the port that my program is sending from. Can anybody confirm that? If it’s true then I’m stuck because I can’t find any way to determine what port that is, much less set it somehow. Perhaps some hardware surfaces do let us set this sort of thing but the OSC library I’m using (oscpy) doesn’t.

UPDATE:
Success! Yep, “send port” is the port the surface (program in this case) is sending from.

For anybody else trying to do this using the Python oscpy library…

Use an OSCThreadServer object as both the sender and receiver (client and server). Whatever port it is instructed to receive on will also be used automatically to send on in its send_message() method, thus satisfying the required setup: “the control surface must set it’s receive port to be the same as it’s send port”.

FWIW the send-on port can also be specified in an OSCClient by first creating a socket, doing a bind() call on that socket with the required port, and passing that socket to the OSCClient constructor.

import socket

sendFromPort = 8007
sendToPort = 3819

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", sendFromPort))

self.client = OSCClient("localhost", sendToPort, sock)

The problem there is, as the receiver (server) needs to listen on that same port, I was getting an “address already in use” error when attempting to startup the server and the client.

Have a look at open stage control : http://openstagecontrol.ammd.net/