pyliblo
pyliblo copied to clipboard
can add_method take a regex to specify components from the OSC path ?
I'm used to url handling in stuff like django, where components can be passed as variables:
I'm constructing osc paths like this:
path = "/vis/smilies/{control_number}/amount".format(control_number=x)
is there a way to specify something like this in add_method, similar to how django urls work with regexes ?
django url soec https://docs.djangoproject.com/en/1.8/topics/http/urls/
I put together some toy code to do something similar in an ipython notebook -
import re
urlspecs = []
def add_regex_method(urlspec, f):
urlspecs.append((urlspec, f))
def dispatch_url(url):
matched = False
for spec, f in urlspecs:
matches = re.match(spec, url)
if matches is not None:
d = matches.groupdict()
f(url, **d)
matched = True
if not matched:
pass ## call handle for nonhandled urls
def handle_amount_url(url, n=None):
print("got amount url: %s n=%s" % (url, n))
add_regex_method("/smilies/(?P<n>.+)/amount", handle_amount_url)
dispatch_url("/smilies/10/amount")
dispatch_url("/notmatch") # nothing happens
output of above code:
got amount url: /smilies/10/amount n=10
For my own uses, I've extended server - like this - though would be nice to have similar functionality in the core
example server extended to handle regex matching osc paths
#!/usr/bin/env python
from __future__ import print_function
import re
import liblo, sys
class OSCServer(liblo.Server):
# extend OSCServer to have regex matching of osc paths
def __init__(self, *args, **kwargs):
liblo.Server.__init__(self, *args, **kwargs)
self.add_method(None, None, self.dispatch_msg)
self.pathspecs = []
def dispatch_msg(self, path, args, types, src):
"""
regex matching for osc messages
"""
matched = False
for spec, t, f in self.pathspecs:
matches = re.match(spec, path)
if matches is not None:
d = matches.groupdict()
f(path, *args, **d)
matched = True
if not matched:
print("not matched ", path)
pass ## call handle for nonhandled urls
def add_regex_method(self, spec, t, f):
self.pathspecs.append((spec, t, f))
# create server, listening on port 1234
try:
server = OSCServer(1234)
except liblo.ServerError as err:
print(err)
sys.exit()
def handle_amount(path, amount, n=0):
print("%s set amount %s" % (n, amount))
def handle_alpha(path, amount, n=0):
print("%s set alpha %s" % (n, amount))
def master_alpha(path, amount):
print("set master alpha %s" % amount)
server.add_regex_method("/vis/entities/(?P<n>.+)/amount", 'f', handle_amount)
server.add_regex_method("/vis/entities/(?P<n>.+)/alpha", 'f', handle_alpha)
server.add_regex_method("/vis/master/alpha", 'f', master_alpha)
# loop and dispatch messages every 100ms
while True:
server.recv(100)
The OSC spec actually has pattern matching that works the other way round, i.e. messages can contain wildcards, while the addresses registered with an OSC server don't. These wildcards are more glob-like, and I don't know if liblo fully implements the OSC spec, but pattern matching is supported.
The problem I see here is that you can't really match wildcards against wildcards, at least not in general (and in a sane way). Currently pyliblo leaves all the pattern matching and message dispatching to liblo, and the only way to add regex matching (without modifying liblo itself) would be through a "wildcard" callback like in your example.
I think this would be a useful addition to pyliblo (arguably more practical than the current pattern matching in liblo), but we should decide on clear semantics of which messages would be supported, and which matching mechanism takes precedence.
I'm also always a bit surprised, that pyliblo/liblo doesn't support more flexible dispatch. Some time ago I implemented an extended form of regular expresssion based dispatching here:
https://github.com/SpotlightKid/python-rtmidi/blob/master/examples/osc2midi/oscdispatcher.py
It works a bit similar to Django URL dispatching. You define a "pattern" patterns = [(regex, typecodes, handler, paramsdict)]
and add that to a dispatcher dispatcher = OSCDispatcher(patterns, search_ns=myhandlermodule)
. See the main
function of the module for an example. What's special about this module is that it allows you to convert part of the OSC address pattern into arguments of your handler function, optionally with a conversion function.
Hello, sorry I only saw this 5 years later, but I just came across it and have now added pattern matching in method names to liblo. https://github.com/radarsat1/liblo/commit/efea904078f1fde89c93d1d880c2d2180098c221
Looking back, I ended up writing a pattern matching dispatcher thingy and using it -
https://github.com/stuaxo/mnd It filtered arguments to functions with a syntax based on Djangos querys.
But if I play with OSC again this will be a good option.
Feel free to close this unless anyone else feels it should stay open.