Module: Webmidi::Network::OSC::Encoder

Defined in:
lib/webmidi/network/osc.rb

Class Method Summary collapse

Class Method Details

.decode_message(data) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/webmidi/network/osc.rb', line 66

def decode_message(data)
  address, offset = decode_string(data, 0)
  type_tag, offset = decode_string(data, offset)
  raise InvalidMessageError, "OSC type tag must start with comma" unless type_tag.start_with?(",")

  type_tag = type_tag[1..]

  args = []
  type_tag.each_char do |t|
    case t
    when "i"
      ensure_available!(data, offset, 4)
      args << data[offset, 4].unpack1("N")
      offset += 4
    when "f"
      ensure_available!(data, offset, 4)
      args << data[offset, 4].unpack1("g")
      offset += 4
    when "s"
      str, offset = decode_string(data, offset)
      args << str
    else
      raise InvalidMessageError, "Unsupported OSC argument type: #{t.inspect}"
    end
  end

  [address, args]
end

.decode_string(data, offset) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/webmidi/network/osc.rb', line 95

def decode_string(data, offset)
  raise InvalidMessageError, "OSC string offset out of bounds" if offset >= data.bytesize

  null_pos = data.index("\0", offset)
  raise InvalidMessageError, "OSC string missing null terminator" unless null_pos

  str = data[offset...null_pos]
  new_offset = null_pos + 1
  new_offset += 1 until (new_offset % 4).zero?
  raise InvalidMessageError, "OSC string padding exceeds packet length" if new_offset > data.bytesize

  [str, new_offset]
end

.encode_message(address, *args) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/webmidi/network/osc.rb', line 38

def encode_message(address, *args)
  data = encode_string(address)
  type_tag = ","
  args_data = String.new(encoding: Encoding::ASCII_8BIT)

  args.each do |arg|
    case arg
    when Integer
      type_tag += "i"
      args_data += [arg].pack("N")
    when Float
      type_tag += "f"
      args_data += [arg].pack("g")
    when String
      type_tag += "s"
      args_data += encode_string(arg)
    end
  end

  data + encode_string(type_tag) + args_data
end

.encode_string(str) ⇒ Object



60
61
62
63
64
# File 'lib/webmidi/network/osc.rb', line 60

def encode_string(str)
  padded = str + "\0"
  padded += "\0" until (padded.bytesize % 4).zero?
  padded.b
end