Esempio n. 1
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 == "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 == "d":  # Timestamp.
                    val, index = osc_types.get_int(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)
Esempio n. 2
0
    def _parse_contents(self, index: int) -> Any:
        contents = []

        try:
            # An OSC Bundle Element consists of its size and its contents.
            # The size is an int32 representing the number of 8-bit bytes in the
            # contents, and will always be a multiple of 4. The contents are either
            # an OSC Message or an OSC Bundle.
            while self._dgram[index:]:
                # Get the sub content size.
                content_size, index = osc_types.get_int(self._dgram, index)
                # Get the datagram for the sub content.
                content_dgram = self._dgram[index:index + content_size]
                # Increment our position index up to the next possible content.
                index += content_size
                # Parse the content into an OSC message or bundle.
                if OscBundle.dgram_is_bundle(content_dgram):
                    contents.append(OscBundle(content_dgram))
                elif osc_message.OscMessage.dgram_is_message(content_dgram):
                    contents.append(osc_message.OscMessage(content_dgram))
                else:
                    logging.warning(
                        "Could not identify content type of dgram %s" %
                        content_dgram)
        except (osc_types.ParseError, osc_message.ParseError, IndexError) as e:
            raise ParseError("Could not parse a content datagram: %s" % e)

        return contents
Esempio n. 3
0
	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)
Esempio n. 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)
                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)
Esempio n. 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:]

      # 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)
Esempio n. 6
0
  def _parse_contents(self, index):
    contents = []

    try:
      # An OSC Bundle Element consists of its size and its contents.
      # The size is an int32 representing the number of 8-bit bytes in the
      # contents, and will always be a multiple of 4. The contents are either
      # an OSC Message or an OSC Bundle.
      while self._dgram[index:]:
        # Get the sub content size.
        content_size, index = osc_types.get_int(self._dgram, index)
        # Get the datagram for the sub content.
        content_dgram = self._dgram[index:index + content_size]
        # Increment our position index up to the next possible content.
        index += content_size
        # Parse the content into an OSC message or bundle.
        if OscBundle.dgram_is_bundle(content_dgram):
          contents.append(OscBundle(content_dgram))
        elif osc_message.OscMessage.dgram_is_message(content_dgram):
          contents.append(osc_message.OscMessage(content_dgram))
        else:
          logging.warning(
              "Could not identify content type of dgram %s" % content_dgram)
    except (osc_types.ParseError, osc_message.ParseError, IndexError) as e:
      raise ParseError("Could not parse a content datagram: %s" % e)

    return contents
Esempio n. 7
0
    def load_file(
            cls, path: Union[str, bytes,
                             os.PathLike]) -> Dict[float, List[OSCMessage]]:
        """Load a OSC file into a dict.

        Parameters
        ----------
        path : Union[str, bytes, os.PathLike]
            Path of the OSC file.

        Returns
        -------
        Dict[float, List[OSCMessage]]
            dict with time tag as keys and lists of OSCMessages as values.
        """
        with open(path, "rb") as file:
            dgram = file.read()
        index = 0
        builder = OscBundleBuilder(0)
        while dgram[index:]:
            size, index = osc_types.get_int(dgram, index)
            builder.add_content(OscBundle(dgram[index:index + size]))
            index += size
        #  TODO rework that times don't get smashed
        warnings.warn(
            "This method currently destroys the time tag if they happend in the past."
        )
        return convert_to_sc3nb_osc(builder.build()).messages()
Esempio n. 8
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)
Esempio n. 9
0
File: sc.py Progetto: dreinsch/sc3nb
    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
Esempio n. 10
0
    def test_get_integer(self):
        cases = {
            b"\x00\x00\x00\x00": (0, 4),
            b"\x00\x00\x00\x01": (1, 4),
            b"\x00\x00\x00\x02": (2, 4),
            b"\x00\x00\x00\x03": (3, 4),
            b"\x00\x00\x01\x00": (256, 4),
            b"\x00\x01\x00\x00": (65536, 4),
            b"\x01\x00\x00\x00": (16777216, 4),
            b"\x00\x00\x00\x01GARBAGE": (1, 4),
        }

        for dgram, expected in cases.items():
            self.assertEqual(expected, osc_types.get_int(dgram, 0))
Esempio n. 11
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
Esempio n. 12
0
def _parse_osc_bundle_element(
        dgram: bytes,
        start_index: int) -> Tuple[Union[Sequence[Any], bytes], int]:
    """Parse an element from an OSC bundle.

    The element needs to be either an OSC bundle or a list

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

    Returns
    -------
    Tuple[Union[Sequence[Any], bytes], int]
        parsed content of the bundle element, starting index + number of consumed bytes

    Raises
    ------
    ParseError
        If the datagram is invalid.
    """
    elem_size, start_index = osc_types.get_int(dgram, start_index)
    _LOGGER.debug(
        ">> parse OSC bundle element (size: %d): %s ",
        elem_size,
        dgram[start_index:start_index + elem_size],
    )

    if OscBundle.dgram_is_bundle(dgram[start_index:start_index + elem_size]):
        _LOGGER.debug("found bundle")
        msgs, start_index = _parse_bundle(dgram, start_index)
        return msgs, start_index

    if dgram[start_index + TYPE_TAG_INDEX] == TYPE_TAG_MARKER:
        _LOGGER.debug("found list")
        value_list, start_index = _parse_list(dgram, start_index)
        return value_list, start_index

    if dgram[start_index:start_index + 4] == SYNTH_DEF_MARKER:
        _LOGGER.debug("found SynthDef blob")
        synth_def = dgram[start_index:start_index + elem_size]
        start_index = start_index + elem_size
        return synth_def, start_index

    raise ParseError("Datagram not recognized")
Esempio n. 13
0
  def test_get_integer(self):
    cases = {
        b"\x00\x00\x00\x00": (0, 4),
        b"\x00\x00\x00\x01": (1, 4),
        b"\x00\x00\x00\x02": (2, 4),
        b"\x00\x00\x00\x03": (3, 4),

        b"\x00\x00\x01\x00": (256, 4),
        b"\x00\x01\x00\x00": (65536, 4),
        b"\x01\x00\x00\x00": (16777216, 4),

        b"\x00\x00\x00\x01GARBAGE": (1, 4),
    }

    for dgram, expected in cases.items():
        self.assertEqual(
            expected, osc_types.get_int(dgram, 0))
Esempio n. 14
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