Package: oscpy
OSCPyCI is done by Github Checks, see the current commit for build status.A modern implementation of OSC for python2/3.What is OSC.OpenSoundControl is an UDP based network protocol, that is designed for fast
dispatching of time-sensitive messages, as the name suggests, it was designed
as a replacement for MIDI, but applies well to other situations. The protocol is
simple to use, OSC addresses look like http URLs, and accept various basic
types, such as string, float, int, etc. You can think of it basically as an
http POST, with less overhead.You can learn more about OSC onOpenSoundControl.orgGoalspython2.7/3.6+ compatibility (can be relaxed more on the python3 side
if needed, but nothing before 2.7 will be supported)fasteasy to userobust (returns meaningful errors in case of malformed messages,
always do the right thing on correct messages, and by default intercept+log
the exceptions raised by callbacks)separation of concerns (message parsing vs communication)sync and async compatibility (threads, asyncio, trio…)clean and easy to read codeFeaturesserialize and parse OSC data types/Messages/Bundlesa thread based udp server to open sockets (INET or UNIX) and bind callbacks on osc addresses on thema simple clientInstallpipinstalloscpyUsageServer (thread)fromoscpy.serverimportOSCThreadServerfromtimeimportsleepdefcallback(*values):print("got values:{}".format(values))osc=OSCThreadServer()# See sources for all the arguments# You can also use an \*nix socket path heresock=osc.listen(address='0.0.0.0',port=8000,default=True)osc.bind(b'/address',callback)sleep(1000)osc.stop()# Stop the default socketosc.stop_all()# Stop all sockets# Here the server is still alive, one might call osc.listen() againosc.terminate_server()# Request the handler thread to stop loopingosc.join_server()# Wait for the handler thread to finish pending tasks and exitor you can use the decorator API.Server (thread)fromoscpy.serverimportOSCThreadServerfromtimeimportsleeposc=OSCThreadServer()sock=osc.listen(address='0.0.0.0',port=8000,default=True)@osc.address(b'/address')defcallback(*values):print("got values:{}".format(values))sleep(1000)osc.stop()Servers are also client, in the sense they can send messages and answer to
messages from other serversfromoscpy.serverimportOSCThreadServerfromtimeimportsleeposc_1=OSCThreadServer()osc_1.listen(default=True)@osc_1.address(b'/ping')defping(*values):print("ping called")ifTrueinvalues:cont.append(True)else:osc_1.answer(b'/pong')osc_2=OSCThreadServer()osc_2.listen(default=True)@osc_2.address(b'/pong')defpong(*values):print("pong called")osc_2.answer(b'/ping',[True])osc_2.send_message(b'/ping',[],*osc_1.getaddress())timeout=time()+1whilenotcont:iftime()>timeout:raiseOSError('timeout while waiting for success message.')Server (async) (TODO!)fromoscpy.serverimportOSCThreadServerwithOSCAsyncServer(port=8000)asOSC:foraddress,valuesinOSC.listen():ifaddress==b'/example':print("got{}on /example".format(values))else:print("unknown address{}".format(address))Clientfromoscpy.clientimportOSCClientaddress="127.0.0.1"port=8000osc=OSCClient(address,port)foriinrange(10):osc.send_message(b'/ping',[i])UnicodeBy default, the server and client take bytes (encoded strings), not unicode
strings, for osc addresses as well as osc strings. However, you can pass anencodingparameter to have your strings automatically encoded and decoded by
them, so your callbacks will get unicode strings (unicode in python2, str in
python3).osc=OSCThreadServer(encoding='utf8')osc.listen(default=True)values=[]@osc.address(u'/encoded')defencoded(*val):forvinval:assertnotisinstance(v,bytes)values.append(val)send_message(u'/encoded',[u'hello world',u'ééééé ààààà'],*osc.getaddress(),encoding='utf8')(uliterals added here for clarity).CLIOSCPy provides an "oscli" util, to help with debugging:oscli dumpto listen for messages and dump themoscli sendto send messages or bundles to a serverSeeoscli -hfor more information.GOTCHASNonevalues are not allowed in serializationUnix-type sockets must not already exist when you listen() on themTODOreal support for timetag (currently only supports optionally
dropping late bundles, not delaying those with timetags in the future)support for additional argument typesan asyncio-oriented server implementationexamples & documentationContributingCheck out ourcontribution guideand feel free to improve OSCPy.LicenseOSCPy is released under the terms of the MIT License.
Please see theLICENSE.txtfile.