ruby-osc 0.3.4 → 0.4.1
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 +7 -0
- data/README.rdoc +25 -25
- data/examples/localtest.rb +20 -20
- data/lib/ruby-osc.rb +20 -17
- data/lib/ruby-osc/bundle.rb +7 -6
- data/lib/ruby-osc/client.rb +15 -10
- data/lib/ruby-osc/message.rb +42 -27
- data/lib/ruby-osc/server.rb +4 -5
- data/lib/ruby-osc/version.rb +2 -1
- data/spec/bundle_spec.rb +13 -12
- data/spec/message_spec.rb +54 -35
- data/spec/server_spec.rb +1 -0
- data/spec/spec_helper.rb +2 -2
- data/streamscanner_benchmark.rb +37 -0
- metadata +29 -23
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c7a3ed90d79d95eb44be4341b5e0e3cd13b19826
|
4
|
+
data.tar.gz: 860511677129f64f5de77c761c6adce36accad05
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5508fc05070baa6616cf7494e7a020c313dbfdf5e870e7db58c45e0d7c80cd3f89b054cec32f5bee0bb78615c232c39e7c38bcd8b2f5a53a09471178a8a1efc6
|
7
|
+
data.tar.gz: 3373a2777db15a1c6e4fe73ca7bacc0808ba8fba2ad66653bcd2c46b7e0e687a7f4a4146a9129ffc7c28b493bbe28701b7fe1dea054bf6230e67e0afd904e921
|
data/README.rdoc
CHANGED
@@ -13,32 +13,32 @@ Concise OSC implementation for Ruby
|
|
13
13
|
require 'rubygems'
|
14
14
|
require 'ruby-osc'
|
15
15
|
|
16
|
-
include
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
exit
|
16
|
+
include OSC
|
17
|
+
|
18
|
+
OSC.run do
|
19
|
+
server = Server.new 9090
|
20
|
+
client = Client.new 9090
|
21
|
+
|
22
|
+
server.add_pattern /.*/ do |*args| # this will match any address
|
23
|
+
p "/.*/: #{ args.join(', ') }"
|
24
|
+
end
|
25
|
+
|
26
|
+
server.add_pattern %r{foo/.*} do |*args| # this will match any /foo node
|
27
|
+
p "%r{foo/.*}: #{ args.join(', ') }"
|
28
|
+
end
|
29
|
+
|
30
|
+
server.add_pattern "/foo/bar" do |*args| # this will just match /foo/bar address
|
31
|
+
p "'/foo/bar': #{ args.join(', ') }"
|
32
|
+
end
|
33
|
+
|
34
|
+
server.add_pattern "/exit" do |*args| # this will just match /exit address
|
35
|
+
exit
|
36
|
+
end
|
37
|
+
|
38
|
+
client.send Message.new('/foo/bar', 1, 1.2, 'a string')
|
39
|
+
client.send Message.new('/foo/bar/zar', 1, 1.2, 'a string')
|
40
|
+
client.send Bundle.new(Time.now + 2, Message.new('/exit'))
|
35
41
|
end
|
36
|
-
|
37
|
-
client.send Message.new('/foo/bar', 1, 1.2, 'a string')
|
38
|
-
client.send Message.new('/foo/bar/zar', 1, 1.2, 'a string')
|
39
|
-
client.send Bundle.new(Time.now + 2, Message.new('/exit'))
|
40
|
-
|
41
|
-
OSC::Thread.join
|
42
42
|
|
43
43
|
== REQUIREMENTS:
|
44
44
|
|
data/examples/localtest.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
# require "#{ File.dirname __FILE__ }/../lib/ruby-osc"
|
3
2
|
require 'ruby-osc'
|
4
3
|
|
5
|
-
include
|
4
|
+
include OSC
|
6
5
|
|
7
|
-
|
8
|
-
|
6
|
+
OSC.run do
|
7
|
+
server = Server.new 9090
|
8
|
+
client = Client.new 9090
|
9
9
|
|
10
|
-
server.add_pattern /.*/ do |*args| # this will match any address
|
11
|
-
|
12
|
-
end
|
10
|
+
server.add_pattern /.*/ do |*args| # this will match any address
|
11
|
+
p "/.*/: #{ args.join(', ') }"
|
12
|
+
end
|
13
13
|
|
14
|
-
server.add_pattern %r{foo/.*} do |*args| # this will match any /foo node
|
15
|
-
|
16
|
-
end
|
14
|
+
server.add_pattern %r{foo/.*} do |*args| # this will match any /foo node
|
15
|
+
p "%r{foo/.*}: #{ args.join(', ') }"
|
16
|
+
end
|
17
17
|
|
18
|
-
server.add_pattern "/foo/bar" do |*args| # this will just match /foo/bar address
|
19
|
-
|
20
|
-
end
|
18
|
+
server.add_pattern "/foo/bar" do |*args| # this will just match /foo/bar address
|
19
|
+
p "'/foo/bar': #{ args.join(', ') }"
|
20
|
+
end
|
21
21
|
|
22
|
-
server.add_pattern "/exit" do |*args| # this will just match /exit address
|
23
|
-
|
24
|
-
end
|
22
|
+
server.add_pattern "/exit" do |*args| # this will just match /exit address
|
23
|
+
exit
|
24
|
+
end
|
25
25
|
|
26
|
-
client.send Message.new('/foo/bar', 1, 1.2, 'a string')
|
27
|
-
client.send Message.new('/foo/bar/zar', 1, 1.2, 'a string')
|
28
|
-
client.send Bundle.new(Time.now + 2, Message.new('/exit'))
|
29
26
|
|
30
|
-
|
27
|
+
client.send Message.new('/foo/bar', 1, 1.2, 'a string')
|
28
|
+
client.send Message.new('/foo/bar/zar', 1, 1.2, 'a string')
|
29
|
+
client.send Bundle.new(Time.now + 2, Message.new('/exit'))
|
30
|
+
end
|
data/lib/ruby-osc.rb
CHANGED
@@ -4,6 +4,9 @@ require 'socket' # Strange side effects with eventmachine udp client and SuperCo
|
|
4
4
|
require 'strscan'
|
5
5
|
require 'thread'
|
6
6
|
|
7
|
+
$:.unshift( File.join( File.dirname( __FILE__), '..', 'lib' ) )
|
8
|
+
|
9
|
+
# encoding: UTF-8
|
7
10
|
require 'ruby-osc/message'
|
8
11
|
require 'ruby-osc/bundle'
|
9
12
|
require 'ruby-osc/server'
|
@@ -11,24 +14,16 @@ require 'ruby-osc/client'
|
|
11
14
|
require "ruby-osc/version"
|
12
15
|
|
13
16
|
module OSC
|
14
|
-
Thread = EM.reactor_running? ? nil : Thread.new {
|
15
|
-
EM.run do
|
16
|
-
EM.error_handler { |e| puts e }
|
17
|
-
EM.set_quantum 5
|
18
|
-
end
|
19
|
-
}
|
20
|
-
Thread.run if RUBY_VERSION.to_f >= 1.9
|
21
|
-
|
22
17
|
class DecodeError < StandardError; end
|
23
|
-
|
18
|
+
|
24
19
|
class Blob < String; end
|
25
|
-
|
20
|
+
|
26
21
|
module OSCArgument
|
27
22
|
def to_osc_type
|
28
23
|
raise NotImplementedError, "#to_osc_type method should be implemented for #{ self.class }"
|
29
24
|
end
|
30
25
|
end
|
31
|
-
|
26
|
+
|
32
27
|
def self.coerce_argument arg
|
33
28
|
case arg
|
34
29
|
when OSCArgument then arg.to_osc_type
|
@@ -36,21 +31,29 @@ module OSC
|
|
36
31
|
when String, Float, Fixnum, Blob, String then arg # Pure osc 1.0 specification
|
37
32
|
else raise(TypeError, "#{ arg.inspect } is not a valid Message argument") end
|
38
33
|
end
|
39
|
-
|
34
|
+
|
40
35
|
def self.decode str #:nodoc:
|
41
36
|
str.match(/^#bundle/) ? Bundle.decode(str) : Message.decode(str)
|
42
37
|
end
|
43
|
-
|
38
|
+
|
44
39
|
def self.padding_size size
|
45
|
-
(4 - (size) % 4) % 4
|
40
|
+
(4 - (size) % 4) % 4
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.run
|
44
|
+
EM.run do
|
45
|
+
EM.error_handler { |e| puts e }
|
46
|
+
EM.set_quantum 5
|
47
|
+
yield
|
48
|
+
end
|
46
49
|
end
|
47
|
-
|
50
|
+
|
48
51
|
def self.encoding_directive obj #:nodoc:
|
49
52
|
case obj
|
50
53
|
when Float then [obj, 'f', 'g']
|
51
54
|
when Fixnum then [obj, 'i', 'N']
|
52
|
-
when Blob then [[obj.
|
53
|
-
when String then [obj, 's', "Z*x#{ padding_size obj.
|
55
|
+
when Blob then [[obj.bytesize, obj], 'b', "Na*x#{ padding_size obj.bytesize + 4 }"]
|
56
|
+
when String then [obj, 's', "Z*x#{ padding_size obj.bytesize + 1 }"]
|
54
57
|
when Time
|
55
58
|
t1, fr = (obj.to_f + 2208988800).divmod(1)
|
56
59
|
t2 = (fr * (2**32)).to_i
|
data/lib/ruby-osc/bundle.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module OSC
|
2
3
|
class Bundle < Array
|
3
4
|
attr_accessor :timetag
|
@@ -15,7 +16,7 @@ module OSC
|
|
15
16
|
time, tag, dir = OSC.encoding_directive @timetag
|
16
17
|
time.pack dir
|
17
18
|
else "\000\000\000\000\000\000\000\001" end
|
18
|
-
|
19
|
+
|
19
20
|
"#bundle\000#{ timetag }" + collect do |x|
|
20
21
|
x = x.encode
|
21
22
|
[x.size].pack('N') + x
|
@@ -25,26 +26,26 @@ module OSC
|
|
25
26
|
def self.decode string
|
26
27
|
string.sub! /^#bundle\000/, ''
|
27
28
|
t1, t2, content_str = string.unpack('N2a*')
|
28
|
-
|
29
|
+
|
29
30
|
timetag = t1 == 0 && t2 == 1 ? nil : Time.at(t1 + t2 / (2**32.0) - 2_208_988_800)
|
30
31
|
scanner = StringScanner.new content_str
|
31
32
|
args = []
|
32
|
-
|
33
|
+
|
33
34
|
until scanner.eos?
|
34
35
|
size = scanner.scan(/.{4}/).unpack('N').first
|
35
36
|
arg_str = scanner.scan(/.{#{ size }}/nm) rescue raise(DecodeError, "An error occured while trying to decode bad formatted osc bundle")
|
36
37
|
args << OSC.decode(arg_str)
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
new timetag, *args
|
40
41
|
end
|
41
|
-
|
42
|
+
|
42
43
|
def == other
|
43
44
|
self.class == other.class and self.timetag == other.timetag and self.to_a == other.to_a
|
44
45
|
end
|
45
46
|
|
46
47
|
def to_a; Array.new self; end
|
47
|
-
|
48
|
+
|
48
49
|
def to_s
|
49
50
|
"OSC::Bundle(#{ self.join(', ') })"
|
50
51
|
end
|
data/lib/ruby-osc/client.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'socket' # Strange side effects with eventmachine udp client and SuperCollider
|
3
|
+
|
1
4
|
# From the Funaba osc gem:
|
2
5
|
module OSC
|
3
6
|
class Client
|
4
|
-
|
5
|
-
def initialize port, host = '
|
7
|
+
|
8
|
+
def initialize port, host = '127.0.0.1'
|
6
9
|
@socket = UDPSocket.new
|
10
|
+
@socket = UDPSocket.open
|
11
|
+
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
|
7
12
|
@socket.connect host, port
|
8
13
|
end
|
9
|
-
|
14
|
+
|
10
15
|
def send mesg, *args
|
11
16
|
@socket.send mesg.encode, 0
|
12
17
|
end
|
@@ -15,25 +20,25 @@ end
|
|
15
20
|
|
16
21
|
# module OSC
|
17
22
|
# class Client
|
18
|
-
#
|
23
|
+
#
|
19
24
|
# def initialize port, address = 'localhost'
|
20
25
|
# @address, @port = address, port
|
21
26
|
# run
|
22
27
|
# end
|
23
|
-
#
|
28
|
+
#
|
24
29
|
# def run
|
25
30
|
# @connection = EventMachine.open_datagram_socket 'localhost', 0, Connection
|
26
31
|
# end
|
27
|
-
#
|
32
|
+
#
|
28
33
|
# def stop
|
29
34
|
# @connection.close_connection if @connection
|
30
35
|
# end
|
31
|
-
#
|
36
|
+
#
|
32
37
|
# def send item
|
33
|
-
# @connection.send_datagram item.encode, @address, @port
|
38
|
+
# @connection.send_datagram item.encode, @address, @port
|
34
39
|
# end
|
35
|
-
#
|
40
|
+
#
|
36
41
|
# class Connection < EventMachine::Connection #:nodoc:
|
37
42
|
# end
|
38
43
|
# end
|
39
|
-
# end
|
44
|
+
# end
|
data/lib/ruby-osc/message.rb
CHANGED
@@ -31,36 +31,51 @@ module OSC
|
|
31
31
|
|
32
32
|
def self.decode string
|
33
33
|
scanner = StringScanner.new string
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
34
|
+
msg = self.decode_message scanner
|
35
|
+
raise DecodeError if not scanner.eos?
|
36
|
+
return msg
|
37
|
+
end
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
when 's'
|
49
|
-
str = scanner.scan(/[^\000]+\000/)
|
50
|
-
scanner.pos += OSC.padding_size(str.size)
|
51
|
-
args.push str.chomp("\000")
|
52
|
-
when 'b'
|
53
|
-
size = scanner.scan(/.{4}/).unpack('N').first
|
54
|
-
str = scanner.scan(/.{#{ size }}/nm)
|
55
|
-
scanner.pos += OSC.padding_size(size + 4)
|
56
|
-
args.push Blob.new(str)
|
57
|
-
else
|
58
|
-
raise DecodeError, "#{ t } is not a known tag"
|
39
|
+
def self.decode_message scanner
|
40
|
+
pos = scanner.pos
|
41
|
+
begin
|
42
|
+
address, tags = (1..2).map do
|
43
|
+
string = scanner.scan(/[^\000]+\000/)
|
44
|
+
raise DecodeError, "no address or tags" if string.nil?
|
45
|
+
scanner.pos += OSC.padding_size(string.bytesize)
|
46
|
+
string.chomp("\000")
|
59
47
|
end
|
60
|
-
end
|
61
48
|
|
62
|
-
|
49
|
+
args = []
|
50
|
+
tags.scan(/\w/) do |tag|
|
51
|
+
case tag
|
52
|
+
when 'i'
|
53
|
+
int = scanner.scan(/.{4}/nm).unpack('N').first
|
54
|
+
args.push( int > (2**31-1) ? int - 2**32 : int )
|
55
|
+
when 'f'
|
56
|
+
args.push scanner.scan(/.{4}/nm).unpack('g').first
|
57
|
+
when 's'
|
58
|
+
str = scanner.scan(/[^\000]+\000/)
|
59
|
+
scanner.pos += OSC.padding_size(str.size)
|
60
|
+
str = str.respond_to?(:force_encoding) ? str.force_encoding('UTF-8') : str
|
61
|
+
args.push str.chomp("\000")
|
62
|
+
when 'b'
|
63
|
+
size = scanner.scan(/.{4}/).unpack('N').first
|
64
|
+
str = scanner.scan(/.{#{ size }}/nm)
|
65
|
+
scanner.pos += OSC.padding_size(size + 4)
|
66
|
+
args.push Blob.new(str)
|
67
|
+
else
|
68
|
+
raise DecodeError, "#{ tag } is not a known tag"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
new address, *args
|
72
|
+
end
|
73
|
+
rescue DecodeError => e
|
74
|
+
scanner.pos = pos
|
75
|
+
raise e
|
76
|
+
rescue => e
|
77
|
+
scanner.pos = pos
|
78
|
+
raise DecodeError, e
|
63
79
|
end
|
64
|
-
|
65
80
|
end
|
66
81
|
end
|
data/lib/ruby-osc/server.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
|
2
1
|
module OSC
|
3
2
|
class Server
|
4
3
|
attr_accessor :port, :address
|
5
4
|
|
6
|
-
def initialize port, address = '
|
5
|
+
def initialize port, address = '127.0.0.1'
|
7
6
|
@port, @address = port, address
|
8
7
|
@queue, @patterns = [], []
|
9
8
|
@mutex = Mutex.new
|
@@ -37,7 +36,7 @@ module OSC
|
|
37
36
|
when Message
|
38
37
|
dispatch decoded
|
39
38
|
end
|
40
|
-
rescue => e
|
39
|
+
rescue => e
|
41
40
|
warn "Bad data received: #{ e }"
|
42
41
|
end
|
43
42
|
|
@@ -55,7 +54,7 @@ module OSC
|
|
55
54
|
end
|
56
55
|
|
57
56
|
def dispatch message
|
58
|
-
@patterns.each do |pat, block|
|
57
|
+
@patterns.each do |pat, block|
|
59
58
|
block.call(*message.to_a) if pat === message.address
|
60
59
|
end
|
61
60
|
end
|
@@ -66,7 +65,7 @@ module OSC
|
|
66
65
|
end
|
67
66
|
|
68
67
|
def receive_data data
|
69
|
-
@server.receive(data)
|
68
|
+
@server.receive(data)
|
70
69
|
end
|
71
70
|
end
|
72
71
|
end
|
data/lib/ruby-osc/version.rb
CHANGED
data/spec/bundle_spec.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
require "#{ File.dirname __FILE__ }/spec_helper"
|
2
3
|
|
3
4
|
describe Bundle do
|
@@ -12,11 +13,11 @@ describe Bundle do
|
|
12
13
|
it "should rise TypeError if passing passing incorrect type" do
|
13
14
|
lambda { Bundle.new Time.now, 1 }.should raise_error(TypeError)
|
14
15
|
end
|
15
|
-
|
16
|
+
|
16
17
|
it "should raise TypeError if timetag is not Time" do
|
17
18
|
lambda { Bundle.new 1 }.should raise_error(TypeError)
|
18
19
|
end
|
19
|
-
|
20
|
+
|
20
21
|
it "should accept nil for timetag" do
|
21
22
|
Bundle.new nil
|
22
23
|
end
|
@@ -38,15 +39,15 @@ describe Bundle do
|
|
38
39
|
Bundle.decode(@expected).should == @bundle
|
39
40
|
end
|
40
41
|
end
|
41
|
-
|
42
|
+
|
42
43
|
describe 'Empty bundle nil timetag' do
|
43
44
|
before do
|
44
45
|
@bundle = Bundle.new
|
45
|
-
@expected = "#bundle\000\000\000\000\000\000\000\000\001"
|
46
|
+
@expected = "#bundle\000\000\000\000\000\000\000\000\001".force_encoding("binary")
|
46
47
|
end
|
47
48
|
it_should_behave_like 'Encodable Bundle'
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
describe 'Empty bundle with timetag' do
|
51
52
|
before do
|
52
53
|
@bundle = Bundle.new Time.at(1251420949.16959)
|
@@ -54,7 +55,7 @@ describe Bundle do
|
|
54
55
|
end
|
55
56
|
it_should_behave_like 'Encodable Bundle'
|
56
57
|
end
|
57
|
-
|
58
|
+
|
58
59
|
describe 'Bundle with timetag and messages' do
|
59
60
|
before do
|
60
61
|
@bundle = Bundle.new Time.at(946702800), Message.new('/bar/foo', 4, 3, 2, 1), Message.new('/foo/bar', 1, 2, 3, 4)
|
@@ -62,15 +63,15 @@ describe Bundle do
|
|
62
63
|
end
|
63
64
|
it_should_behave_like 'Encodable Bundle'
|
64
65
|
end
|
65
|
-
|
66
|
+
|
66
67
|
describe 'Nested bundles' do
|
67
68
|
before do
|
68
69
|
@bundle = Bundle.new( nil, Bundle.new(nil, Message.new('/a')), Message.new('/b') )
|
69
|
-
@expected = "#bundle\000\000\000\000\000\000\000\000\001\000\000\000\034#bundle\000\000\000\000\000\000\000\000\001\000\000\000\b/a\000\000,\000\000\000\000\000\000\b/b\000\000,\000\000\000"
|
70
|
+
@expected = "#bundle\000\000\000\000\000\000\000\000\001\000\000\000\034#bundle\000\000\000\000\000\000\000\000\001\000\000\000\b/a\000\000,\000\000\000\000\000\000\b/b\000\000,\000\000\000".force_encoding("binary")
|
70
71
|
end
|
71
72
|
it_should_behave_like 'Encodable Bundle'
|
72
73
|
end
|
73
|
-
|
74
|
+
|
74
75
|
describe 'Complex blob' do
|
75
76
|
before do
|
76
77
|
data = [ 83, 67, 103, 102, 0, 0, 0, 1, 0, 1, 4, 104, 111, 108, 97, 0, 2, 67, -36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 83, 105, 110, 79, 115, 99, 2, 0, 2, 0, 1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 1, 2, 0, 0 ].pack('C*')
|
@@ -79,7 +80,7 @@ describe Bundle do
|
|
79
80
|
end
|
80
81
|
it_should_behave_like 'Encodable Bundle'
|
81
82
|
end
|
82
|
-
|
83
|
+
|
83
84
|
describe 'Complex blob 2' do
|
84
85
|
before do
|
85
86
|
data = [ 83, 67, 103, 102, 0, 0, 0, 1, 0, 1, 2, 97, 109, 0, 7, 0, 0, 0, 0, 63, 0, 0, 0, 63, -128, 0, 0, 64, 0, 0, 0, -62, -58, 0, 0, 64, -96, 0, 0, -64, -128, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 103, 97, 116, 101, 0, 0, 9, 112, 111, 114, 116, 97, 100, 111, 114, 97, 0, 1, 10, 109, 111, 100, 117, 108, 97, 100, 111, 114, 97, 0, 2, 3, 97, 109, 112, 0, 3, 0, 8, 7, 67, 111, 110, 116, 114, 111, 108, 1, 0, 0, 0, 4, 0, 0, 1, 1, 1, 1, 6, 83, 105, 110, 79, 115, 99, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 2, -1, -1, 0, 0, 1, 6, 77, 117, 108, 65, 100, 100, 1, 0, 3, 0, 1, 0, 0, 0, 1, 0, 0, -1, -1, 0, 1, -1, -1, 0, 1, 1, 6, 83, 105, 110, 79, 115, 99, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 2, 12, 66, 105, 110, 97, 114, 121, 79, 112, 85, 71, 101, 110, 2, 0, 2, 0, 1, 0, 2, 0, 3, 0, 0, 0, 2, 0, 0, 2, 6, 69, 110, 118, 71, 101, 110, 1, 0, 17, 0, 1, 0, 0, 0, 0, 0, 0, -1, -1, 0, 2, -1, -1, 0, 0, -1, -1, 0, 2, -1, -1, 0, 3, -1, -1, 0, 0, -1, -1, 0, 3, -1, -1, 0, 2, -1, -1, 0, 4, -1, -1, 0, 2, -1, -1, 0, 3, -1, -1, 0, 5, -1, -1, 0, 6, -1, -1, 0, 0, -1, -1, 0, 3, -1, -1, 0, 5, -1, -1, 0, 6, 1, 12, 66, 105, 110, 97, 114, 121, 79, 112, 85, 71, 101, 110, 2, 0, 2, 0, 1, 0, 2, 0, 4, 0, 0, 0, 5, 0, 0, 2, 3, 79, 117, 116, 2, 0, 2, 0, 0, 0, 0, -1, -1, 0, 0, 0, 6, 0, 0, 0, 0 ].pack('C*')
|
@@ -88,9 +89,9 @@ describe Bundle do
|
|
88
89
|
end
|
89
90
|
it_should_behave_like 'Encodable Bundle'
|
90
91
|
end
|
91
|
-
|
92
|
+
|
92
93
|
it 'Should raise OSC::DecodeError with bad encoded bundle' do
|
93
|
-
bad_data = "#bundle\000\000\000\000\000\000\000\000\001\000\000\000\034#bundle\000\000\000\000\000\001\000\000\000\b/a\000\000,\000\000\000\000\000\000\b/b\000\000,\000\000\000"
|
94
|
+
bad_data = "#bundle\000\000\000\000\000\000\000\000\001\000\000\000\034#bundle\000\000\000\000\000\001\000\000\000\b/a\000\000,\000\000\000\000\000\000\b/b\000\000,\000\000\000".force_encoding("binary")
|
94
95
|
lambda { Bundle.decode bad_data }.should raise_error(DecodeError)
|
95
96
|
end
|
96
97
|
end
|
data/spec/message_spec.rb
CHANGED
@@ -1,56 +1,59 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
require "#{ File.dirname __FILE__ }/spec_helper"
|
2
3
|
|
3
4
|
describe Message do
|
4
|
-
|
5
5
|
it "should raise TypeError if passing wrong type" do
|
6
|
-
|
6
|
+
expect { Message.new('address', Class) }.to raise_error(TypeError)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
it "should raise TypeError if not passing a string for address" do
|
10
|
-
|
10
|
+
expect { Message.new(OSC) }.to raise_error(TypeError)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
it "should have address" do
|
14
14
|
Message.new('/foo/bar').address.should == '/foo/bar'
|
15
15
|
end
|
16
|
+
|
17
|
+
it "should accept utf8 address" do
|
18
|
+
Message.new('/foo/bär').address.should == '/foo/bär'
|
19
|
+
end
|
16
20
|
|
17
21
|
it "should collect args" do
|
18
22
|
Message.new('/foo/bar', 1, 2, 3, 4).args.size.should == 4
|
19
23
|
end
|
20
|
-
|
24
|
+
|
21
25
|
it "should accept integer" do
|
22
26
|
Message.new('/foo/bar', 1).args.should == [1]
|
23
27
|
end
|
24
|
-
|
28
|
+
|
25
29
|
it "should should accept float" do
|
26
30
|
Message.new('/foo/bar', 1.0).args.should == [1.0]
|
27
31
|
end
|
28
|
-
|
32
|
+
|
29
33
|
it "should accept string" do
|
30
34
|
Message.new('/foo/bar', 'string').args.should == ['string']
|
31
35
|
end
|
32
|
-
|
36
|
+
|
33
37
|
it "should accept Blob" do
|
34
38
|
Message.new('/foo/bar', Blob.new('blob')).args.should == [Blob.new('blob')]
|
35
39
|
end
|
36
|
-
|
40
|
+
|
37
41
|
it "should convert to array" do
|
38
42
|
Message.new('/foo/bar', 1, 2, 3, 4).to_a.should == ['/foo/bar', 1, 2, 3, 4]
|
39
43
|
end
|
40
|
-
|
44
|
+
|
41
45
|
describe 'Custom argument coercion' do
|
42
|
-
|
43
46
|
before do
|
44
47
|
TrueClass.send(:include, OSCArgument)
|
45
48
|
TrueClass.send( :define_method, :to_osc_type){ 1 }
|
46
49
|
FalseClass.send(:include, OSCArgument)
|
47
50
|
FalseClass.send( :define_method, :to_osc_type){ 0 }
|
48
51
|
Hash.send(:include, OSCArgument)
|
49
|
-
Hash.send( :define_method, :to_osc_type) do
|
52
|
+
Hash.send( :define_method, :to_osc_type) do
|
50
53
|
self.to_a.collect{ |pair| pair.collect{ |a| OSC.coerce_argument a } }
|
51
54
|
end
|
52
55
|
end
|
53
|
-
|
56
|
+
|
54
57
|
it "should accept true" do
|
55
58
|
Message.new('/foo/bar', true).args.should == [1]
|
56
59
|
end
|
@@ -63,50 +66,50 @@ describe Message do
|
|
63
66
|
Message.new('/foo/bar', {:a => :b}).args.should == ["a", "b"]
|
64
67
|
end
|
65
68
|
end
|
66
|
-
|
69
|
+
|
67
70
|
describe 'Encode/decode' do
|
68
71
|
shared_examples_for 'Encodable Message' do
|
69
72
|
it "should encode" do
|
70
73
|
@message.encode.should == @expected
|
71
74
|
end
|
72
|
-
|
75
|
+
|
73
76
|
it "should decode to message" do
|
74
77
|
Message.decode(@expected).should be_a(Message)
|
75
78
|
end
|
76
|
-
|
79
|
+
|
77
80
|
it "should decode address" do
|
78
81
|
Message.decode(@expected).address.should == @message.address
|
79
82
|
end
|
80
|
-
|
83
|
+
|
81
84
|
it "should actually decode" do
|
82
85
|
Message.decode(@expected).to_a.inspect.should == @message.to_a.inspect.to_s # Problem with float comparing
|
83
86
|
end
|
84
87
|
end
|
85
|
-
|
88
|
+
|
86
89
|
describe 'Address' do
|
87
90
|
before do
|
88
91
|
@message = Message.new('/foo/bar/long/very/long/long/long/address')
|
89
|
-
@expected = "/foo/bar/long/very/long/long/long/address\000\000\000,\000\000\000"
|
92
|
+
@expected = "/foo/bar/long/very/long/long/long/address\000\000\000,\000\000\000".force_encoding("binary")
|
90
93
|
end
|
91
94
|
it_should_behave_like 'Encodable Message'
|
92
95
|
end
|
93
|
-
|
96
|
+
|
94
97
|
describe 'Integer' do
|
95
98
|
before do
|
96
99
|
@message = Message.new('/foo/barz', 2)
|
97
|
-
@expected = "/foo/barz\000\000\000,i\000\000\000\000\000\002"
|
100
|
+
@expected = "/foo/barz\000\000\000,i\000\000\000\000\000\002".force_encoding("binary")
|
98
101
|
end
|
99
102
|
it_should_behave_like 'Encodable Message'
|
100
103
|
end
|
101
|
-
|
104
|
+
|
102
105
|
describe 'Negative Integer' do
|
103
106
|
before do
|
104
107
|
@message = Message.new('/foo/barz', -2)
|
105
|
-
@expected = "/foo/barz\000\000\000,i\000\000\377\377\377\376"
|
108
|
+
@expected = "/foo/barz\000\000\000,i\000\000\377\377\377\376".force_encoding("binary")
|
106
109
|
end
|
107
110
|
it_should_behave_like 'Encodable Message'
|
108
111
|
end
|
109
|
-
|
112
|
+
|
110
113
|
describe 'Float' do
|
111
114
|
before do
|
112
115
|
@message = Message.new('/foo/bar', 1.100000023841858)
|
@@ -114,7 +117,7 @@ describe Message do
|
|
114
117
|
end
|
115
118
|
it_should_behave_like 'Encodable Message'
|
116
119
|
end
|
117
|
-
|
120
|
+
|
118
121
|
describe 'Negative Float' do
|
119
122
|
before do
|
120
123
|
@message = Message.new('/foo/bar', -1.100000023841858)
|
@@ -122,11 +125,19 @@ describe Message do
|
|
122
125
|
end
|
123
126
|
it_should_behave_like 'Encodable Message'
|
124
127
|
end
|
125
|
-
|
128
|
+
|
126
129
|
describe 'String' do
|
127
130
|
before do
|
128
131
|
@message = Message.new('/foo/bar', 'a string to encode')
|
129
|
-
@expected = "/foo/bar\000\000\000\000,s\000\000a string to encode\000\000"
|
132
|
+
@expected = "/foo/bar\000\000\000\000,s\000\000a string to encode\000\000".force_encoding("binary")
|
133
|
+
end
|
134
|
+
it_should_behave_like 'Encodable Message'
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'UTF8 String' do
|
138
|
+
before do
|
139
|
+
@message = Message.new('/foo/bar', 'a string to äncode')
|
140
|
+
@expected = "/foo/bar\000\000\000\000,s\000\000a string to äncode\000".force_encoding("binary")
|
130
141
|
end
|
131
142
|
it_should_behave_like 'Encodable Message'
|
132
143
|
end
|
@@ -138,27 +149,35 @@ describe Message do
|
|
138
149
|
end
|
139
150
|
it_should_behave_like 'Encodable Message'
|
140
151
|
end
|
141
|
-
|
152
|
+
|
142
153
|
describe 'Blob' do
|
143
154
|
before do
|
144
155
|
@message = Message.new('/foo/bar', Blob.new('test blob'))
|
145
|
-
@expected = "/foo/bar\000\000\000\000,b\000\000\000\000\000\ttest blob\000\000\000"
|
156
|
+
@expected = "/foo/bar\000\000\000\000,b\000\000\000\000\000\ttest blob\000\000\000".force_encoding("binary")
|
146
157
|
end
|
147
158
|
it_should_behave_like 'Encodable Message'
|
148
|
-
|
159
|
+
|
149
160
|
it "should raise if size doesn't correspond and return empty message" do
|
150
161
|
lambda do
|
151
|
-
Message.decode("/foo/bar\000\000\000\000,b\000\000\000\000\000\020test blob\000\000\000")
|
162
|
+
Message.decode("/foo/bar\000\000\000\000,b\000\000\000\000\000\020test blob\000\000\000".force_encoding("binary"))
|
152
163
|
end.should raise_error
|
153
164
|
end
|
154
165
|
end
|
155
|
-
|
166
|
+
|
156
167
|
describe 'Lots of ints' do
|
157
168
|
before do
|
158
169
|
@message = Message.new('/bar/foo', 4, 3, 2, 1)
|
159
|
-
@expected = "/bar/foo\000\000\000\000,iiii\000\000\000\000\000\000\004\000\000\000\003\000\000\000\002\000\000\000\001"
|
170
|
+
@expected = "/bar/foo\000\000\000\000,iiii\000\000\000\000\000\000\004\000\000\000\003\000\000\000\002\000\000\000\001".force_encoding("binary")
|
160
171
|
end
|
161
172
|
it_should_behave_like 'Encodable Message'
|
162
173
|
end
|
163
|
-
|
174
|
+
|
175
|
+
describe 'Invalid message' do
|
176
|
+
it "should raise if invalid tag is used" do
|
177
|
+
lambda do
|
178
|
+
Message.decode("/foo/bar\000\000\000\000,k\000\000\000\000\000\020test blob\000\000\000".force_encoding("binary"))
|
179
|
+
end.should raise_exception(DecodeError)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
164
183
|
end
|
data/spec/server_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
$:.unshift( File.join( File.dirname( __FILE__), 'lib' ) )
|
4
|
+
|
5
|
+
require 'ruby-osc/streamscanner'
|
6
|
+
|
7
|
+
@ss = OSC::StreamScanner.new
|
8
|
+
|
9
|
+
count = 10_000
|
10
|
+
|
11
|
+
Benchmark.bm(23) do |x|
|
12
|
+
x.report("add new string") do
|
13
|
+
count.times do
|
14
|
+
@ss << "/bar/foo\000\000\000\000,iiii\000\000\000\000\000\000\004\000\000\000\003\000\000\000\002\000\000\000\001".force_encoding("binary")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
x.report("parse string") do
|
19
|
+
count.times do
|
20
|
+
@ss.tryparse
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
x.report("try parse each message") do
|
26
|
+
count.times do
|
27
|
+
OSC::Message.decode("/bar/foo\000\000\000\000,iiii\000\000\000\000\000\000\004\000\000\000\003\000\000\000\002\000\000\000\001".force_encoding("binary"))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
x.report("parse failure") do
|
32
|
+
count.times do
|
33
|
+
@ss.tryparse rescue nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
metadata
CHANGED
@@ -1,50 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-osc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Macario
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
default_executable:
|
11
|
+
date: 2013-07-06 00:00:00.000000000 Z
|
14
12
|
dependencies:
|
15
13
|
- !ruby/object:Gem::Dependency
|
16
14
|
name: rspec
|
17
|
-
requirement:
|
18
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
19
16
|
requirements:
|
20
|
-
- -
|
17
|
+
- - '>='
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: 2.6.0
|
23
20
|
type: :development
|
24
21
|
prerelease: false
|
25
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.6.0
|
26
27
|
- !ruby/object:Gem::Dependency
|
27
28
|
name: bundler
|
28
|
-
requirement:
|
29
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
37
41
|
- !ruby/object:Gem::Dependency
|
38
42
|
name: eventmachine
|
39
|
-
requirement:
|
40
|
-
none: false
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
41
44
|
requirements:
|
42
|
-
- -
|
45
|
+
- - '>='
|
43
46
|
- !ruby/object:Gem::Version
|
44
47
|
version: 0.12.8
|
45
48
|
type: :runtime
|
46
49
|
prerelease: false
|
47
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.12.8
|
48
55
|
description: Concise OSC Ruby implementation
|
49
56
|
email:
|
50
57
|
- macarui@gmail.com
|
@@ -69,30 +76,29 @@ files:
|
|
69
76
|
- spec/message_spec.rb
|
70
77
|
- spec/server_spec.rb
|
71
78
|
- spec/spec_helper.rb
|
72
|
-
|
79
|
+
- streamscanner_benchmark.rb
|
73
80
|
homepage: http://makarius.me
|
74
81
|
licenses: []
|
82
|
+
metadata: {}
|
75
83
|
post_install_message:
|
76
84
|
rdoc_options: []
|
77
85
|
require_paths:
|
78
86
|
- lib
|
79
87
|
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
-
none: false
|
81
88
|
requirements:
|
82
|
-
- -
|
89
|
+
- - '>='
|
83
90
|
- !ruby/object:Gem::Version
|
84
91
|
version: '0'
|
85
92
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
-
none: false
|
87
93
|
requirements:
|
88
|
-
- -
|
94
|
+
- - '>='
|
89
95
|
- !ruby/object:Gem::Version
|
90
96
|
version: '0'
|
91
97
|
requirements: []
|
92
98
|
rubyforge_project: ruby-osc
|
93
|
-
rubygems_version:
|
99
|
+
rubygems_version: 2.0.0
|
94
100
|
signing_key:
|
95
|
-
specification_version:
|
101
|
+
specification_version: 4
|
96
102
|
summary: Concise OSC Ruby implementation
|
97
103
|
test_files:
|
98
104
|
- spec/bundle_spec.rb
|