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
data/lib/osc-ruby/osc_types.rb
CHANGED
@@ -1,28 +1,53 @@
|
|
1
|
-
require File.join(
|
1
|
+
require File.join(File.dirname(__FILE__), "osc_argument")
|
2
2
|
|
3
3
|
module OSC
|
4
4
|
class OSCInt32 < OSCArgument
|
5
|
-
def tag
|
6
|
-
|
5
|
+
def tag
|
6
|
+
'i'
|
7
|
+
end
|
8
|
+
|
9
|
+
def encode
|
10
|
+
[@val].pack('N').force_encoding("BINARY")
|
11
|
+
end
|
7
12
|
end
|
8
13
|
|
9
14
|
class OSCFloat32 < OSCArgument
|
10
|
-
def tag
|
11
|
-
|
15
|
+
def tag
|
16
|
+
'f'
|
17
|
+
end
|
18
|
+
|
19
|
+
def encode
|
20
|
+
[@val].pack('g').force_encoding("BINARY")
|
21
|
+
end
|
12
22
|
end
|
13
23
|
|
14
24
|
class OSCDouble64 < OSCArgument
|
15
|
-
def tag
|
16
|
-
|
25
|
+
def tag
|
26
|
+
'd'
|
27
|
+
end
|
28
|
+
|
29
|
+
def encode
|
30
|
+
[@val].pack('G').force_encoding("BINARY")
|
31
|
+
end
|
17
32
|
end
|
18
33
|
|
19
34
|
class OSCString < OSCArgument
|
20
|
-
def tag
|
21
|
-
|
35
|
+
def tag
|
36
|
+
's'
|
37
|
+
end
|
38
|
+
|
39
|
+
def encode
|
40
|
+
padding(@val.sub(/\000.*\z/, '') + "\000").force_encoding("BINARY")
|
41
|
+
end
|
22
42
|
end
|
23
43
|
|
24
44
|
class OSCBlob < OSCArgument
|
25
|
-
def tag
|
26
|
-
|
45
|
+
def tag
|
46
|
+
'b'
|
47
|
+
end
|
48
|
+
|
49
|
+
def encode
|
50
|
+
padding([@val.size].pack('N') + @val).force_encoding("BINARY")
|
51
|
+
end
|
27
52
|
end
|
28
53
|
end
|
data/lib/osc-ruby/server.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module OSC
|
2
|
-
class
|
3
|
-
def initialize(
|
2
|
+
class Server
|
3
|
+
def initialize(port)
|
4
4
|
@socket = UDPSocket.new
|
5
|
-
@socket.bind(
|
5
|
+
@socket.bind('', port)
|
6
6
|
@matchers = []
|
7
7
|
@queue = Queue.new
|
8
8
|
end
|
@@ -17,76 +17,75 @@ module OSC
|
|
17
17
|
@socket.close
|
18
18
|
end
|
19
19
|
|
20
|
-
def add_method(
|
21
|
-
matcher = AddressPattern.new(
|
20
|
+
def add_method(address_pattern, &proc)
|
21
|
+
matcher = AddressPattern.new(address_pattern)
|
22
22
|
|
23
23
|
@matchers << [matcher, proc]
|
24
24
|
end
|
25
25
|
|
26
|
-
private
|
26
|
+
private
|
27
27
|
|
28
28
|
def start_detector
|
29
29
|
begin
|
30
|
-
|
30
|
+
detector
|
31
31
|
rescue
|
32
|
-
|
32
|
+
Thread.main.raise($!)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
def start_dispatcher
|
37
37
|
Thread.fork do
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
begin
|
39
|
+
dispatcher
|
40
|
+
rescue
|
41
|
+
Thread.main.raise($!)
|
42
|
+
end
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
46
|
def dispatcher
|
47
47
|
loop do
|
48
|
-
|
49
|
-
dispatch_message(
|
48
|
+
mesg = @queue.pop
|
49
|
+
dispatch_message(mesg)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def dispatch_message(
|
54
|
-
diff = (
|
53
|
+
def dispatch_message(message)
|
54
|
+
diff = (message.time || 0) - Time.now.to_ntp
|
55
55
|
|
56
56
|
if diff <= 0
|
57
|
-
sendmesg(
|
57
|
+
sendmesg(message)
|
58
58
|
else # spawn a thread to wait until it's time
|
59
59
|
Thread.fork do
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
sleep(diff)
|
61
|
+
sendmesg(mesg)
|
62
|
+
Thread.exit
|
63
|
+
end
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
67
|
def sendmesg(mesg)
|
68
68
|
@matchers.each do |matcher, proc|
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
if matcher.match?(mesg.address)
|
70
|
+
proc.call(mesg)
|
71
|
+
end
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
75
|
def detector
|
76
76
|
loop do
|
77
|
-
|
78
|
-
|
77
|
+
osc_data, network = @socket.recvfrom(16384)
|
78
|
+
begin
|
79
79
|
ip_info = Array.new
|
80
80
|
ip_info << network[1]
|
81
81
|
ip_info.concat(network[2].split('.'))
|
82
|
-
|
83
|
-
|
82
|
+
OSCPacket.messages_from_network( osc_data, ip_info ).each do |message|
|
83
|
+
@queue.push(message)
|
84
84
|
end
|
85
85
|
|
86
|
-
|
87
|
-
|
86
|
+
rescue(EOFError)
|
87
|
+
end
|
88
88
|
end
|
89
89
|
end
|
90
|
-
|
91
90
|
end
|
92
91
|
end
|
@@ -1,56 +1,55 @@
|
|
1
1
|
class MessageBuilder
|
2
|
-
|
3
2
|
def initialize
|
4
3
|
@address = ""
|
5
4
|
@tags = []
|
6
5
|
@values = []
|
7
6
|
@time = nil
|
8
7
|
end
|
9
|
-
|
10
|
-
def with_address(
|
8
|
+
|
9
|
+
def with_address(addr)
|
11
10
|
@address = addr
|
12
11
|
self
|
13
12
|
end
|
14
|
-
|
15
|
-
def with_float(
|
16
|
-
with_arg(
|
13
|
+
|
14
|
+
def with_float(float)
|
15
|
+
with_arg("f", float)
|
17
16
|
self
|
18
17
|
end
|
19
18
|
|
20
|
-
def with_double(
|
21
|
-
with_arg(
|
19
|
+
def with_double(double)
|
20
|
+
with_arg("d", double)
|
22
21
|
self
|
23
22
|
end
|
24
|
-
|
25
|
-
def with_int(
|
26
|
-
with_arg(
|
23
|
+
|
24
|
+
def with_int(int)
|
25
|
+
with_arg("i", int)
|
27
26
|
self
|
28
27
|
end
|
29
|
-
|
30
|
-
def with_string(
|
31
|
-
with_arg(
|
28
|
+
|
29
|
+
def with_string(string)
|
30
|
+
with_arg("s", string)
|
32
31
|
self
|
33
32
|
end
|
34
|
-
|
35
|
-
def with_blob(
|
36
|
-
with_arg( "b", blob
|
33
|
+
|
34
|
+
def with_blob(blob)
|
35
|
+
with_arg( "b", blob)
|
37
36
|
self
|
38
37
|
end
|
39
|
-
|
40
|
-
def with_time(
|
38
|
+
|
39
|
+
def with_time(time)
|
41
40
|
@time = time
|
42
41
|
end
|
43
|
-
|
42
|
+
|
44
43
|
def build
|
45
|
-
message = OSC::Message.new(
|
44
|
+
message = OSC::Message.new(@address , *@values)
|
46
45
|
message.time = @time
|
47
46
|
message
|
48
47
|
end
|
49
|
-
|
50
|
-
private
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
|
49
|
+
private
|
50
|
+
|
51
|
+
def with_arg(tag, value)
|
52
|
+
@tags << tag
|
53
|
+
@values << value
|
55
54
|
end
|
56
55
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(
|
1
|
+
require File.join(File.dirname(__FILE__) , '..', 'spec_helper')
|
2
2
|
|
3
3
|
describe OSC::AddressPattern do
|
4
4
|
# it "..." do
|
@@ -13,81 +13,81 @@ describe OSC::AddressPattern do
|
|
13
13
|
# end
|
14
14
|
|
15
15
|
it "should match anything if the pattern is nil" do
|
16
|
-
ap = OSC::AddressPattern.new(
|
16
|
+
ap = OSC::AddressPattern.new(nil)
|
17
17
|
|
18
|
-
ap.match?(
|
19
|
-
ap.match?(
|
18
|
+
_(ap.match?("/some/nonsense")).must_equal(true)
|
19
|
+
_(ap.match?("/completely.different")).must_equal(true)
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should match based on a regex" do
|
23
|
-
ap = OSC::AddressPattern.new(
|
23
|
+
ap = OSC::AddressPattern.new(/hi/)
|
24
24
|
|
25
|
-
ap.match?(
|
26
|
-
ap.match?(
|
25
|
+
_(ap.match?('/hi')).must_equal(true)
|
26
|
+
_(ap.match?('/hidden')).must_equal(true)
|
27
27
|
|
28
|
-
ap.match?(
|
28
|
+
_(ap.match?('/bye')).must_equal(false)
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should return a regex if the pattern is a string" do
|
32
|
-
ap = OSC::AddressPattern.new(
|
32
|
+
ap = OSC::AddressPattern.new("/hi")
|
33
33
|
|
34
|
-
ap.match?(
|
34
|
+
_(ap.match?('/hi')).must_equal(true)
|
35
35
|
|
36
|
-
ap.match?(
|
37
|
-
ap.match?(
|
38
|
-
ap.match?(
|
39
|
-
ap.match?(
|
36
|
+
_(ap.match?(' /hi')).must_equal(false)
|
37
|
+
_(ap.match?('/ahi')).must_equal(false)
|
38
|
+
_(ap.match?('/hidden')).must_equal(false)
|
39
|
+
_(ap.match?('/bye')).must_equal(false)
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should match with question mark" do
|
43
|
-
ap = OSC::AddressPattern.new(
|
44
|
-
|
45
|
-
ap.match?(
|
46
|
-
ap.match?(
|
47
|
-
ap.match?(
|
48
|
-
ap.match?(
|
49
|
-
ap.match?(
|
50
|
-
ap.match?(
|
43
|
+
ap = OSC::AddressPattern.new("/h?l")
|
44
|
+
|
45
|
+
_(ap.match?('/hal')).must_equal(true)
|
46
|
+
_(ap.match?('/hel')).must_equal(true)
|
47
|
+
_(ap.match?('/hil')).must_equal(true)
|
48
|
+
_(ap.match?('/hol')).must_equal(true)
|
49
|
+
_(ap.match?('/hul')).must_equal(true)
|
50
|
+
_(ap.match?('/hub')).must_equal(false)
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should match with *" do
|
54
|
-
ap = OSC::AddressPattern.new(
|
54
|
+
ap = OSC::AddressPattern.new("/believ*d")
|
55
55
|
|
56
|
-
ap.match?(
|
57
|
-
ap.match?(
|
58
|
-
ap.match?(
|
59
|
-
ap.match?(
|
60
|
-
ap.match?(
|
56
|
+
_(ap.match?('/believd')).must_equal(true)
|
57
|
+
_(ap.match?('/believed')).must_equal(true)
|
58
|
+
_(ap.match?('/believeeed')).must_equal(true)
|
59
|
+
_(ap.match?('/believaeeeioud')).must_equal(true)
|
60
|
+
_(ap.match?('/believaeeeioud')).must_equal(true)
|
61
61
|
end
|
62
62
|
|
63
63
|
it "should match with []" do
|
64
|
-
ap = OSC::AddressPattern.new(
|
65
|
-
|
66
|
-
ap.match?(
|
67
|
-
ap.match?(
|
68
|
-
ap.match?(
|
69
|
-
ap.match?(
|
70
|
-
ap.match?(
|
71
|
-
ap.match?(
|
64
|
+
ap = OSC::AddressPattern.new("/believ[aeiou]d")
|
65
|
+
|
66
|
+
_(ap.match?('/believad')).must_equal(true)
|
67
|
+
_(ap.match?('/believed')).must_equal(true)
|
68
|
+
_(ap.match?('/believid')).must_equal(true)
|
69
|
+
_(ap.match?('/believod')).must_equal(true)
|
70
|
+
_(ap.match?('/believud')).must_equal(true)
|
71
|
+
_(ap.match?('/believkd')).must_equal(false)
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should match with [!]" do
|
75
|
-
ap = OSC::AddressPattern.new(
|
76
|
-
|
77
|
-
ap.match?(
|
78
|
-
ap.match?(
|
79
|
-
ap.match?(
|
80
|
-
ap.match?(
|
81
|
-
ap.match?(
|
82
|
-
ap.match?(
|
83
|
-
ap.match?(
|
75
|
+
ap = OSC::AddressPattern.new("/believ[!aeiou]d")
|
76
|
+
|
77
|
+
_(ap.match?('/believad')).must_equal(false)
|
78
|
+
_(ap.match?('/believed')).must_equal(false)
|
79
|
+
_(ap.match?('/believid')).must_equal(false)
|
80
|
+
_(ap.match?('/believod')).must_equal(false)
|
81
|
+
_(ap.match?('/believud')).must_equal(false)
|
82
|
+
_(ap.match?('/believkd')).must_equal(true)
|
83
|
+
_(ap.match?('/believzd')).must_equal(true)
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should match with {}" do
|
87
|
-
ap = OSC::AddressPattern.new(
|
87
|
+
ap = OSC::AddressPattern.new("/{hi,bye}")
|
88
88
|
|
89
|
-
ap.match?(
|
90
|
-
ap.match?(
|
91
|
-
ap.match?(
|
89
|
+
_(ap.match?('/hi')).must_equal(true)
|
90
|
+
_(ap.match?('/bye')).must_equal(true)
|
91
|
+
_(ap.match?('/greetings')).must_equal(false)
|
92
92
|
end
|
93
93
|
end
|
@@ -1,45 +1,43 @@
|
|
1
|
-
# sanity checks
|
2
1
|
require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
|
3
2
|
|
4
3
|
describe MessageBuilder do
|
5
4
|
before :each do
|
6
5
|
@builder = MessageBuilder.new
|
7
6
|
end
|
8
|
-
|
7
|
+
|
9
8
|
it "encodes just the address" do
|
10
9
|
mesg = @builder.with_address("/hi")
|
11
|
-
|
10
|
+
_(mesg.build.encode).must_equal binary_string("/hi\000,\000\000\000")
|
12
11
|
end
|
13
|
-
|
12
|
+
|
14
13
|
it "encodes single int values" do
|
15
14
|
mesg = @builder.with_address("/hi").
|
16
|
-
|
17
|
-
|
18
|
-
mesg.build.encode.must_equal binary_string("/hi\000,i\000\000\000\000\000!")
|
15
|
+
with_int(33)
|
16
|
+
_(mesg.build.encode).must_equal binary_string("/hi\000,i\000\000\000\000\000!")
|
19
17
|
end
|
20
|
-
|
18
|
+
|
21
19
|
it "encodes single string values" do
|
22
20
|
mesg = @builder.with_address("/hi").
|
23
|
-
|
24
|
-
|
25
|
-
mesg.build.encode.must_equal binary_string("/hi\000,s\000\000hello\000\000\000")
|
21
|
+
with_string("hello")
|
22
|
+
|
23
|
+
_(mesg.build.encode).must_equal binary_string("/hi\000,s\000\000hello\000\000\000")
|
26
24
|
end
|
27
|
-
|
25
|
+
|
28
26
|
it "encodes single float values" do
|
29
27
|
mesg = @builder.with_address("/hi").
|
30
|
-
|
31
|
-
|
32
|
-
mesg.build.encode.must_equal binary_string("/hi\000,f\000\000@I\017\320")
|
28
|
+
with_float(3.14159)
|
29
|
+
|
30
|
+
_(mesg.build.encode).must_equal binary_string("/hi\000,f\000\000@I\017\320")
|
33
31
|
end
|
34
|
-
|
32
|
+
|
35
33
|
it "encodes multiple floats" do
|
36
34
|
mesg = @builder.with_address("/hi").
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
mesg.build.encode.must_equal [47, 104, 105, 0, 44, 102, 102, 0, 64, 73, 15, 208, 64, 144, 0, 0].pack("C*")
|
35
|
+
with_float(3.14159).
|
36
|
+
with_float(4.5)
|
37
|
+
|
38
|
+
_(mesg.build.encode).must_equal [47, 104, 105, 0, 44, 102, 102, 0, 64, 73, 15, 208, 64, 144, 0, 0].pack("C*")
|
41
39
|
end
|
42
|
-
|
40
|
+
|
43
41
|
def binary_string(string)
|
44
42
|
string.force_encoding("BINARY")
|
45
43
|
end
|