osc-ruby 1.1.3 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|