osc-ruby 0.2.0 → 0.6.0
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.
- data/README.rdoc +1 -1
- data/Rakefile +19 -6
- data/lib/osc-ruby/bundle.rb +12 -13
- data/lib/osc-ruby/client.rb +0 -1
- data/lib/osc-ruby/em_server.rb +18 -22
- data/lib/osc-ruby/message.rb +8 -12
- data/lib/osc-ruby/network_packet.rb +16 -17
- data/lib/osc-ruby/osc_argument.rb +0 -2
- data/lib/osc-ruby/osc_packet.rb +24 -24
- data/lib/osc-ruby/osc_types.rb +0 -8
- data/spec/unit/message_builder_spec.rb +43 -0
- data/spec/unit/message_spec.rb +39 -15
- metadata +8 -6
- data/lib/osc-ruby/packet.rb +0 -134
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spec/rake/spectask'
|
2
2
|
|
3
|
-
|
4
3
|
task :default => :spec
|
5
4
|
|
6
5
|
Spec::Rake::SpecTask.new do |t|
|
@@ -9,10 +8,26 @@ Spec::Rake::SpecTask.new do |t|
|
|
9
8
|
t.spec_opts = ["--colour"]
|
10
9
|
end
|
11
10
|
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
Rake::RDocTask.new do |rdoc|
|
13
|
+
if File.exist?('VERSION')
|
14
|
+
version = File.read('VERSION')
|
15
|
+
else
|
16
|
+
version = ""
|
17
|
+
end
|
18
|
+
|
19
|
+
rdoc.rdoc_dir = 'rdoc'
|
20
|
+
rdoc.title = "osc-ruby #{version}"
|
21
|
+
rdoc.rdoc_files.include('README*')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
24
|
+
|
25
|
+
|
12
26
|
begin
|
13
27
|
require 'jeweler'
|
14
28
|
Jeweler::Tasks.new do |gem|
|
15
29
|
gem.name = "osc-ruby"
|
30
|
+
gem.description = "a ruby client for the OSC protocol"
|
16
31
|
gem.summary = %Q{inital gem}
|
17
32
|
gem.email = "qzzzq1@gmail.com"
|
18
33
|
gem.homepage = "http://github.com/aberant/osc-ruby"
|
@@ -20,12 +35,10 @@ begin
|
|
20
35
|
gem.files = FileList['Rakefile', 'examples/**/*', 'lib/**/*'].to_a
|
21
36
|
gem.test_files = FileList['spec/**/*.rb']
|
22
37
|
gem.rubyforge_project = "osc-ruby"
|
23
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
24
|
-
end
|
25
|
-
|
26
|
-
Jeweler::RubyforgeTasks.new do |rubyforge|
|
27
|
-
rubyforge.doc_task = "rdoc"
|
28
38
|
end
|
39
|
+
|
40
|
+
Jeweler::GemcutterTasks.new
|
41
|
+
|
29
42
|
rescue LoadError
|
30
43
|
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
31
44
|
end
|
data/lib/osc-ruby/bundle.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
|
-
require File.join( File.dirname( __FILE__ ), "packet" )
|
2
|
-
|
3
1
|
module OSC
|
4
|
-
class Bundle
|
2
|
+
class Bundle
|
5
3
|
attr_accessor :timetag
|
6
|
-
|
4
|
+
|
7
5
|
def initialize(timetag=nil, *args)
|
8
6
|
@timetag = timetag
|
9
7
|
@args = args
|
10
8
|
end
|
11
|
-
|
9
|
+
|
12
10
|
def encode()
|
13
11
|
s = OSCString.new('#bundle').encode
|
14
12
|
s << encode_timetag(@timetag)
|
@@ -17,12 +15,9 @@ module OSC
|
|
17
15
|
end.join
|
18
16
|
end
|
19
17
|
|
20
|
-
|
21
18
|
def to_a() @args.collect{|x| x.to_a} end
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
private
|
20
|
+
private
|
26
21
|
|
27
22
|
def encode_timetag(t)
|
28
23
|
case t
|
@@ -30,16 +25,20 @@ module OSC
|
|
30
25
|
t1 = 0
|
31
26
|
t2 = 1
|
32
27
|
when Numeric
|
33
|
-
t1,
|
34
|
-
t2 = (fr * (2**32)).to_i
|
28
|
+
t1, t2 = construct_timetag( t )
|
35
29
|
when Time
|
36
|
-
t1,
|
37
|
-
t2 = (fr * (2**32)).to_i
|
30
|
+
t1, t2 = construct_timetag( t.to_ntp )
|
38
31
|
else
|
39
32
|
raise ArgumentError, 'invalid time'
|
40
33
|
end
|
41
34
|
[t1, t2].pack('N2')
|
42
35
|
end
|
43
36
|
|
37
|
+
def construct_timetag( time )
|
38
|
+
t1, fr = time.divmod(1)
|
39
|
+
t2 = (fr * (2**32)).to_i
|
40
|
+
|
41
|
+
[t1, t2]
|
42
|
+
end
|
44
43
|
end
|
45
44
|
end
|
data/lib/osc-ruby/client.rb
CHANGED
data/lib/osc-ruby/em_server.rb
CHANGED
@@ -2,54 +2,51 @@ require 'rubygems'
|
|
2
2
|
require 'eventmachine'
|
3
3
|
require File.join( File.dirname( __FILE__), '..', 'osc-ruby')
|
4
4
|
|
5
|
-
|
6
5
|
module OSC
|
7
6
|
Channel = EM::Channel.new
|
8
|
-
|
9
|
-
class Connection < EventMachine::Connection
|
10
7
|
|
11
|
-
|
8
|
+
class Connection < EventMachine::Connection
|
9
|
+
def receive_data data
|
12
10
|
Channel << OSC::OSCPacket.messages_from_network( data )
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
16
|
-
|
17
14
|
class EMServer
|
18
|
-
|
15
|
+
|
19
16
|
def initialize( port = 3333 )
|
20
17
|
@port = port
|
21
18
|
setup_dispatcher
|
22
19
|
@tuples = []
|
23
20
|
end
|
24
|
-
|
21
|
+
|
25
22
|
def run
|
26
23
|
EM::run { EM::open_datagram_socket "localhost", @port, Connection }
|
27
24
|
end
|
28
|
-
|
25
|
+
|
29
26
|
def add_method(address_pattern, &proc)
|
30
27
|
matcher = AddressPattern.new( address_pattern )
|
31
|
-
|
28
|
+
|
32
29
|
@tuples << [matcher, proc]
|
33
|
-
end
|
34
|
-
|
30
|
+
end
|
31
|
+
|
35
32
|
private
|
36
33
|
def setup_dispatcher
|
37
34
|
Channel.subscribe do |messages|
|
38
|
-
messages.each do |message|
|
39
|
-
diff = ( message.time || 0 ) - Time.now.to_ntp
|
35
|
+
messages.each do |message|
|
36
|
+
diff = ( message.time || 0 ) - Time.now.to_ntp
|
40
37
|
|
41
|
-
if diff <= 0
|
38
|
+
if diff <= 0
|
42
39
|
sendmesg( message )
|
43
|
-
else
|
44
|
-
EM.defer do
|
45
|
-
sleep( diff )
|
40
|
+
else
|
41
|
+
EM.defer do
|
42
|
+
sleep( diff )
|
46
43
|
sendmesg( message )
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
50
47
|
end
|
51
48
|
end
|
52
|
-
|
49
|
+
|
53
50
|
def sendmesg(mesg)
|
54
51
|
@tuples.each do |matcher, obj|
|
55
52
|
if matcher.match?( mesg.address )
|
@@ -57,7 +54,6 @@ module OSC
|
|
57
54
|
end
|
58
55
|
end
|
59
56
|
end
|
60
|
-
|
61
57
|
end
|
62
58
|
end
|
63
59
|
|
data/lib/osc-ruby/message.rb
CHANGED
@@ -1,22 +1,19 @@
|
|
1
|
-
require File.join( File.dirname( __FILE__ ), "packet" )
|
2
|
-
|
3
1
|
module OSC
|
4
|
-
class Message
|
2
|
+
class Message
|
5
3
|
attr_accessor :address
|
6
|
-
attr_accessor :time
|
4
|
+
attr_accessor :time
|
7
5
|
|
8
|
-
|
9
6
|
def self.new_with_time( address, time, tags=nil, *args )
|
10
7
|
message = new( address, tags, *args )
|
11
8
|
message.time = time
|
12
9
|
message
|
13
10
|
end
|
14
|
-
|
15
|
-
def initialize(address, *args)
|
11
|
+
|
12
|
+
def initialize( address, *args )
|
16
13
|
@address = address
|
17
14
|
@args = []
|
18
|
-
|
19
|
-
args.
|
15
|
+
|
16
|
+
args.each do |arg|
|
20
17
|
case arg
|
21
18
|
when Integer; @args << OSCInt32.new(arg)
|
22
19
|
when Float; @args << OSCFloat32.new(arg)
|
@@ -26,7 +23,6 @@ module OSC
|
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
|
-
|
30
26
|
def tags() @args.collect{|x| x.tag}.join end
|
31
27
|
|
32
28
|
def encode
|
@@ -36,8 +32,8 @@ module OSC
|
|
36
32
|
end
|
37
33
|
|
38
34
|
def to_a() @args.collect{|x| x.val} end
|
39
|
-
|
40
|
-
def
|
35
|
+
|
36
|
+
def ==( other )
|
41
37
|
@address == other.address &&
|
42
38
|
to_a == other.to_a
|
43
39
|
end
|
@@ -1,29 +1,29 @@
|
|
1
1
|
module OSC
|
2
2
|
class NetworkPacket
|
3
|
-
def initialize(str)
|
4
|
-
@str, @index = str, 0
|
3
|
+
def initialize(str)
|
4
|
+
@str, @index = str, 0
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def to_s
|
8
8
|
@str
|
9
9
|
end
|
10
|
-
|
11
|
-
def rem()
|
12
|
-
@str.length - @index
|
10
|
+
|
11
|
+
def rem()
|
12
|
+
@str.length - @index
|
13
13
|
end
|
14
|
-
|
15
|
-
def eof? ()
|
16
|
-
rem <= 0
|
14
|
+
|
15
|
+
def eof? ()
|
16
|
+
rem <= 0
|
17
17
|
end
|
18
|
-
|
19
|
-
def skip(n)
|
20
|
-
@index += n
|
18
|
+
|
19
|
+
def skip(n)
|
20
|
+
@index += n
|
21
21
|
end
|
22
|
-
|
23
|
-
def skip_padding()
|
24
|
-
skip((4 - (@index % 4)) % 4)
|
22
|
+
|
23
|
+
def skip_padding()
|
24
|
+
skip((4 - (@index % 4)) % 4)
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def getn(n)
|
28
28
|
raise EOFError if rem < n
|
29
29
|
s = @str[@index, n]
|
@@ -37,6 +37,5 @@ module OSC
|
|
37
37
|
skip(1)
|
38
38
|
c
|
39
39
|
end
|
40
|
-
|
41
40
|
end
|
42
41
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module OSC
|
2
2
|
class OSCArgument
|
3
|
-
|
4
3
|
def initialize(val) @val = val end
|
5
4
|
|
6
5
|
attr_accessor :val
|
@@ -9,7 +8,6 @@ module OSC
|
|
9
8
|
def to_f() @val.to_f end
|
10
9
|
def to_s() @val.to_s end
|
11
10
|
|
12
|
-
|
13
11
|
private
|
14
12
|
def padding(s)
|
15
13
|
s + ("\000" * ((4 - (s.size % 4)) % 4))
|
data/lib/osc-ruby/osc_packet.rb
CHANGED
@@ -3,53 +3,53 @@ require 'ostruct'
|
|
3
3
|
|
4
4
|
module OSC
|
5
5
|
class OSCPacket
|
6
|
-
|
6
|
+
|
7
7
|
def self.messages_from_network( string )
|
8
8
|
messages = []
|
9
9
|
osc = new( string )
|
10
|
-
|
10
|
+
|
11
11
|
if osc.bundle?
|
12
12
|
bundle = osc.get_string
|
13
13
|
time = osc.get_timestamp
|
14
|
-
|
14
|
+
|
15
15
|
osc.get_bundle_messages.each do | message |
|
16
16
|
messages << decode_simple_message( time, OSCPacket.new( message ) )
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
else
|
20
20
|
messages << decode_simple_message( time, osc )
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
return messages
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def self.decode_simple_message( time, osc_packet )
|
27
27
|
address = osc_packet.get_string
|
28
|
-
args = osc_packet.get_arguments
|
28
|
+
args = osc_packet.get_arguments
|
29
29
|
|
30
30
|
Message.new_with_time(address, time, nil, *args )
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def initialize( string )
|
34
34
|
@packet = NetworkPacket.new( string )
|
35
|
-
|
36
|
-
@types = { "i" => lambda{ OSCInt32.new( get_int32 ) },
|
35
|
+
|
36
|
+
@types = { "i" => lambda{ OSCInt32.new( get_int32 ) },
|
37
37
|
"f" => lambda{ OSCFloat32.new( get_float32 ) },
|
38
38
|
"s" => lambda{ OSCString.new( get_string ) },
|
39
39
|
"b" => lambda{ OSCBlob.new( get_blob )}
|
40
40
|
}
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def get_bundle_messages
|
44
44
|
bundle_messages = []
|
45
|
-
|
45
|
+
|
46
46
|
until @packet.eof?
|
47
47
|
l = @packet.getn(4).unpack('N')[0]
|
48
48
|
bundle_messages << @packet.getn(l)
|
49
49
|
end
|
50
50
|
bundle_messages
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def get_string
|
54
54
|
result = ''
|
55
55
|
until (c = @packet.getc) == string_delemeter
|
@@ -58,58 +58,58 @@ module OSC
|
|
58
58
|
@packet.skip_padding
|
59
59
|
result
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
def get_timestamp
|
63
63
|
t1 = @packet.getn(4).unpack('N')[0]
|
64
64
|
t2 = @packet.getn(4).unpack('N')[0]
|
65
65
|
@packet.skip_padding
|
66
|
-
|
66
|
+
|
67
67
|
if t1 == 0 && t2 == 1
|
68
68
|
time = nil
|
69
69
|
else
|
70
70
|
time = t1 + t2.to_f / (2**32)
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
time
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
def get_arguments
|
77
77
|
if @packet.getc == ?,
|
78
|
-
|
78
|
+
|
79
79
|
tags = get_string
|
80
80
|
args = []
|
81
|
-
|
81
|
+
|
82
82
|
tags.scan(/./) do | tag |
|
83
83
|
args << @types[tag].call
|
84
84
|
end
|
85
85
|
args
|
86
86
|
end
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
def get_int32
|
90
90
|
i = @packet.getn(4).unpack('N')[0]
|
91
91
|
i -= 2**32 if i > (2**31-1)
|
92
92
|
@packet.skip_padding
|
93
93
|
i
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
96
|
def get_float32
|
97
97
|
f = @packet.getn(4).unpack('g')[0]
|
98
98
|
@packet.skip_padding
|
99
99
|
f
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
def get_blob
|
103
103
|
l = @packet.getn(4).unpack('N')[0]
|
104
104
|
b = @packet.getn(l)
|
105
105
|
@packet.skip_padding
|
106
106
|
b
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
def bundle?
|
110
110
|
!(@packet.to_s =~ /\A\#bundle/).nil?
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
def string_delemeter
|
114
114
|
# ruby 1.9 has multicharacter support
|
115
115
|
RUBY_VERSION.include?( '1.9' ) ? "\x00" : 0
|
data/lib/osc-ruby/osc_types.rb
CHANGED
@@ -2,30 +2,22 @@ require File.join( File.dirname( __FILE__ ), "osc_argument" )
|
|
2
2
|
|
3
3
|
module OSC
|
4
4
|
class OSCInt32 < OSCArgument
|
5
|
-
|
6
5
|
def tag() 'i' end
|
7
6
|
def encode() [@val].pack('N') end
|
8
|
-
|
9
7
|
end
|
10
8
|
|
11
9
|
class OSCFloat32 < OSCArgument
|
12
|
-
|
13
10
|
def tag() 'f' end
|
14
11
|
def encode() [@val].pack('g') end # fake - why fake?
|
15
|
-
|
16
12
|
end
|
17
13
|
|
18
14
|
class OSCString < OSCArgument
|
19
|
-
|
20
15
|
def tag() 's' end
|
21
16
|
def encode() padding(@val.sub(/\000.*\z/, '') + "\000") end
|
22
|
-
|
23
17
|
end
|
24
18
|
|
25
19
|
class OSCBlob < OSCArgument
|
26
|
-
|
27
20
|
def tag() 'b' end
|
28
21
|
def encode() padding([@val.size].pack('N') + @val) end
|
29
|
-
|
30
22
|
end
|
31
23
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# sanity checks
|
2
|
+
require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
|
3
|
+
|
4
|
+
describe MessageBuilder do
|
5
|
+
before :each do
|
6
|
+
@builder = MessageBuilder.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "encodes just the address" do
|
10
|
+
mesg = @builder.with_address("/hi")
|
11
|
+
mesg.build.encode.should == "/hi\000,\000\000\000"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "encodes single int values" do
|
15
|
+
mesg = @builder.with_address("/hi").
|
16
|
+
with_int(33)
|
17
|
+
|
18
|
+
mesg.build.encode.should == "/hi\000,i\000\000\000\000\000!"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "encodes single string values" do
|
22
|
+
mesg = @builder.with_address("/hi").
|
23
|
+
with_string("hello")
|
24
|
+
|
25
|
+
mesg.build.encode.should == "/hi\000,s\000\000hello\000\000\000"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "encodes single float values" do
|
29
|
+
mesg = @builder.with_address("/hi").
|
30
|
+
with_float(3.14159)
|
31
|
+
|
32
|
+
mesg.build.encode.should == "/hi\000,f\000\000@I\017\320"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "encodes multiple floats" do
|
36
|
+
mesg = @builder.with_address("/hi").
|
37
|
+
with_float(3.14159).
|
38
|
+
with_float(4.5)
|
39
|
+
|
40
|
+
mesg.build.encode.should == [47, 104, 105, 0, 44, 102, 102, 0, 64, 73, 15, 208, 64, 144, 0, 0].pack("C*")
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/spec/unit/message_spec.rb
CHANGED
@@ -12,23 +12,47 @@ require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
|
|
12
12
|
|
13
13
|
|
14
14
|
describe OSC::Message do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
describe "basic traits" do
|
16
|
+
it "should have no arguments if you define none" do
|
17
|
+
m = OSC::Message.new( "/hi" )
|
18
|
+
m.to_a.should == []
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should accept int arguments" do
|
22
|
+
m = OSC::Message.new( "/hi", 42 )
|
23
|
+
m.to_a.should == [42]
|
24
|
+
m.tags.should == "i"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should accept string arguments" do
|
28
|
+
m = OSC::Message.new( "/hi", "42" )
|
29
|
+
m.to_a.should == ["42"]
|
30
|
+
m.tags.should == "s"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should accept float arguments" do
|
34
|
+
m = OSC::Message.new( "/hi", 42.001 )
|
35
|
+
m.to_a.should == [42.001]
|
36
|
+
m.tags.should == "f"
|
37
|
+
end
|
21
38
|
end
|
22
39
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
40
|
+
describe "more interesting traits" do
|
41
|
+
before :each do
|
42
|
+
@builder = MessageBuilder.new
|
43
|
+
@builder.with_int( 42 ).
|
44
|
+
with_int( 33 )
|
45
|
+
|
46
|
+
@message = @builder.build
|
47
|
+
end
|
27
48
|
|
28
|
-
|
29
|
-
m = OSC::Message.new( "/hi", 42 )
|
30
|
-
m.to_a.should == [42]
|
31
|
-
m.tags.should == "i"
|
32
|
-
end
|
49
|
+
|
33
50
|
|
51
|
+
it "should know equality" do
|
52
|
+
@message2 = @builder.build
|
53
|
+
|
54
|
+
@message.object_id.should_not == @message2.object_id
|
55
|
+
@message.should == @message2
|
56
|
+
end
|
57
|
+
end
|
34
58
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: osc-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- aberant
|
@@ -9,11 +9,11 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-03 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description:
|
16
|
+
description: a ruby client for the OSC protocol
|
17
17
|
email: qzzzq1@gmail.com
|
18
18
|
executables: []
|
19
19
|
|
@@ -38,11 +38,12 @@ files:
|
|
38
38
|
- lib/osc-ruby/osc_argument.rb
|
39
39
|
- lib/osc-ruby/osc_packet.rb
|
40
40
|
- lib/osc-ruby/osc_types.rb
|
41
|
-
- lib/osc-ruby/packet.rb
|
42
41
|
- lib/osc-ruby/server.rb
|
43
42
|
- README.rdoc
|
44
43
|
has_rdoc: true
|
45
44
|
homepage: http://github.com/aberant/osc-ruby
|
45
|
+
licenses: []
|
46
|
+
|
46
47
|
post_install_message:
|
47
48
|
rdoc_options:
|
48
49
|
- --charset=UTF-8
|
@@ -63,14 +64,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
64
|
requirements: []
|
64
65
|
|
65
66
|
rubyforge_project: osc-ruby
|
66
|
-
rubygems_version: 1.3.
|
67
|
+
rubygems_version: 1.3.5
|
67
68
|
signing_key:
|
68
|
-
specification_version:
|
69
|
+
specification_version: 3
|
69
70
|
summary: inital gem
|
70
71
|
test_files:
|
71
72
|
- spec/builders/message_builder.rb
|
72
73
|
- spec/spec_helper.rb
|
73
74
|
- spec/unit/address_pattern_spec.rb
|
75
|
+
- spec/unit/message_builder_spec.rb
|
74
76
|
- spec/unit/message_bundle_spec.rb
|
75
77
|
- spec/unit/message_spec.rb
|
76
78
|
- spec/unit/network_packet_spec.rb
|
data/lib/osc-ruby/packet.rb
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
module OSC
|
2
|
-
class Packet
|
3
|
-
|
4
|
-
class PO
|
5
|
-
def initialize(str)
|
6
|
-
@str, @index = str, 0
|
7
|
-
end
|
8
|
-
|
9
|
-
def rem()
|
10
|
-
@str.length - @index
|
11
|
-
end
|
12
|
-
|
13
|
-
def eof? ()
|
14
|
-
rem <= 0
|
15
|
-
end
|
16
|
-
|
17
|
-
def skip(n)
|
18
|
-
@index += n
|
19
|
-
end
|
20
|
-
|
21
|
-
def skip_padding()
|
22
|
-
skip((4 - (@index % 4)) % 4)
|
23
|
-
end
|
24
|
-
|
25
|
-
def getn(n)
|
26
|
-
raise EOFError if rem < n
|
27
|
-
s = @str[@index, n]
|
28
|
-
skip(n)
|
29
|
-
s
|
30
|
-
end
|
31
|
-
|
32
|
-
def getc
|
33
|
-
raise EOFError if rem < 1
|
34
|
-
c = @str[@index]
|
35
|
-
skip(1)
|
36
|
-
c
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.decode_int32(io)
|
41
|
-
i = io.getn(4).unpack('N')[0]
|
42
|
-
i -= 2**32 if i > (2**31-1)
|
43
|
-
i
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.decode_float32(io)
|
47
|
-
f = io.getn(4).unpack('g')[0]
|
48
|
-
f
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.decode_string(io)
|
52
|
-
s = ''
|
53
|
-
until (c = io.getc) == 0
|
54
|
-
s << c
|
55
|
-
end
|
56
|
-
io.skip_padding
|
57
|
-
s
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.decode_blob(io)
|
61
|
-
l = io.getn(4).unpack('N')[0]
|
62
|
-
b = io.getn(l)
|
63
|
-
io.skip_padding
|
64
|
-
b
|
65
|
-
end
|
66
|
-
|
67
|
-
def self.decode_timetag(io)
|
68
|
-
t1 = io.getn(4).unpack('N')[0]
|
69
|
-
t2 = io.getn(4).unpack('N')[0]
|
70
|
-
[t1, t2]
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.decode2(time, packet, list)
|
74
|
-
io = PO.new(packet)
|
75
|
-
id = decode_string(io)
|
76
|
-
if id =~ /\A\#/
|
77
|
-
if id == '#bundle'
|
78
|
-
t1, t2 = decode_timetag(io)
|
79
|
-
if t1 == 0 && t2 == 1
|
80
|
-
time = nil
|
81
|
-
else
|
82
|
-
time = t1 + t2.to_f / (2**32)
|
83
|
-
end
|
84
|
-
until io.eof?
|
85
|
-
l = io.getn(4).unpack('N')[0]
|
86
|
-
s = io.getn(l)
|
87
|
-
decode2(time, s, list)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
elsif id =~ /\//
|
91
|
-
address = id
|
92
|
-
if io.getc == ?,
|
93
|
-
tags = decode_string(io)
|
94
|
-
args = []
|
95
|
-
tags.scan(/./) do |t|
|
96
|
-
case t
|
97
|
-
when 'i'
|
98
|
-
i = decode_int32(io)
|
99
|
-
args << OSCInt32.new(i)
|
100
|
-
when 'f'
|
101
|
-
f = decode_float32(io)
|
102
|
-
args << OSCFloat32.new(f)
|
103
|
-
when 's'
|
104
|
-
s = decode_string(io)
|
105
|
-
args << OSCString.new(s)
|
106
|
-
when 'b'
|
107
|
-
b = decode_blob(io)
|
108
|
-
args << OSCBlob.new(b)
|
109
|
-
when /[htd]/; io.read(8)
|
110
|
-
when 'S'; decode_string(io)
|
111
|
-
when /[crm]/; io.read(4)
|
112
|
-
when /[TFNI\[\]]/;
|
113
|
-
end
|
114
|
-
end
|
115
|
-
list << [time, Message.new(address, nil, *args)]
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
private_class_method :decode_int32,
|
121
|
-
:decode_float32,
|
122
|
-
:decode_string,
|
123
|
-
:decode_blob,
|
124
|
-
:decode_timetag,
|
125
|
-
:decode2
|
126
|
-
|
127
|
-
def self.decode(packet)
|
128
|
-
list = []
|
129
|
-
decode2(nil, packet, list)
|
130
|
-
list
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
end
|