diff --git a/.gitignore b/.gitignore index 378eac2..8458dd7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ build +*.pyc +.DS_Store diff --git a/OSC.py b/OSC.py index a65ae20..6db0e1e 100755 --- a/OSC.py +++ b/OSC.py @@ -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 @@ -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 @@ -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 @@ -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' @@ -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 @@ -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 """ @@ -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(","): @@ -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 ','") @@ -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 '(|)' @@ -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)) @@ -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(): diff --git a/setup.py b/setup.py index c010af4..7056bba 100755 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from distutils.core import setup +from setuptools import setup import OSC