Commit 50a22a1d authored by Bruno Laurencich's avatar Bruno Laurencich

basic OSC receive

parent 8f1af6cd
......@@ -11,14 +11,13 @@ if "bpy" in locals():
imp.reload(panel)
imp.reload(remote_runner)
imp.reload(utils)
imp.reload(receive)
else:
from . import connection
from . import panel
from . import remote_runner
from . import utils
from . import receive
import bpy
......@@ -37,19 +36,20 @@ class Chord_Properties(bpy.types.PropertyGroup):
items=connection.possible_states(),\
options={'SKIP_SAVE'})
notochord_msg =props.StringProperty( default = "" )
notochord_msg = props.StringProperty( default = "" )
notochord_hostname =props.StringProperty( default = "notochord" )
notochord_hostname = props.StringProperty( default = "notochord" )
notochord_ip =props.StringProperty( default = "" )
notochord_parameters = props.StringProperty( default = "192.168.1.30 6565" )
last_check =props.IntProperty( default = 0 )
notochord_ip = props.StringProperty( default = "" )
last_check = props.IntProperty( default = 0 )
max_ip_discover_attempts = props.IntProperty( default = 3 )
# ====== End of GLOBAL PROPERTIES =======
def register():
# bpy.utils.register_class(Chord_Get_Ip)
bpy.utils.register_class(Chord_Properties)
......
No preview for this file type
import bpy
import threading
from pythonosc import dispatcher
from pythonosc import osc_server
import time, threading
from re import search as regex
from mathutils import *
from math import *
D = bpy.data
C = bpy.context
class Error(Exception):
def __init__(self, msg):
self.msg = msg
class Chordata:
def __init__(self):
self.object = None
bpy.ops.object.mode_set(mode="OBJECT")
self.message = " Chordata operator | Calibrating... Press AKEY to end "
for o in D.objects:
if o.type == "ARMATURE":
self.object = o
if self.object is None:
raise Error("There's no Armature in the scene.")
self.pose = self.object.pose.bones
self.bones = self.object.data.bones
self.temp = {}
print("Bones found in armature")
for b in self.bones:
if b.name == "no-capture-bone":
continue
b.use_inherit_rotation = False
D.objects[b.name].rotation_mode = "QUATERNION"
self.temp[b.name] = {}
self.temp[b.name]["chord_quat"] = Quaternion()
self.temp[b.name]["avg_quat"] = Quaternion()
self.temp[b.name]["diff_quat"] = False
self.temp[b.name]["local_q"] = b.matrix_local.to_quaternion()
print(" [{}]".format(b.name))
def set_key(self, context):
for b in self.object.pose.bones:
# print("Setting key to %s"% b.name)
self.object.keyframe_insert(\
'pose.bones["'+ b.name +'"].rotation_quaternion',
index=-1,
frame=context.scene.frame_current,
group=b.name)
def reset_pose(self):
for b in self.object.pose.bones:
b.rotation_quaternion.identity()
def put_quad_on_bones(self):
# for b in self.bones:
# self.pose[b.name].rotation_quaternion = b["chord_quat"]
# print(self.pose[b.name].rotation_quaternion)
#
for key, b in self.temp.items():
D.objects[key].rotation_quaternion = b['chord_quat']
if not b["diff_quat"]:
b["avg_quat"] = b['chord_quat'].slerp(b["avg_quat"], 0.5)
else:
#this set the bone to the same rotation than the cube in world space
q = b["local_q"].conjugated() * b['chord_quat'].copy() * b["local_q"]
self.object.pose.bones[key].rotation_quaternion = q * b["diff_quat"].conjugated()
def get_rot_diff(self):
for key, b in self.temp.items():
q0 = b["local_q"].conjugated() * b['avg_quat'].copy() * b["local_q"]
b["diff_quat"] = self.object.pose.bones[key].rotation_quaternion.rotation_difference(q0)
self.message = " Chordata operator | posing... (Press Q, W, E to switch layers)"
def start_server(self, IP = "", PORT = 6565):
"""
Start the OSC server on different thread and attach a handler to the OSC address "/quats"
"""
#create the dispatcher
self.dispatcher = dispatcher.Dispatcher()
#register a handler to get the recived values on the address /Chordata
self.dispatcher.map("/Chordata/.*", receive, self)
#Start evetything
self.server = osc_server.BlockingOSCUDPServer((IP, PORT), self.dispatcher)
self.st = threading.Thread( target = self.server.serve_forever,)
print("Serving on {}".format(self.server.server_address))
self.st.start()
def close_server(self):
print ("\nClosing OSCServer.")
self.server.shutdown()
print ("Waiting for Server-thread to finish")
self.st.join()
print ("Done")
def receive(addr, objs, *osc_vals):
sensor = regex("^/Chordata/(\w.*)", addr)
if not sensor or sensor.lastindex < 1:
print("Invalid address")
return
# print(osc_vals)
try:
for x in range(len(osc_vals)):
objs[0].temp[sensor.group(1)]["chord_quat"][x] = float(osc_vals[x])
except IndexError as e:
print("An OSC lecture came with too much values")
return
except Exception as e:
print("There was an error while reading 0SC data")
print(e)
return
# if __name__ == '__main__':
# c = Chordata()
# try:
# c.start_server()
# except KeyboardInterrupt as e:
# del c
\ No newline at end of file
......@@ -8,7 +8,7 @@ else:
from . import mdns
def possible_states(raw = True):
def possible_states():
"""Returns the 'items' to create the states enum property.
The format is a list of tuples like:
[(identifier, name, description, icon, number), ...]
......@@ -46,10 +46,8 @@ class Chord_Get_Ip(bpy.types.Operator):
if event.type == 'TIMER':
context.area.tag_redraw()
context.object.rotation_euler.y +=0.3
if self.query_thread.is_alive():
if self.query_thread.is_alive():
self.chord_global.state = \
possible_states()[self.counter%2+2][0]
else:
......
import bpy
from bpy.props import IntProperty, FloatProperty
from mathutils import *
from math import *
# import pdb
from os import system
from os import path
from sys import path as syspath
# from pythonosc import dispatcher
# from pythonosc import osc_server
syspath.append(path.dirname(bpy.data.filepath))
import Chordata_Armature as chordata
import send_arm_osc as send
from importlib import reload
reload(chordata)
reload(send)
system("clear")
D = bpy.data
C = bpy.context
do_send_osc = True
def check_sc_fr_end(context):
sc = context.scene
if sc.frame_current > sc.frame_end:
sc.frame_current = sc.frame_start
class Send_Anim_Osc(bpy.types.Operator):
"""Send Chordata armature animation trough OSC"""
bl_idname = "object.send_anim_osc"
bl_label = "Send Chordata Animation OSC"
def invoke(self, context, event):
return self.execute(context);
def execute(self, context):
for o in D.objects:
if o.type == "ARMATURE":
self.object = o
if self.object is None:
raise Error("There's no Armature in the scene.")
sc = context.scene
if sc.frame_current < sc.frame_start:
sc.frame_current = sc.frame_start
check_sc_fr_end(context)
wm = context.window_manager
self._timer = wm.event_timer_add( 1 / context.scene.render.fps , context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
def modal(self, context, event):
if event.type == 'TIMER':
send.send_Armature(self.object)
context.scene.frame_current += 1
check_sc_fr_end(context)
elif event.type in {'RIGHTMOUSE', 'ESC'}:
print("ESQUING")
self.cancel(context)
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def cancel(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
class ReceiveOperator(bpy.types.Operator):
"""Receive quaternions from OSC and move an armature"""
bl_idname = "object.receive_operator"
bl_label = "Receive Chordata Armature"
views_3d = [area for area in bpy.context.screen.areas if area.type == 'VIEW_3D' ]
def __init__(self):
self.chord = chordata.Chordata()
self.last_event = ""
def invoke(self, context, event):
"""Start the timer"""
if context.scene.layers[10]:
do_send_osc = True
print ("^"*10, "SENDING OSC TO:", send.IP, send.PORT)
else:
do_send_osc = False
print("^"*10, "NOT SENDING OSC!")
wm = context.window_manager
self._timer = wm.event_timer_add( 1 / context.scene.render.fps , context.window)
wm.modal_handler_add(self)
self.chord.start_server()
self.text(self.chord.message)
D.scenes['Scene'].layers[0] = True
D.scenes['Scene'].layers[1] = True
D.scenes['Scene'].layers[2] = True
if do_send_osc:
send.send_init_msg(self.chord.object)
self.do_set_keyframes = False
context.scene.frame_current = 0
context.scene.frame_start = 0
send.init_osc()
self.chord.reset_pose()
return {'RUNNING_MODAL'}
def text(self, text):
for a in self.views_3d:
a.header_text_set(text)
def modal(self, context, event):
if context.scene.layers[10]:
do_send_osc = True
else:
do_send_osc = False
if event.type == 'TIMER':
self.chord.put_quad_on_bones()
if do_send_osc:
send.send_Armature(self.chord.object)
if self.do_set_keyframes:
self.chord.set_key(context)
context.scene.frame_current += 1
elif event.type == 'A':
self.chord.get_rot_diff()
self.text(self.chord.message)
elif event.type == "Q":
D.scenes['Scene'].layers[0] = False
elif event.type == "K":
self.chord.object.animation_data_clear()
self.do_set_keyframes = True
self.report({"INFO"}, "Registering animation!")
elif event.type == "W":
D.scenes['Scene'].layers[1] = False
elif event.type == "E":
D.scenes['Scene'].layers[2] = False
elif event.type == "R":
D.scenes['Scene'].layers[0] = True
D.scenes['Scene'].layers[1] = True
D.scenes['Scene'].layers[2] = True
# elif event.type == 'LEFTMOUSE':
# self.cancel(context)
# return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
print("ESQUING")
if self.chord.object.animation_data:
context.scene.frame_end = self.chord.object.animation_data.action.frame_range[1]
wm = context.window_manager
wm.event_timer_remove(self._timer)
self.chord.server.shutdown()
self.chord.server.socket.close()
self.chord.st.join()
send.osc_terminate()
for a in self.views_3d:
a.header_text_set()
# pdb.set_trace()
# self.cancel(context)
return {'CANCELLED'}
self.last_event = event.type
return {'RUNNING_MODAL'}
def cancel(self, context):
"""
cancel() get's called when the operator is about to exit
Here we remove the timer and stop the server
"""
print("CANCELLING")
wm = context.window_manager
wm.event_timer_remove(self._timer)
self.text("Closing server..")
# self.chord.close_server()
self.chord.server.shutdown()
self.chord.st.join()
for a in self.views_3d:
a.header_text_set()
# ###########################################
# ### DEFINING CUSTOM METHODS ###
# ###########################################
def register():
# send.register()
bpy.utils.register_class(ReceiveOperator)
bpy.utils.register_class(Send_Anim_Osc)
def unregister():
bpy.utils.unregister_class(ReceiveOperator)
bpy.utils.unregister_class(Send_Anim_Osc)
# send.unregister()
if __name__ == "__main__":
register()
# test call
# bpy.ops.object.receive_operator('INVOKE_DEFAULT')
Metadata-Version: 1.1
Name: osc4py3
Version: 1.0.4
Summary: Python3 package for Open Sound Control (OSC) communications.
Home-page: http://perso.limsi.fr/pointal/dev:osc4py3
Author: Laurent Pointal
Author-email: laurent.pointal@limsi.fr
License: CEA CNRS Inria Logiciel Libre License, version 2.1 (CeCILL-2.1)
Download-URL: https://sourcesup.renater.fr/projects/osc4py3/
Description: OSC for Python3
===============
:author: Laurent Pointal <laurent.pointal@limsi.fr> <laurent.pointal@laposte.net>
:organization: CNRS - LIMSI
:copyright: CNRS - 2013-2018
:license: CeCILL-2.1
:version: 1.0.3
`Module documentation <http://osc4py3.readthedocs.org/>`_
`Subversion repository & bug tracking <https://sourcesup.renater.fr/scm/viewvc.php?root=osc4py3>`_
(on french academic SourceSup site).
`Developer page <https://perso.limsi.fr/pointal/dev:osc4py3>`_
.. note::
Testers feedback welcome. This development was finally not tested in its
initial planning, any problem / bug / info are welcome.
What is it?
-----------
This module is an implementation of `Open Sound Control (OSC)`_ message
transport protocol within a Python3 package.
.. _Open Sound Control (OSC): http://opensoundcontrol.org/
Manage different sides of OSC in possibly different contexts:
- encoding/decoding of OSC message packets (including bundles)
- routing of incoming messages based on selector regexps or globbing
- timed messages with possible delay period
- named client/server for sending/subscribing
- different scheduling models (single process, totally multithread, only multithread for communications)
- extra processing of packets (hack points to encrypt/decrypt, sign/verify…)
Note: routing, timed messages, named client/server, scheduling models make a complex system
(see the “big picture” in doc). The oscbuildparse module of osc4py3 package can be used as
is and provides nice OSC packets encoding/decoding functions usable in your own message
transmission scheme.
Installation
------------
Unless someone built a package for your OS distro, the simplest procedure
is to use ``pip`` to install the module:
pip install osc4py3
If you have no admin access to install things on you computer, you may install
a virtualenv and run pip inside this virtual env, or you can do a local user
installation:
pip install --user osc4py3
Keywords: communication,sound,network,open sound control,osc
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: CEA CNRS Inria Logiciel Libre License, version 2.1 (CeCILL-2.1)
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Multimedia :: Sound/Audio
OSC for Python3
===============
:author: Laurent Pointal <laurent.pointal@limsi.fr> <laurent.pointal@laposte.net>
:organization: CNRS - LIMSI
:copyright: CNRS - 2013-2018
:license: CeCILL-2.1
:version: 1.0.3
`Module documentation <http://osc4py3.readthedocs.org/>`_
`Subversion repository & bug tracking <https://sourcesup.renater.fr/scm/viewvc.php?root=osc4py3>`_
(on french academic SourceSup site).
`Developer page <https://perso.limsi.fr/pointal/dev:osc4py3>`_
.. note::
Testers feedback welcome. This development was finally not tested in its
initial planning, any problem / bug / info are welcome.
What is it?
-----------
This module is an implementation of `Open Sound Control (OSC)`_ message
transport protocol within a Python3 package.
.. _Open Sound Control (OSC): http://opensoundcontrol.org/
Manage different sides of OSC in possibly different contexts:
- encoding/decoding of OSC message packets (including bundles)
- routing of incoming messages based on selector regexps or globbing
- timed messages with possible delay period
- named client/server for sending/subscribing
- different scheduling models (single process, totally multithread, only multithread for communications)
- extra processing of packets (hack points to encrypt/decrypt, sign/verify…)
Note: routing, timed messages, named client/server, scheduling models make a complex system
(see the “big picture” in doc). The oscbuildparse module of osc4py3 package can be used as
is and provides nice OSC packets encoding/decoding functions usable in your own message
transmission scheme.
Installation
------------
Unless someone built a package for your OS distro, the simplest procedure
is to use ``pip`` to install the module:
pip install osc4py3
If you have no admin access to install things on you computer, you may install
a virtualenv and run pip inside this virtual env, or you can do a local user
installation:
pip install --user osc4py3
Metadata-Version: 1.1
Name: osc4py3
Version: 1.0.4
Summary: Python3 package for Open Sound Control (OSC) communications.
Home-page: http://perso.limsi.fr/pointal/dev:osc4py3
Author: Laurent Pointal
Author-email: laurent.pointal@limsi.fr
License: CEA CNRS Inria Logiciel Libre License, version 2.1 (CeCILL-2.1)
Download-URL: https://sourcesup.renater.fr/projects/osc4py3/
Description: OSC for Python3
===============
:author: Laurent Pointal <laurent.pointal@limsi.fr> <laurent.pointal@laposte.net>
:organization: CNRS - LIMSI
:copyright: CNRS - 2013-2018
:license: CeCILL-2.1
:version: 1.0.3
`Module documentation <http://osc4py3.readthedocs.org/>`_
`Subversion repository & bug tracking <https://sourcesup.renater.fr/scm/viewvc.php?root=osc4py3>`_
(on french academic SourceSup site).
`Developer page <https://perso.limsi.fr/pointal/dev:osc4py3>`_
.. note::
Testers feedback welcome. This development was finally not tested in its
initial planning, any problem / bug / info are welcome.
What is it?
-----------
This module is an implementation of `Open Sound Control (OSC)`_ message
transport protocol within a Python3 package.
.. _Open Sound Control (OSC): http://opensoundcontrol.org/
Manage different sides of OSC in possibly different contexts:
- encoding/decoding of OSC message packets (including bundles)
- routing of incoming messages based on selector regexps or globbing
- timed messages with possible delay period
- named client/server for sending/subscribing
- different scheduling models (single process, totally multithread, only multithread for communications)
- extra processing of packets (hack points to encrypt/decrypt, sign/verify…)
Note: routing, timed messages, named client/server, scheduling models make a complex system
(see the “big picture” in doc). The oscbuildparse module of osc4py3 package can be used as
is and provides nice OSC packets encoding/decoding functions usable in your own message
transmission scheme.
Installation
------------
Unless someone built a package for your OS distro, the simplest procedure
is to use ``pip`` to install the module:
pip install osc4py3
If you have no admin access to install things on you computer, you may install
a virtualenv and run pip inside this virtual env, or you can do a local user
installation:
pip install --user osc4py3
Keywords: communication,sound,network,open sound control,osc
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: CEA CNRS Inria Logiciel Libre License, version 2.1 (CeCILL-2.1)
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Multimedia :: Sound/Audio
README.txt
setup.py
osc4py3/__init__.py
osc4py3/as__common.py
osc4py3/as_allthreads.py
osc4py3/as_comthreads.py
osc4py3/as_eventloop.py
osc4py3/oscbuildparse.py
osc4py3/oscchannel.py
osc4py3/oscdispatching.py
osc4py3/oscdistributing.py
osc4py3/oscmethod.py
osc4py3/oscnettools.py
osc4py3/oscpacketoptions.py
osc4py3/oscpeeradapt.py
osc4py3/oscscheduling.py
osc4py3/osctcp.py
osc4py3/osctoolspools.py
osc4py3/oscudpmc.py
osc4py3.egg-info/PKG-INFO
osc4py3.egg-info/SOURCES.txt
osc4py3.egg-info/dependency_links.txt
osc4py3.egg-info/top_level.txt
osc4py3/demos/__init__.py
osc4py3/demos/demoslogger.py
osc4py3/demos/rundemo.py
osc4py3/demos/speedudpcli.py
osc4py3/demos/speedudpcommon.py
osc4py3/demos/speedudpsrv.py
osc4py3/tests/__init__.py
osc4py3/tests/buildparse.py
osc4py3/tests/channel.py
osc4py3/tests/dispatching.py
osc4py3/tests/method.py
osc4py3/tests/nettools.py
osc4py3/tests/testslogger.py
osc4py3/tests/toolspools.py
osc4py3/tests/udp.py
osc4py3/tests/udpbc.py
osc4py3/tests/udpmc.py
\ No newline at end of file