Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Boolean support #4

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
build
*.pyc
.DS_Store
67 changes: 58 additions & 9 deletions OSC.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
global IntTypes
IntTypes = [types.IntType]

global BoolTypes
BoolTypes = [types.BooleanType]

global NTP_epoch
from calendar import timegm
NTP_epoch = timegm((1900,1,1,0,0,0)) # NTP time started in 1 Jan 1900
Expand Down Expand Up @@ -291,11 +294,22 @@ def append(self, argument, typehint=None):
elif typehint == 't':
binary = OSCTimeTag(argument)
tag = 't'
# for booleans we take only the empty
# binary from the def and trust the users tag
elif typehint == 'T':
binary = OSCBoolean(argument)[0]
tag = 'T'
elif typehint == 'F':
binary = OSCBoolean(arguement)[0]
tag = 'F'
else:
tag, binary = OSCArgument(argument, typehint)

self.typetags += tag
self.message += binary

if binary is not None:
self.message += binary


def getBinary(self):
"""Returns the binary representation of the message
Expand All @@ -314,7 +328,7 @@ def __repr__(self):
def __str__(self):
"""Returns the Message's address and contents as a string.
"""
return "%s %s" % (self.address, str(self.values()))
return "%s %s %s" % (self.address, self.tags(), str(self.values()))

def __len__(self):
"""Returns the number of arguments appended so far
Expand Down Expand Up @@ -737,6 +751,9 @@ def OSCArgument(next, typehint=None):
elif type(next) in IntTypes:
binary = struct.pack(">i", int(next))
tag = 'i'
elif type(next) in BoolTypes:
# return tag and an empty string
tag, binary = OSCBoolean(next)
else:
binary = OSCString(next)
tag = 's'
Expand Down Expand Up @@ -782,6 +799,22 @@ def OSCTimeTag(time):

return binary

def OSCBoolean(boolean_value):
""" Verifys you are trying to perform opperation on
a boolean and returns the empty binary required along with correct tag"""
# binary is always empty so define immediately
binary = None
if isinstance(boolean_value, bool):
if boolean_value == True:
tag = 'T'
elif boolean_value == False:
tag = 'F'
else:
raise OSCError('OSC was expecting and boolean and got a %s' %type(boolean_value))

return tag, binary


######
#
# OSCMessage decoding functions
Expand All @@ -795,6 +828,14 @@ def _readString(data):
nextData = int(math.ceil((length+1) / 4.0) * 4)
return (data[0:length], data[nextData:])

def _readBoolean(data):
"""Tries to verify boolean value"""
# data can't have anything in it if its a boolean
if len(data) > 0:
print 'To Many Data Bits for a Boolean Value'
else:
return None, None

def _readBlob(data):
"""Reads the next (numbered) block of data
"""
Expand Down Expand Up @@ -872,7 +913,9 @@ def _readDouble(data):
def decodeOSC(data):
"""Converts a binary OSC message to a Python list.
"""
table = {"i":_readInt, "f":_readFloat, "s":_readString, "b":_readBlob, "d":_readDouble, "t":_readTimeTag}
table = {"i":_readInt, "f":_readFloat, "s":_readString,
"b":_readBlob, "d":_readDouble, "t":_readTimeTag,
"T":_readBoolean, "F":_readBoolean}
decoded = []
address, rest = _readString(data)
if address.startswith(","):
Expand All @@ -897,8 +940,13 @@ def decodeOSC(data):
decoded.append(typetags)
if typetags.startswith(","):
for tag in typetags[1:]:
value, rest = table[tag](rest)
decoded.append(value)
if tag == 'T':
decoded.append(True)
elif tag == 'F':
decoded.append(False)
else:
value, rest = table[tag](rest)
decoded.append(value)
else:
raise OSCError("OSCMessage's typetag-string lacks the magic ','")

Expand Down Expand Up @@ -1306,7 +1354,9 @@ def getRegEx(pattern):
# Translate OSC-address syntax to python 're' syntax
pattern = pattern.replace(".", r"\.") # first, escape all '.'s in the pattern.
pattern = pattern.replace("(", r"\(") # escape all '('s.
pattern = pattern.replace(")", r"\)") # escape all ')'s.
pattern = pattern.replace(")", r"\)")
pattern = pattern.replace("]", r"\]")
pattern = pattern.replace("[", r"\[") # escape all ')'s.
pattern = pattern.replace("*", r".*") # replace a '*' by '.*' (match 0 or more characters)
pattern = pattern.translate(OSCtrans) # change '?' to '.' and '{,}' to '(|)'

Expand Down Expand Up @@ -1691,9 +1741,9 @@ def addMsgHandler(self, address, callback):
- 'callback' is the function called for incoming OSCMessages that match 'address'.
The callback-function will be called with the same arguments as the 'msgPrinter_handler' below
"""
for chk in '*?,[]{}# ':
for chk in '*?,{}# ':
if chk in address:
raise OSCServerError("OSC-address string may not contain any characters in '*?,[]{}# '")
raise OSCServerError("OSC-address string may not contain any characters in '*?,{}# '")

if type(callback) not in (types.FunctionType, types.MethodType):
raise OSCServerError("Message callback '%s' is not callable" % repr(callback))
Expand Down Expand Up @@ -1728,7 +1778,6 @@ def dispatchMessage(self, pattern, tags, data, client_address):
raise OSCServerError("Malformed OSC-message; got %d typetags [%s] vs. %d values" % (len(tags), tags, len(data)))

expr = getRegEx(pattern)

replies = []
matched = 0
for addr in self.callbacks.keys():
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python

from distutils.core import setup
from setuptools import setup

import OSC

Expand Down