osc-ruby 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/VERSION +1 -1
- data/lib/osc-ruby.rb +0 -2
- data/lib/osc-ruby/address_pattern.rb +34 -32
- data/lib/osc-ruby/bundle.rb +14 -12
- data/lib/osc-ruby/em_server.rb +22 -22
- data/lib/osc-ruby/message.rb +18 -15
- data/lib/osc-ruby/network_packet.rb +14 -13
- data/lib/osc-ruby/osc_argument.rb +15 -5
- data/lib/osc-ruby/osc_packet.rb +26 -27
- data/lib/osc-ruby/osc_types.rb +36 -11
- data/lib/osc-ruby/server.rb +31 -32
- data/spec/builders/message_builder.rb +25 -26
- data/spec/unit/address_pattern_spec.rb +49 -49
- data/spec/unit/message_builder_spec.rb +19 -21
- data/spec/unit/message_bundle_spec.rb +1 -1
- data/spec/unit/message_spec.rb +27 -27
- data/spec/unit/network_packet_spec.rb +18 -18
- data/spec/unit/osc_argument_spec.rb +2 -2
- data/spec/unit/osc_complex_packets_spec.rb +16 -16
- data/spec/unit/osc_packet_unknown_type_spec.rb +3 -8
- data/spec/unit/osc_simple_packets_spec.rb +37 -43
- data/spec/unit/osc_types_spec.rb +6 -6
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6c72442242b273fbc11e6cb48c2c4b4b906a404f
|
4
|
+
data.tar.gz: 43b65407de6f406116439cd01439a3b14b0c3d2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fc3f71473e08423d0fff5cf1baad0cf18b8b7c447946e23448e0a68b3b46b767917c1df9fd203820b846b287b8f2ff70084a8b50e25c022544c835be21c2479
|
7
|
+
data.tar.gz: 050b7b71dbda1a73f3762d5f310473db311e0862fc808bf2643d209679c9caa9f5f497810f54ce86aca1d5e614a71490f781f343a350e5acda85bfe4b973d9ce
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.
|
1
|
+
1.1.4
|
data/lib/osc-ruby.rb
CHANGED
@@ -1,55 +1,57 @@
|
|
1
1
|
module OSC
|
2
2
|
class AddressPattern
|
3
|
-
def initialize(
|
3
|
+
def initialize(pattern)
|
4
4
|
@pattern = pattern
|
5
5
|
|
6
6
|
generate_regex_from_pattern
|
7
7
|
end
|
8
8
|
|
9
|
-
def match?(
|
10
|
-
!!(@re.nil? || @re.match(
|
9
|
+
def match?(address)
|
10
|
+
!!(@re.nil? || @re.match(address))
|
11
11
|
end
|
12
12
|
|
13
|
-
private
|
13
|
+
private
|
14
|
+
|
14
15
|
def generate_regex_from_pattern
|
15
16
|
case @pattern
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
when nil
|
18
|
+
@re = @pattern
|
19
|
+
when Regexp
|
20
|
+
@re = @pattern
|
21
|
+
when String
|
22
|
+
# i'm unsure what this does
|
23
|
+
# @pattern.gsub!(/[.^(|)]/, '\\1')
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
# handles osc single char wildcard matching
|
26
|
+
@pattern.gsub!(/\?/, '[^/]')
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
# handles ** - used in creating osc routers
|
29
|
+
# TODO: turns out the OSC 1.1 spec says that we shoudl use "//"
|
30
|
+
# this will be implemented in the next major release of this gem
|
31
|
+
#@pattern.gsub!(/\*\*/, '.*' )
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
+
# handles osc * - 0 or more matching
|
34
|
+
@pattern.gsub!(/\*[^\*]/, '[^/]*')
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
+
# handles [!] matching
|
37
|
+
@pattern.gsub!(/\[!/, '[^')
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
# handles {} matching
|
40
|
+
@pattern.gsub!(/\{/, '(')
|
41
|
+
@pattern.gsub!(/,/, '|')
|
42
|
+
@pattern.gsub!(/\}/, ')')
|
41
43
|
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
+
# keeps from matching before the begining of the pattern
|
46
|
+
@pattern.gsub!(/\A/, '\A')
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
# keeps from matching beyond the end,
|
49
|
+
# eg. pattern /hi does not match /hidden
|
50
|
+
@pattern.gsub!(/\z/, '\z')
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
@re = Regexp.new(@pattern)
|
53
|
+
else
|
54
|
+
raise(ArgumentError, 'invalid pattern')
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
data/lib/osc-ruby/bundle.rb
CHANGED
@@ -15,26 +15,28 @@ module OSC
|
|
15
15
|
end.join
|
16
16
|
end
|
17
17
|
|
18
|
-
def to_a
|
18
|
+
def to_a
|
19
|
+
@args.collect{|x| x.to_a}
|
20
|
+
end
|
19
21
|
|
20
|
-
|
22
|
+
private
|
21
23
|
|
22
24
|
def encode_timetag(t)
|
23
25
|
case t
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
when nil # immediately
|
27
|
+
t1 = 0
|
28
|
+
t2 = 1
|
29
|
+
when Numeric
|
30
|
+
t1, t2 = construct_timetag(t)
|
31
|
+
when Time
|
32
|
+
t1, t2 = construct_timetag(t.to_ntp)
|
33
|
+
else
|
34
|
+
raise(ArgumentError, 'invalid time')
|
33
35
|
end
|
34
36
|
[t1, t2].pack('N2')
|
35
37
|
end
|
36
38
|
|
37
|
-
def construct_timetag(
|
39
|
+
def construct_timetag(time)
|
38
40
|
t1, fr = time.divmod(1)
|
39
41
|
t2 = (fr * (2**32)).to_i
|
40
42
|
|
data/lib/osc-ruby/em_server.rb
CHANGED
@@ -4,42 +4,48 @@ module OSC
|
|
4
4
|
Channel = EM::Channel.new
|
5
5
|
|
6
6
|
class Connection < EventMachine::Connection
|
7
|
-
def receive_data
|
8
|
-
|
9
|
-
|
7
|
+
def receive_data(data)
|
8
|
+
ip_info = get_peername[2,6].unpack("nC4")
|
9
|
+
Channel << OSC::OSCPacket.messages_from_network(data, ip_info)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
class EMServer
|
14
14
|
|
15
|
-
def initialize(
|
15
|
+
def initialize(port = 3333)
|
16
16
|
@port = port
|
17
17
|
setup_dispatcher
|
18
18
|
@tuples = []
|
19
19
|
end
|
20
20
|
|
21
21
|
def run
|
22
|
-
EM
|
22
|
+
EM.error_handler{ |e|
|
23
|
+
Thread.main.raise e
|
24
|
+
}
|
25
|
+
|
26
|
+
EM.run do
|
27
|
+
EM::open_datagram_socket "0.0.0.0", @port, Connection
|
28
|
+
end
|
23
29
|
end
|
24
30
|
|
25
31
|
def add_method(address_pattern, &proc)
|
26
|
-
matcher = AddressPattern.new(
|
32
|
+
matcher = AddressPattern.new(address_pattern)
|
27
33
|
|
28
34
|
@tuples << [matcher, proc]
|
29
35
|
end
|
30
36
|
|
31
|
-
|
37
|
+
private
|
32
38
|
def setup_dispatcher
|
33
|
-
Channel.subscribe do
|
39
|
+
Channel.subscribe do |messages|
|
34
40
|
messages.each do |message|
|
35
|
-
diff = (
|
41
|
+
diff = (message.time || 0) - Time.now.to_ntp
|
36
42
|
|
37
|
-
if diff <=
|
38
|
-
sendmesg(
|
43
|
+
if diff <= 0
|
44
|
+
sendmesg(message)
|
39
45
|
else
|
40
|
-
EM.defer
|
41
|
-
sleep(
|
42
|
-
sendmesg(
|
46
|
+
EM.defer do
|
47
|
+
sleep(diff)
|
48
|
+
sendmesg(message)
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
@@ -48,16 +54,10 @@ module OSC
|
|
48
54
|
|
49
55
|
def sendmesg(mesg)
|
50
56
|
@tuples.each do |matcher, obj|
|
51
|
-
if matcher.match?(
|
52
|
-
obj.call(
|
57
|
+
if matcher.match?(mesg.address)
|
58
|
+
obj.call(mesg)
|
53
59
|
end
|
54
60
|
end
|
55
61
|
end
|
56
62
|
end
|
57
63
|
end
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
data/lib/osc-ruby/message.rb
CHANGED
@@ -5,39 +5,42 @@ module OSC
|
|
5
5
|
attr_accessor :ip_address
|
6
6
|
attr_accessor :ip_port
|
7
7
|
|
8
|
-
def self.new_with_time(
|
9
|
-
message = new(
|
8
|
+
def self.new_with_time(address, time, tags=nil, *args)
|
9
|
+
message = new(address, tags, *args)
|
10
10
|
message.time = time
|
11
11
|
message
|
12
12
|
end
|
13
13
|
|
14
|
-
def initialize(
|
14
|
+
def initialize(address, *args)
|
15
15
|
@address = address
|
16
16
|
@args = []
|
17
17
|
|
18
18
|
args.each do |arg|
|
19
19
|
case arg
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
when Integer; @args << OSCInt32.new(arg)
|
21
|
+
when Float; @args << OSCFloat32.new(arg)
|
22
|
+
when String; @args << OSCString.new(arg)
|
23
|
+
when OSCArgument; @args << arg
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def tags
|
28
|
+
def tags
|
29
|
+
@args.collect{|x| x.tag}.join
|
30
|
+
end
|
29
31
|
|
30
32
|
def encode
|
31
|
-
s = OSCString.new(
|
32
|
-
s << OSCString.new(
|
33
|
+
s = OSCString.new(@address).encode
|
34
|
+
s << OSCString.new(',' + tags).encode
|
33
35
|
s << @args.collect{|x| x.encode}.join
|
34
36
|
end
|
35
37
|
|
36
|
-
def to_a
|
38
|
+
def to_a
|
39
|
+
@args.collect{|x| x.val}
|
40
|
+
end
|
37
41
|
|
38
|
-
def ==(
|
39
|
-
@address == other.address &&
|
40
|
-
to_a == other.to_a
|
42
|
+
def ==(other)
|
43
|
+
@address == other.address && to_a == other.to_a
|
41
44
|
end
|
42
45
|
end
|
43
|
-
end
|
46
|
+
end
|
@@ -1,18 +1,19 @@
|
|
1
1
|
module OSC
|
2
2
|
class NetworkPacket
|
3
3
|
def initialize(str)
|
4
|
-
@str
|
4
|
+
@str = str.force_encoding("BINARY")
|
5
|
+
@index = 0
|
5
6
|
end
|
6
7
|
|
7
8
|
def to_s
|
8
9
|
@str
|
9
10
|
end
|
10
11
|
|
11
|
-
def rem
|
12
|
+
def rem
|
12
13
|
@str.length - @index
|
13
14
|
end
|
14
15
|
|
15
|
-
def eof?
|
16
|
+
def eof?
|
16
17
|
rem <= 0
|
17
18
|
end
|
18
19
|
|
@@ -20,22 +21,22 @@ module OSC
|
|
20
21
|
@index += n
|
21
22
|
end
|
22
23
|
|
23
|
-
def skip_padding
|
24
|
+
def skip_padding
|
24
25
|
skip((4 - (@index % 4)) % 4)
|
25
26
|
end
|
26
27
|
|
27
28
|
def getn(n)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
raise(EOFError) if rem < n
|
30
|
+
s = @str[@index, n]
|
31
|
+
skip(n)
|
32
|
+
s
|
32
33
|
end
|
33
34
|
|
34
35
|
def getc
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
raise(EOFError) if rem < 1
|
37
|
+
c = @str[@index]
|
38
|
+
skip(1)
|
39
|
+
c
|
39
40
|
end
|
40
41
|
end
|
41
|
-
end
|
42
|
+
end
|
@@ -1,14 +1,24 @@
|
|
1
1
|
module OSC
|
2
2
|
class OSCArgument
|
3
|
-
def initialize(val)
|
3
|
+
def initialize(val)
|
4
|
+
@val = val
|
5
|
+
end
|
4
6
|
|
5
7
|
attr_accessor :val
|
6
8
|
|
7
|
-
def to_i()
|
8
|
-
|
9
|
-
|
9
|
+
def to_i()
|
10
|
+
@val.to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_f()
|
14
|
+
@val.to_f
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s()
|
18
|
+
@val.to_s
|
19
|
+
end
|
10
20
|
|
11
|
-
|
21
|
+
private
|
12
22
|
def padding(s)
|
13
23
|
s + ("\000" * ((4 - (s.size % 4)) % 4))
|
14
24
|
end
|
data/lib/osc-ruby/osc_packet.rb
CHANGED
@@ -1,21 +1,20 @@
|
|
1
|
-
require File.join(
|
1
|
+
require File.join(File.dirname( __FILE__ ), 'network_packet')
|
2
2
|
require 'ostruct'
|
3
3
|
|
4
4
|
module OSC
|
5
5
|
class UnknownType < StandardError; end
|
6
6
|
|
7
7
|
class OSCPacket
|
8
|
-
|
9
|
-
def self.messages_from_network( string, ip_info=nil )
|
8
|
+
def self.messages_from_network(string, ip_info=nil)
|
10
9
|
messages = []
|
11
|
-
osc = new(
|
10
|
+
osc = new(string)
|
12
11
|
|
13
12
|
if osc.bundle?
|
14
|
-
osc.get_string
|
13
|
+
osc.get_string
|
15
14
|
time = osc.get_timestamp
|
16
15
|
|
17
|
-
osc.get_bundle_messages.each do |
|
18
|
-
msg = decode_simple_message(
|
16
|
+
osc.get_bundle_messages.each do |message|
|
17
|
+
msg = decode_simple_message(time, OSCPacket.new(message))
|
19
18
|
if ip_info
|
20
19
|
# Append info for the ip address
|
21
20
|
msg.ip_port = ip_info.shift
|
@@ -25,11 +24,11 @@ module OSC
|
|
25
24
|
end
|
26
25
|
|
27
26
|
else
|
28
|
-
msg = decode_simple_message(
|
27
|
+
msg = decode_simple_message(time, osc)
|
29
28
|
if ip_info
|
30
29
|
# Append info for the ip address
|
31
|
-
|
32
|
-
|
30
|
+
msg.ip_port = ip_info.shift
|
31
|
+
msg.ip_address = ip_info.join(".")
|
33
32
|
end
|
34
33
|
messages << msg
|
35
34
|
end
|
@@ -37,22 +36,23 @@ module OSC
|
|
37
36
|
return messages
|
38
37
|
end
|
39
38
|
|
40
|
-
def self.decode_simple_message(
|
39
|
+
def self.decode_simple_message(time, osc_packet)
|
41
40
|
address = osc_packet.get_string
|
42
41
|
args = osc_packet.get_arguments
|
43
42
|
|
44
|
-
Message.new_with_time(address, time, nil, *args
|
43
|
+
Message.new_with_time(address, time, nil, *args)
|
45
44
|
end
|
46
45
|
|
47
|
-
def initialize(
|
48
|
-
@packet = NetworkPacket.new(
|
46
|
+
def initialize(string)
|
47
|
+
@packet = NetworkPacket.new(string)
|
49
48
|
|
50
|
-
@types = {
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
@types = {
|
50
|
+
"i" => lambda{OSCInt32.new(get_int32)},
|
51
|
+
"f" => lambda{ OSCFloat32.new(get_float32)},
|
52
|
+
"d" => lambda{ OSCDouble64.new(get_double64)},
|
53
|
+
"s" => lambda{ OSCString.new(get_string)},
|
54
|
+
"b" => lambda{ OSCBlob.new(get_blob)}
|
55
|
+
}
|
56
56
|
end
|
57
57
|
|
58
58
|
def get_bundle_messages
|
@@ -67,8 +67,8 @@ module OSC
|
|
67
67
|
|
68
68
|
def get_string
|
69
69
|
result = ''
|
70
|
-
until (c = @packet.getc) == string_delemeter
|
71
|
-
|
70
|
+
until ((c = @packet.getc) == string_delemeter)
|
71
|
+
result << c
|
72
72
|
end
|
73
73
|
@packet.skip_padding
|
74
74
|
result
|
@@ -90,14 +90,13 @@ module OSC
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def get_arguments
|
93
|
-
if @packet.getc == ?,
|
94
|
-
|
93
|
+
if (@packet.getc == ?,)
|
95
94
|
tags = get_string
|
96
95
|
args = []
|
97
96
|
|
98
|
-
tags.scan(/./) do |
|
97
|
+
tags.scan(/./) do |tag|
|
99
98
|
type_handler = @types[tag]
|
100
|
-
raise(
|
99
|
+
raise(UnknownType, "Unknown OSC type: #{tag}") unless type_handler
|
101
100
|
args << type_handler.call
|
102
101
|
end
|
103
102
|
args
|
@@ -135,7 +134,7 @@ module OSC
|
|
135
134
|
end
|
136
135
|
|
137
136
|
def string_delemeter
|
138
|
-
|
137
|
+
"\x00"
|
139
138
|
end
|
140
139
|
end
|
141
140
|
end
|