def _parse_datagram(self):
		self._address_regexp, index = osc_types.get_string(self._dgram, 0)
		if not self._dgram[index:]:
			# No params is legit, just return now.
			return

		# Get the parameters types.
		type_tag, index = osc_types.get_string(self._dgram, index)
		if type_tag.startswith(','):
			type_tag = type_tag[1:]

		# Parse each parameter given its type.
		for param in type_tag:
			if param == "i":  # Integer.
				val, index = osc_types.get_int(self._dgram, index)
			elif param == "f":  # Float.
				val, index = osc_types.get_float(self._dgram, index)
			elif param == "s":  # String.
				val, index = osc_types.get_string(self._dgram, index)
			elif param == "b":  # Blob.
				val, index = osc_types.get_blob(self._dgram, index)
			elif param == "T": # True.
				val = True
			elif param == "F": # False.
				val = False
			# TODO: Support more exotic types as described in the specification.
			else:
				logging.getLogger().warning('Unhandled parameter type: {0}'.format(param))
				continue
			self._parameters.append(val)
Exemple #2
0
    def _parse_datagram(self) -> None:
        try:
            self._address_regexp, index = osc_types.get_string(self._dgram, 0)
            if not self._dgram[index:]:
                # No params is legit, just return now.
                return

            # Get the parameters types.
            type_tag, index = osc_types.get_string(self._dgram, index)
            if type_tag.startswith(','):
                type_tag = type_tag[1:]

            params = []
            param_stack = [params]
            # Parse each parameter given its type.
            for param in type_tag:
                if param == "i":  # Integer.
                    val, index = osc_types.get_int(self._dgram, index)
                elif param == "f":  # Float.
                    val, index = osc_types.get_float(self._dgram, index)
                elif param == "d":  # Double.
                    val, index = osc_types.get_double(self._dgram, index)
                elif param == "s":  # String.
                    val, index = osc_types.get_string(self._dgram, index)
                elif param == "b":  # Blob.
                    val, index = osc_types.get_blob(self._dgram, index)
                elif param == "r":  # RGBA.
                    val, index = osc_types.get_rgba(self._dgram, index)
                elif param == "m":  # MIDI.
                    val, index = osc_types.get_midi(self._dgram, index)
                elif param == "t":  # osc time tag:
                    val, index = osc_types.get_ttag(self._dgram, index)
                elif param == "T":  # True.
                    val = True
                elif param == "F":  # False.
                    val = False
                elif param == "[":  # Array start.
                    array = []
                    param_stack[-1].append(array)
                    param_stack.append(array)
                elif param == "]":  # Array stop.
                    if len(param_stack) < 2:
                        raise ParseError(
                            'Unexpected closing bracket in type tag: {0}'.
                            format(type_tag))
                    param_stack.pop()
                # TODO: Support more exotic types as described in the specification.
                else:
                    logging.warning(
                        'Unhandled parameter type: {0}'.format(param))
                    continue
                if param not in "[]":
                    param_stack[-1].append(val)
            if len(param_stack) != 1:
                raise ParseError(
                    'Missing closing bracket in type tag: {0}'.format(
                        type_tag))
            self._parameters = params
        except osc_types.ParseError as pe:
            raise ParseError('Found incorrect datagram, ignoring it', pe)
Exemple #3
0
    def _parse_datagram(self):
        try:
            self._address_regexp, index = osc_types.get_string(self._dgram, 0)
            if not self._dgram[index:]:
                # No params is legit, just return now.
                return

            # Get the parameters types.
            type_tag, index = osc_types.get_string(self._dgram, index)
            if type_tag.startswith(','):
                type_tag = type_tag[1:]

            # Parse each parameter given its type.
            for param in type_tag:
                if param == "i":  # Integer.
                    val, index = osc_types.get_int(self._dgram, index)
                elif param == "f":  # Float.
                    val, index = osc_types.get_float(self._dgram, index)
                elif param == "s":  # String.
                    val, index = osc_types.get_string(self._dgram, index)
                elif param == "b":  # Blob.
                    val, index = osc_types.get_blob(self._dgram, index)
                elif param == "T":  # True.
                    val = True
                elif param == "F":  # False.
                    val = False
                # TODO: Support more exotic types as described in the specification.
                else:
                    logging.warning(
                        'Unhandled parameter type: {0}'.format(param))
                    continue
                self._parameters.append(val)
        except osc_types.ParseError as pe:
            raise ParseError('Found incorrect datagram, ignoring it', pe)
Exemple #4
0
  def _parse_datagram(self):
    try:
      self._address_regexp, index = osc_types.get_string(self._dgram, 0)
      if not self._dgram[index:]:
        # No params is legit, just return now.
        return

      # Get the parameters types.
      type_tag, index = osc_types.get_string(self._dgram, index)
      if type_tag.startswith(','):
        type_tag = type_tag[1:]

      # Parse each parameter given its type.
      for param in type_tag:
        if param == "i":  # Integer.
          val, index = osc_types.get_int(self._dgram, index)
        elif param == "f":  # Float.
          val, index = osc_types.get_float(self._dgram, index)
        elif param == "s":  # String.
          val, index = osc_types.get_string(self._dgram, index)
        elif param == "b":  # Blob.
          val, index = osc_types.get_blob(self._dgram, index)
        # TODO: Support more exotic types as described in the specification.
        elif param == 0:
          # We've reached the end of the param string, finish now.
          return
        else:
          logging.warning('Unhandled parameter type: {0}'.format(param))
          continue
        self._parameters.append(val)
    except osc_types.ParseError as pe:
      raise ParseError('Found incorrect datagram, ignoring it', pe)
Exemple #5
0
  def _parse_datagram(self):
    try:
      self._address_regexp, index = osc_types.get_string(self._dgram, 0)
      if not self._dgram[index:]:
        # No params is legit, just return now.
        return

      # Get the parameters types.
      type_tag, index = osc_types.get_string(self._dgram, index)
      if type_tag.startswith(','):
        type_tag = type_tag[1:]

      params = []
      param_stack = [params]
      # Parse each parameter given its type.
      for param in type_tag:
        if param == "i":  # Integer.
          val, index = osc_types.get_int(self._dgram, index)
        elif param == "f":  # Float.
          val, index = osc_types.get_float(self._dgram, index)
        elif param == "d":  # Double.
          val, index = osc_types.get_double(self._dgram, index)
        elif param == "s":  # String.
          val, index = osc_types.get_string(self._dgram, index)
        elif param == "b":  # Blob.
          val, index = osc_types.get_blob(self._dgram, index)
        elif param == "r":  # RGBA.
          val, index = osc_types.get_rgba(self._dgram, index)
        elif param == "m":  # MIDI.
          val, index = osc_types.get_midi(self._dgram, index)
        elif param == "t":  # osc time tag:
            val, index = osc_types.get_ttag(self._dgram, index)
        elif param == "T":  # True.
          val = True
        elif param == "F":  # False.
          val = False
        elif param == "[":  # Array start.
          array = []
          param_stack[-1].append(array)
          param_stack.append(array)
        elif param == "]": # Array stop.
          if len(param_stack) < 2:
            raise ParseError('Unexpected closing bracket in type tag: {0}'.format(type_tag))
          param_stack.pop()
        # TODO: Support more exotic types as described in the specification.
        else:
          logging.warning('Unhandled parameter type: {0}'.format(param))
          continue
        if param not in "[]":
          param_stack[-1].append(val)
      if len(param_stack) != 1:
        raise ParseError('Missing closing bracket in type tag: {0}'.format(type_tag))
      self._parameters = params
    except osc_types.ParseError as pe:
      raise ParseError('Found incorrect datagram, ignoring it', pe)
Exemple #6
0
    def __parse_sc_blob(data):
        '''Parses the blob from a SuperCollider osc message'''

        TYPE_TAG_MARKER = ord(b',')
        TYPE_TAG_START = 4
        NUM_SIZE = 4
        INT_TAG = ord(b'i')
        bytes2type = {
            ord(b'i'): lambda data: osc_types.get_int(data, 0),
            ord(b'f'): lambda data: osc_types.get_float(data, 0),
            ord(b's'): lambda data: osc_types.get_string(data, 0),
        }

        def __get_aligned_pos(pos):
            return NUM_SIZE * int(np.ceil((pos)/NUM_SIZE))

        def __parse_list(data):
            list_size, _ = bytes2type[INT_TAG](data)
            type_tag_offset = __get_aligned_pos(list_size + 2)
            type_tag_end = TYPE_TAG_START + type_tag_offset
            type_tag = data[TYPE_TAG_START + 1: TYPE_TAG_START + 1 + list_size]
            value_list = []
            idx = type_tag_end
            for t in type_tag:
                value, num_bytes = bytes2type[t](data[idx:])
                value_list.append(value)
                idx += num_bytes

            return value_list, list_size

        def __parse_sc_msg(data):
            list_size, _ = bytes2type[INT_TAG](data)
            msg_size = __get_aligned_pos(NUM_SIZE + list_size)
            sc_list, _ = __parse_list(data[NUM_SIZE: msg_size])
            return sc_list, msg_size

        bytes2type[ord(b'b')] = __parse_sc_msg

        def __parse_bundle(data):
            bundle_size = len(data)
            lists = []
            idx = 16  # skip header
            while idx < bundle_size:
                sc_list, list_size = __parse_sc_msg(data[idx:])
                lists.append(sc_list)
                idx += list_size

            return lists, bundle_size

        if data[TYPE_TAG_START] == TYPE_TAG_MARKER:
            return __parse_list(data)[0]
        elif data[:8] == b'#bundle\x00':
            return __parse_bundle(data)[0]
        else:
            return data
    def test_get_string(self):
        cases = {
            b"A\x00\x00\x00": ("A", 4),
            b"AB\x00\x00": ("AB", 4),
            b"ABC\x00": ("ABC", 4),
            b"ABCD\x00\x00\x00\x00": ("ABCD", 8),
            b"ABCD\x00\x00\x00\x00GARBAGE": ("ABCD", 8),
        }

        for dgram, expected in cases.items():
            self.assertEqual(expected, osc_types.get_string(dgram, 0))
Exemple #8
0
  def test_get_string(self):
    cases = {
        b"A\x00\x00\x00": ("A", 4),
        b"AB\x00\x00": ("AB", 4),
        b"ABC\x00": ("ABC", 4),
        b"ABCD\x00\x00\x00\x00": ("ABCD", 8),

        b"ABCD\x00\x00\x00\x00GARBAGE": ("ABCD", 8),
    }

    for dgram, expected in cases.items():
      self.assertEqual(expected, osc_types.get_string(dgram, 0))
def _parse_list(dgram: bytes, start_index: int) -> Tuple[Sequence[Any], int]:
    """Parse a OSC List

    List consists of the following bytes:
    4 bytes (int) : list_size
    n bytes (string) : OSC type tag
    n bytes (x) : content as specified by type tag

    Parameters
    ----------
    dgram : bytes
        datagram with the list
    start_index : int
        parsing starting index

    Returns
    -------
    Tuple[Sequence[Any], int]
        parsed list contents, starting index + number of consumed bytes

    Raises
    ------
    ParseError
        If datagram is invalid.
    """
    # parse list size
    _LOGGER.debug("[ start parsing list: %s", dgram[start_index:])
    list_size, start_index = osc_types.get_int(dgram, start_index)

    # parse type tag
    type_tag, start_index = osc_types.get_string(dgram, start_index)
    if type_tag.startswith(","):
        type_tag = type_tag[1:]

    _LOGGER.debug("list with size %d and content '%s'", list_size, type_tag)

    # parse content
    value_list = []
    for tag in type_tag:
        try:
            value, start_index = BYTES_2_TYPE[tag](dgram, start_index)
        except KeyError:
            raise ParseError('type tag "{}" not understood'.format(chr(tag)))
        _LOGGER.debug("new value %s", value)
        value_list.append(value)

    _LOGGER.debug("resulting list %s", value_list)
    _LOGGER.debug("] end parsing list")
    return value_list, start_index
Exemple #10
0
def parse_sclang_blob(data):
    '''Parses the blob from a SuperCollider osc message'''

    TYPE_TAG_MARKER = ord(b',')
    TYPE_TAG_START = 4
    NUM_SIZE = 4
    INT_TAG = ord(b'i')
    bytes2type = {
        ord(b'i'): lambda data: osc_types.get_int(data, 0),
        ord(b'f'): lambda data: osc_types.get_float(data, 0),
        ord(b's'): lambda data: osc_types.get_string(data, 0),
        ord(b'N'): lambda data: (None, 0),
        ord(b'I'): lambda data: (np.inf, 0),
        ord(b'T'): lambda data: (True, 0),
        ord(b'F'): lambda data: (False, 0)
    }

    def _get_aligned_pos(pos):
        return NUM_SIZE * int(np.ceil((pos) / NUM_SIZE))

    def _parse_list(data):
        logging.debug("[ start parsing list: {}".format(data))
        list_size, _ = bytes2type[INT_TAG](data)
        type_tag_offset = _get_aligned_pos(list_size + 2)
        type_tag_end = TYPE_TAG_START + type_tag_offset
        type_tag = data[TYPE_TAG_START + 1:TYPE_TAG_START + 1 + list_size]
        value_list = []
        idx = type_tag_end
        for t in type_tag:
            try:
                value, num_bytes = bytes2type[t](data[idx:])
            except KeyError:
                raise Exception('type tag "{}" not understood'.format(chr(t)))
            logging.debug("new value {}".format(value))
            value_list.append(value)
            idx += num_bytes

        logging.debug("resulting list {}".format(value_list))
        logging.debug("] end parsing list")
        return value_list, idx

    def _parse_sc_msg(data):
        logging.debug(">> parse sc msg: {}".format(data))
        msg_size, _ = bytes2type[INT_TAG](data)
        logging.debug("msg size {}".format(msg_size))
        data = data[NUM_SIZE:]

        if data[:8] == b'#bundle\x00':
            logging.debug("found bundle")
            msgs, bundle_size = _parse_bundle(data)
            return msgs, bundle_size + NUM_SIZE
        elif data[TYPE_TAG_START] == TYPE_TAG_MARKER:
            logging.debug("found list")
            value_list, list_size = _parse_list(data[:msg_size])
            return value_list, list_size + NUM_SIZE
        else:
            raise Exception("Datagram not recognized")

    bytes2type[ord(b'b')] = _parse_sc_msg

    def _parse_bundle(data):
        logging.debug("## start parsing bundle: {}".format(data))
        msgs = []
        msg_count = ord(data[8 + 3:8 + 4]) - ord("\x80")
        bundle_size = 16  # skip header
        logging.debug("msg count {}".format(msg_count))
        while msg_count > 0:
            sc_msg, msg_size = _parse_sc_msg(data[bundle_size:])
            msgs.append(sc_msg)
            bundle_size += msg_size
            msg_count -= 1
            logging.debug("msgs left {}".format(msg_count))

        bundle_size = _get_aligned_pos(bundle_size)
        logging.debug("parsed bytes {}".format(data[:bundle_size]))
        logging.debug("msgs {}".format(msgs))
        logging.debug("## end parsing bundle ")
        return msgs, bundle_size

    try:
        if len(data) > TYPE_TAG_START + 1:
            if data[TYPE_TAG_START] == TYPE_TAG_MARKER:
                return _parse_list(data)[0]
            elif data[:8] == b'#bundle\x00':
                return _parse_bundle(data)[0]
    except Exception as e:
        logging.warning('Ignoring Exception:\n{}\nreturning blob'.format(e))
    return data