How to listen for OSC asynchronously?

The documentation describes a basic OSC listener that blocks until there’s activity on the channel it’s syncing to. I’d like to have a dedicated OSC loop that updates any number of variables when a corresponding OSC message arrives and just keeps looping, updating whichever ones have arrived on each loop.

Something like this, for example:

live_loop :oscListener do
  flag1 = "/osc/flag1"
  flag2 = "/osc/flag2"
  flagn = "/osc/flagn"
  sleep 0.1

I would use the flags as conditions in other loops to do stuff or not do stuff. I’d then be able to control aspects of playback externally without modifying the buffer’s code. Will this work? I’m asking before experimenting so that I can be confident of what’s going on on the Sonic Pi side before messing with external things that have their own learning curve.

1 Like

You can do this using get which returns the last known value or nil if not yet detected
In the example below I test for 4 different osc messages.
the get commands retrieve the last message detected. If this is not nil then the value of the message is printed. I deliberately don’t send anything to the 4th osc address to show what happens.

The second test loop sends messages at different times to the first three osc addresses, and these are printed out when detected.

use_osc_logging false
use_osc "localhost",4560
live_loop :oscListener do
  flag1 = get "/osc*/flag1"
  flag2 = get "/osc*/flag2"
  flag3 = get "/osc*/flag3"
  flag4 = get "/osc*/flag4"  #nothing sent to this address (by me!) so always nil
  puts flag1[0] if !(flag1==nil)
  puts flag2[0] if !(flag2==nil)
  puts flag3[0] if !(flag3==nil)
  puts flag4[0] if !(flag4==nil)
  sleep 0.1

live_loop :randomValues do
  osc "/flag1",rrand(1,2)
  osc "/flag2",["one","two","three"].choose if one_in 3
  osc "/flag3",rrand_i(0,10) if one_in 2
  sleep rand(2)

I have turned off osc logging so that you can see more easily when the printed output changes.

You could also have multiple data items assocaited with one osc address


Thanks, your example will save me a lot of time. The documentation refers to get, but primarily talks about sync, so the correct way to do this was not obvious to me. Also, why put an asterisk after “osc” in the path?

For more info check out Section 10.3 of the tutorial. :slight_smile:

I understand that the asterisk is for matching patterns, but I can’t tell what patterns “osc*” is matching. Why doesn’t “osc” work without the asterisk?

if you look in teh cues log when an osc cue is received in this program you might get something like
The is the ip sourcing the osc and 4560 is the port. IF you send from external IP addresses you would have to match both of these for the get to match the cue. If you don’t care, it is easier to put a * to match any source addressed to /flag1