Worklog for Zakk
TUIO Client
Return to Worklogs
| ||
'TUIO Client.bmx '============================= SuperStrict Graphics 640, 480 Include "OSC.bmx" Include "message type.bmx" Include "puck type.bmx" Include "events.bmx" '============================= '============================= Global bytes_got:Int=0 '============================= Global GetByte:Byte[] Global socket:TSocket, stream:TSocketStream socket = TSocket.CreateUDP() '============================= If Not socket RuntimeError("Your sockets are fried!") End If socket.Bind(3333) Print "creating stream" stream = TSocketStream.Create(socket) Global avail:Int '============================= '==========MAIN LOOP========== Local n:Int, stringy:String While Not KeyHit(KEY_ESCAPE) avail = socket.ReadAvail() If avail > 0 stringy=stream.ReadString(avail) GetByte=New Byte[avail] For n=0 To avail-1 GetByte[n]=stringy[n] Next bytes_got=-1 GetMessages() EndIf Local p:TPuck For p=EachIn TPuck.global_list SetRotation p.a_degrees SetHandle 10, 10 DrawRect p.x, p.y, 21, 21 Next Flip Cls Wend '============================= 'OSC.bmx '==========FUNCTIONS========== Function NextByte:Byte() bytes_got:+1 If bytes_got<=avail-1 Return GetByte[bytes_got] EndIf Notify "overread" Return 222 End Function '============================= Function NextInt:Int() Return (NextByte() Shl 24) | (NextByte() Shl 16) | (NextByte() Shl 8) | NextByte() End Function '============================= Function NextFloat:Float() Local i:Int=NextInt() Local f:Float Ptr=Float Ptr(Varptr(i)) Return f[0] End Function '============================= Function GetMessages() bytes_got:+8 Print "#bundle" bytes_got:+8 '============================= Local c:Byte Local message:TMessage While bytes_got<avail-1 Print "size: "+Nextint() message=TMessage.GetMessage() message.Printout() message.Process() While (bytes_got Mod 4)<>3 c=NextByte() Wend Wend Print "" End Function '============================= Function OSC_ReadString:String() Local s:String, c:Byte c=NextByte() While c<>Null s=s+Chr(c) c=NextByte() If c=Null s=s EndIf Wend While (bytes_got Mod 4)<>3 c=NextByte() s=s Wend Return s End Function '============================= 'message type.bmx '============================= Const ARG_INT:Int=1, ARG_FLOAT:Int=2, ARG_STRING:Int=3 '============================= '============================= Type TArgument Field kind:Int Field i:Int, f:Float, s:String End Type '============================= Type TMessage Field address_pattern:String Field type_tags:String Field argument_list:TList Field message_type:String '============================= Function GetMessage:TMessage() Local message:TMessage=New TMessage message.address_pattern=OSC_ReadString() 'Read OSC Address Pattern message.type_tags=OSC_ReadString() Print "address: "+message.address_pattern Print "type tags: "+message.type_tags Local typetags:String=Right(message.type_tags, Len(message.type_tags)-1) Print typetags Local L:Int=Len(typetags), n:Int, c:String For n=0 To L-1 c=Left(typetags, 1) typetags=Right(typetags, Len(typetags)-1) Local arg:TArgument=New TArgument Select c Case "i" 'int32 arg.kind=ARG_INT arg.i=NextInt() message.argument_list.AddLast( arg ) Case "f" 'float32 arg.kind=ARG_FLOAT arg.f=NextFloat() message.argument_list.AddLast( arg ) Case "s" 'OSC-String arg.kind=ARG_STRING arg.s=OSC_ReadString() 'message.argument_list.AddLast( arg ) message.message_type=arg.s Case "b" 'OSC-blob End Select Next Return message End Function '============================= Method New() argument_list=New TList End Method '============================= Method Printout() Local o:Object For o=EachIn argument_list If TArgument(o) Local a:TArgument=TArgument(o) Select a.kind Case ARG_INT Print "Int: "+a.i Case ARG_FLOAT Print "Float: "+a.f Case ARG_STRING Print "String: "+a.s Default End Select EndIf Next End Method '============================= Method Process() Local profile:String=Right(address_pattern, address_pattern.length-6) Print "profile: "+profile Select profile Case "2Dobj" Print "message type: "+message_type Select message_type Case "alive" TPuck.alive_list.Clear() Local arg:TArgument, p:TPuck, new_puck:Int For arg=EachIn argument_list If arg.kind=ARG_INT new_puck=True p=TPuck.SessionId_Puck(arg.i) If p<>Null TPuck.alive_list.AddLast(p) Else p=New TPuck p.session_id=arg.i TPuck.alive_list.AddLast(p) EventCall_PuckEnter(p) EndIf EndIf Next For p=EachIn TPuck.global_list If Not TPuck.alive_list.Contains(p) EventCall_PuckLeave(p) EndIf Next Case "set" Local p:TPuck Local array:Object[]=ListToArray(argument_list) 's i x y a X Y A m r Local session_id:Int=TArgument(array[0]).i p=TPuck.SessionId_Puck(session_id) If p<>Null p.class_id=TArgument(array[1]).i Local sensor_x:Float=TArgument(array[2]).f Local sensor_y:Float=TArgument(array[3]).f Local a_radians:Float=TArgument(array[4]).f EventCall_PuckMove(p, sensor_x, sensor_y, a_radians) EndIf Case "fseq" End Select' Case "2Dcur" Default End Select End Method End Type '============================= 'puck type.bmx '============================= Const sensor_w:Int=640, sensor_h:Int=480 '============================= '============================= Type TPuck '============================= Global global_list:TList=New TList Global alive_list:TList=New TList '============================= Field global_link:TLink Field session_id:Int Field class_id:Int Field sensor_x:Float, sensor_y:Float Field x:Int, y:Int Field a_radians:Float, a_degrees:Float '============================= Function Update_Alive() End Function '============================= Function SessionId_Puck:TPuck(sid:Int) Local p:TPuck For p=EachIn TPuck.global_list If p.session_id=sid Return p EndIf Next Return Null End Function '============================= Method New() global_link=global_list.AddLast(Self) End Method '============================= Method Destroy() global_link.Remove() End Method End Type '============================= 'events.bmx '============================= Global EVENT_PUCKENTER:Int=AllocUserEventId() Global EVENT_PUCKLEAVE:Int=AllocUserEventId() Global EVENT_PUCKMOVE:Int=AllocUserEventId() '============================= '============================= Function EventCall_PuckMove(puck:Object, sensor_x:Float, sensor_y:Float, a_radians:Float) Local x:Int=sensor_x*sensor_w, y:Int=sensor_y*sensor_h Local a_degrees:Float=RadToDeg(a_radians) Local puckmove:TEvent=TEvent.Create(EVENT_PUCKMOVE, puck, a_degrees, 0, x, y, Null) PostEvent(puckmove, True) Rem the event data contains the pucks rotation End Rem Local p:TPuck=TPuck(puck) p.sensor_x=sensor_x p.sensor_y=sensor_y p.a_radians=a_radians p.a_degrees=a_degrees p.x=sensor_x*sensor_w p.y=sensor_y*sensor_h End Function '============================= Function EventCall_PuckEnter(puck:Object) End Function '============================= Function EventCall_PuckLeave(puck:Object) Local p:TPuck=TPuck(puck) p.Destroy() End Function '============================= Function RadToDeg:Float(rad:Float) Return rad*180.0/Pi End Function -------------------- <XtiaeN>: i wear my rollerblades while i hack games, for quick getaways |
| ||
Progress is coming along nicely, I've gotten my client program to communicate with the TUIO simulator acquired here,
but the OSC client part of the program is pretty stripped down. When
this project is done I will definitely be coming back to that. I finally managed to get TSocketStream to be able to read floats and ints from UDP streams, using a pretty straightforward workaround involving pointers. Will post the code after I finish cleaning it up. -------------------- <XtiaeN>: i wear my rollerblades while i hack games, for quick getaways |