Skip to content

Commit 7e521bc

Browse files
Emlyn CorrinEmlyn Corrin
authored andcommitted
Support Arrays
1 parent 7768cb1 commit 7e521bc

2 files changed

Lines changed: 70 additions & 18 deletions

File tree

pythonosc/osc_message.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ def _parse_datagram(self):
3333
if type_tag.startswith(','):
3434
type_tag = type_tag[1:]
3535

36+
params = []
37+
param_stack = [params]
3638
# Parse each parameter given its type.
3739
for param in type_tag:
40+
have_val = True
3841
if param == "i": # Integer.
3942
val, index = osc_types.get_int(self._dgram, index)
4043
elif param == "f": # Float.
@@ -49,11 +52,25 @@ def _parse_datagram(self):
4952
val = True
5053
elif param == "F": # False.
5154
val = False
55+
elif param == "[": # Array start.
56+
a = []
57+
param_stack[-1].append(a)
58+
param_stack.append(a)
59+
have_val = False
60+
elif param == "]": # Array stop.
61+
if len(param_stack) < 2:
62+
raise ParseError('Unexpected closing bracket in type tag: {0}'.format(type_tag))
63+
param_stack.pop()
64+
have_val = False
5265
# TODO: Support more exotic types as described in the specification.
5366
else:
5467
logging.warning('Unhandled parameter type: {0}'.format(param))
5568
continue
56-
self._parameters.append(val)
69+
if have_val:
70+
param_stack[-1].append(val)
71+
if len(param_stack) != 1:
72+
raise ParseError('Missing closing bracket in type tag: {0}'.format(type_tag))
73+
self._parameters = params
5774
except osc_types.ParseError as pe:
5875
raise ParseError('Found incorrect datagram, ignoring it', pe)
5976

pythonosc/osc_message_builder.py

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class OscMessageBuilder(object):
1919
ARG_TYPE_TRUE = "T"
2020
ARG_TYPE_FALSE = "F"
2121

22+
ARG_TYPE_ARRAY_START = "["
23+
ARG_TYPE_ARRAY_STOP = "]"
24+
2225
_SUPPORTED_ARG_TYPES = (
2326
ARG_TYPE_FLOAT, ARG_TYPE_INT, ARG_TYPE_BLOB, ARG_TYPE_STRING, ARG_TYPE_RGBA, ARG_TYPE_TRUE, ARG_TYPE_FALSE)
2427

@@ -46,6 +49,16 @@ def args(self):
4649
"""Returns the (type, value) arguments list of this message."""
4750
return self._args
4851

52+
def valid_type(self, arg_type):
53+
if arg_type in self._SUPPORTED_ARG_TYPES:
54+
return True
55+
elif isinstance(arg_type, list):
56+
for a in arg_type:
57+
if not self.valid_type(a):
58+
return False
59+
return True
60+
return False
61+
4962
def add_arg(self, arg_value, arg_type=None):
5063
"""Add a typed argument to this message.
5164
@@ -56,25 +69,44 @@ def add_arg(self, arg_value, arg_type=None):
5669
Raises:
5770
- ValueError: if the type is not supported.
5871
"""
59-
if arg_type and arg_type not in self._SUPPORTED_ARG_TYPES:
72+
if arg_type and not self.valid_type(arg_type):
6073
raise ValueError(
6174
'arg_type must be one of {}'.format(self._SUPPORTED_ARG_TYPES))
6275
if not arg_type:
63-
if isinstance(arg_value, str):
64-
arg_type = self.ARG_TYPE_STRING
65-
elif isinstance(arg_value, bytes):
66-
arg_type = self.ARG_TYPE_BLOB
67-
elif isinstance(arg_value, int):
68-
arg_type = self.ARG_TYPE_INT
69-
elif isinstance(arg_value, float):
70-
arg_type = self.ARG_TYPE_FLOAT
71-
elif arg_value == True:
72-
arg_type = self.ARG_TYPE_TRUE
73-
elif arg_value == False:
74-
arg_type = self.ARG_TYPE_FALSE
75-
else:
76-
raise ValueError('Infered arg_value type is not supported')
77-
self._args.append((arg_type, arg_value))
76+
arg_type = self.get_arg_type(arg_value)
77+
if isinstance(arg_type, list):
78+
self._args.append((self.ARG_TYPE_ARRAY_START, None))
79+
for v, t in zip(arg_value, arg_type):
80+
self.add_arg(v, t)
81+
self._args.append((self.ARG_TYPE_ARRAY_STOP, None))
82+
else:
83+
self._args.append((arg_type, arg_value))
84+
85+
def get_arg_type(self, arg_value):
86+
"""Guess the type of a value.
87+
88+
Args:
89+
- arg_value: The value to guess the type of.
90+
Raises:
91+
- ValueError: if the type is not supported.
92+
"""
93+
if isinstance(arg_value, str):
94+
arg_type = self.ARG_TYPE_STRING
95+
elif isinstance(arg_value, bytes):
96+
arg_type = self.ARG_TYPE_BLOB
97+
elif isinstance(arg_value, int):
98+
arg_type = self.ARG_TYPE_INT
99+
elif isinstance(arg_value, float):
100+
arg_type = self.ARG_TYPE_FLOAT
101+
elif arg_value == True:
102+
arg_type = self.ARG_TYPE_TRUE
103+
elif arg_value == False:
104+
arg_type = self.ARG_TYPE_FALSE
105+
elif isinstance(arg_value, list):
106+
arg_type = [self.get_arg_type(v) for v in arg_value]
107+
else:
108+
raise ValueError('Infered arg_value type is not supported')
109+
return arg_type
78110

79111
def build(self):
80112
"""Builds an OscMessage from the current state of this builder.
@@ -110,7 +142,10 @@ def build(self):
110142
dgram += osc_types.write_blob(value)
111143
elif arg_type == self.ARG_TYPE_RGBA:
112144
dgram += osc_types.write_rgba(value)
113-
elif arg_type == self.ARG_TYPE_TRUE or arg_type == self.ARG_TYPE_FALSE:
145+
elif arg_type in (self.ARG_TYPE_TRUE,
146+
self.ARG_TYPE_FALSE,
147+
self.ARG_TYPE_ARRAY_START,
148+
self.ARG_TYPE_ARRAY_STOP):
114149
continue
115150
else:
116151
raise BuildError('Incorrect parameter type found {}'.format(

0 commit comments

Comments
 (0)