tuio-ruby 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Colin Harris
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,23 @@
1
+ = A TUIO client for Ruby
2
+
3
+ http://www.tuio.org/
4
+
5
+ == REQUIREMENTS:
6
+
7
+ You will need the OSC gem
8
+
9
+ [sudo] gem install osc
10
+
11
+ == INSTALL:
12
+
13
+ [sudo] gem install aberant-tuio-ruby
14
+
15
+ == EXAMPLE:
16
+
17
+ please see tuio_dump.rb in the example folder for basic useage
18
+
19
+ == COPYRIGHT:
20
+
21
+ Copyright (c) 2009 Colin Harris. See LICENSE for details.
22
+
23
+
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ require 'spec/rake/spectask'
2
+
3
+
4
+ task :default => :spec
5
+
6
+ Spec::Rake::SpecTask.new do |t|
7
+ t.warning = false
8
+ t.rcov = false
9
+ t.spec_opts = ["--colour"]#, "--diff"]
10
+ end
11
+
12
+ require 'rake/rdoctask'
13
+ Rake::RDocTask.new do |rdoc|
14
+ if File.exist?('VERSION')
15
+ version = File.read('VERSION')
16
+ else
17
+ version = ""
18
+ end
19
+
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = "tuio-ruby #{version}"
22
+ rdoc.rdoc_files.include('README*')
23
+ rdoc.rdoc_files.include('lib/**/*.rb')
24
+ end
25
+
26
+ begin
27
+ require 'jeweler'
28
+ Jeweler::Tasks.new do |gem|
29
+ gem.name = "tuio-ruby"
30
+ gem.summary = %Q{library to interface with TUIO protocol}
31
+ gem.email = "qzzzq1@gmail.com"
32
+ gem.homepage = "http://github.com/aberant/tuio-ruby"
33
+ gem.authors = ["aberant"]
34
+ gem.files = FileList['Rakefile', 'examples/**/*', 'lib/**/*'].to_a
35
+ gem.test_files = FileList['spec/**/*.rb']
36
+ gem.add_dependency('osc-ruby', '>= 0.1.6')
37
+ gem.rubyforge_project = "tuio-ruby"
38
+
39
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
40
+ end
41
+
42
+ Jeweler::RubyforgeTasks.new do |rubyforge|
43
+ rubyforge.doc_task = "rdoc"
44
+ end
45
+ rescue LoadError
46
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
47
+ end
@@ -0,0 +1,32 @@
1
+ require File.join( File.dirname( __FILE__ ), '..', 'lib', 'tuio-ruby' )
2
+
3
+
4
+ @tc = TuioClient.new
5
+
6
+ @tc.on_object_creation do | to |
7
+ puts "New TUIO Object at x: #{to.x_pos}, y: #{to.y_pos}"
8
+ end
9
+
10
+ @tc.on_object_update do | to |
11
+ puts "Updated TUIO Object #{to.fiducial_id} at x: #{to.x_pos}, y: #{to.y_pos}"
12
+ end
13
+
14
+ @tc.on_object_removal do | to |
15
+ puts "Removed TUIO Object #{to.fiducial_id}"
16
+ end
17
+
18
+
19
+ @tc.on_cursor_creation do | to |
20
+ puts "New TUIO Cursor at x: #{to.x_pos}, y: #{to.y_pos}"
21
+ end
22
+
23
+ @tc.on_cursor_update do | to |
24
+ puts "Updated TUIO Cursor #{to.session_id} at x: #{to.x_pos}, y: #{to.y_pos}"
25
+ end
26
+
27
+ @tc.on_cursor_removal do | to |
28
+ puts "Removed TUIO Cursor #{to.session_id}"
29
+ end
30
+
31
+ @tc.start
32
+ sleep
@@ -0,0 +1,5 @@
1
+ class Float
2
+ def approx_equal?(other,threshold=0.00000000001)
3
+ (self-other).abs < threshold
4
+ end
5
+ end
@@ -0,0 +1,30 @@
1
+ # this is a little meta magic to clean up some of the repetition in the client
2
+ # i noticed that i kept making the same similiar methods for each event such as
3
+ #
4
+ # client_events :object_creation
5
+ #
6
+ # which causes these two methods to be created
7
+
8
+ # def on_object_creation( &object_creation_blk )
9
+ # @object_creation_callback_blk = object_creation_blk
10
+ # end
11
+ #
12
+ # def trigger_object_creation_callback( tuio )
13
+ # @object_creation_callback_blk.call( tuio ) if @object_creation_callback_blk
14
+ # end
15
+
16
+ class Object
17
+ def client_events( *args )
18
+ args.each do | event |
19
+ self.class_eval <<-EOF
20
+ def on_#{event}( &#{event}_blk )
21
+ @#{event}_callback_blk = #{event}_blk
22
+ end
23
+
24
+ def trigger_#{event}_callback( tuio )
25
+ @#{event}_callback_blk.call( tuio ) if @#{event}_callback_blk
26
+ end
27
+ EOF
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,168 @@
1
+ require 'rubygems'
2
+ require 'osc-ruby'
3
+
4
+ # core exts
5
+ require 'core_ext/object'
6
+ require 'core_ext/float'
7
+
8
+ class TuioClient
9
+ include OSC
10
+
11
+ attr_reader :tuio_objects, :tuio_cursors
12
+
13
+
14
+ client_events :object_creation, :object_update, :object_removal
15
+ client_events :cursor_creation, :cursor_update, :cursor_removal
16
+
17
+ def initialize( args = {} )
18
+ @port = args[:port] || 3333
19
+
20
+ @tuio_objects = { }
21
+ @tuio_cursors = { }
22
+
23
+ @osc = OSC::Server.new(@port)
24
+
25
+ @osc.add_method '/tuio/2Dobj' do |msg|
26
+ args = msg.to_a
27
+
28
+ case args.shift
29
+ when "set"
30
+ track_tuio_object( args )
31
+ when "alive"
32
+ keep_alive( :tuio_objects, args )
33
+ when "fseq"
34
+ # puts args
35
+ end
36
+ end
37
+
38
+ @osc.add_method '/tuio/2Dcur' do |msg|
39
+ args = msg.to_a
40
+
41
+ case args.shift
42
+ when "set"
43
+ track_tuio_cursor args
44
+ when "alive"
45
+ keep_alive( :tuio_cursors, args )
46
+ when "fseq"
47
+ # puts args
48
+ end
49
+ end
50
+ end
51
+
52
+ def start
53
+ Thread.new do
54
+ @osc.run
55
+ end
56
+ end
57
+
58
+ ####################################
59
+ # getters #
60
+ ####################################
61
+
62
+ def tuio_object( id )
63
+ @tuio_objects[id]
64
+ end
65
+
66
+ def tuio_cursor( id )
67
+ @tuio_cursors[id]
68
+ end
69
+
70
+ private
71
+
72
+ def track_tuio_object( args )
73
+ params = TuioObjectParameter.new( *args )
74
+
75
+ if tuio_object_previously_tracked?( params )
76
+
77
+ tuio_object = grab_tuio_object_by( params.session_id )
78
+
79
+ return if tuio_object.params_equal?( params )
80
+
81
+ tuio_object.update_from_params( params )
82
+
83
+ trigger_object_update_callback( tuio_object )
84
+ else # this is a new object
85
+ tuio_object = track_new_tuio_object_with( params )
86
+
87
+ trigger_object_creation_callback( tuio_object )
88
+ end
89
+ end
90
+
91
+ def track_tuio_cursor( args )
92
+ params = TuioCursorParameter.new( *args )
93
+
94
+ if tuio_cursor_previously_tracked?( params )
95
+
96
+ tuio_cursor = grab_tuio_cursor_by( params.session_id )
97
+
98
+ return if tuio_cursor.params_equal?( params )
99
+ tuio_cursor.update_from_params( params )
100
+
101
+ trigger_cursor_update_callback( tuio_cursor )
102
+
103
+ else # this is a new cursor
104
+ finger_id = @tuio_cursors.size
105
+ tuio_cursor = track_new_tuio_cursor_with( params )
106
+
107
+ trigger_cursor_creation_callback( tuio_cursor )
108
+ end
109
+ end
110
+
111
+ def tuio_object_previously_tracked?( params )
112
+ @tuio_objects.has_key?( params.session_id )
113
+ end
114
+
115
+ def tuio_cursor_previously_tracked?( params )
116
+ @tuio_cursors.has_key?( params.session_id )
117
+ end
118
+
119
+ def grab_tuio_object_by( session_id )
120
+ @tuio_objects[session_id]
121
+ end
122
+
123
+ def grab_tuio_cursor_by( session_id )
124
+ @tuio_cursors[session_id]
125
+ end
126
+
127
+ def track_new_tuio_object_with( tuio_params )
128
+ @tuio_objects[tuio_params.session_id] = TuioObject.from_params( tuio_params )
129
+ end
130
+
131
+ def track_new_tuio_cursor_with( params )
132
+ new_cursor = TuioCursor.from_params( params )
133
+ @tuio_cursors[params.session_id] = new_cursor
134
+
135
+ new_cursor.finger_id = @tuio_cursors.size
136
+ new_cursor
137
+ end
138
+
139
+ ####################################
140
+ # "alive" msgs #
141
+ ####################################
142
+
143
+ def delete_tuio_objects( session_id )
144
+ tuio_object = grab_tuio_object_by( session_id )
145
+
146
+ trigger_object_removal_callback( tuio_object )
147
+ end
148
+
149
+ def delete_tuio_cursors( session_id )
150
+ tuio_cursor = grab_tuio_cursor_by( session_id )
151
+
152
+ trigger_cursor_removal_callback( tuio_cursor )
153
+ end
154
+
155
+
156
+ def keep_alive( type, session_ids )
157
+ return if session_ids.nil?
158
+ all_keys = send( type ).keys
159
+
160
+ dead = all_keys.reject { |key| session_ids.include? key }
161
+
162
+ dead.each do | session_id |
163
+ send( "delete_#{type}", session_id )
164
+
165
+ send( type ).delete( session_id )
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,63 @@
1
+ require File.join( File.dirname( __FILE__ ), 'tuio_point' )
2
+
3
+ class TuioContainer < TuioPoint
4
+ attr_accessor :session_id, :x_pos, :y_pos, :x_speed, :y_speed, :motion_accel
5
+
6
+
7
+ def initialize( session_id, x_pos, y_pos )
8
+ super( x_pos, y_pos )
9
+
10
+ @session_id = session_id
11
+ @x_speed = 0.0
12
+ @y_speed = 0.0
13
+ @motion_accel = 0.0
14
+
15
+ add_point_to_path( TuioPoint.new( x_pos, y_pos ) )
16
+ end
17
+
18
+ def update( x_pos, y_pos, x_speed, y_speed, motion_accel )
19
+ super( x_pos, y_pos )
20
+
21
+ @x_speed = x_speed
22
+ @y_speed = y_speed
23
+ @motion_accel = motion_accel
24
+
25
+ new_point = TuioPoint.new( x_pos, y_pos )
26
+ add_point_to_path( new_point ) unless new_point == @path.last
27
+ end
28
+
29
+ def update_from_params( params )
30
+ @x_pos = params.x_pos
31
+ @y_pos = params.y_pos
32
+ @x_speed = params.x_speed
33
+ @y_speed = params.y_speed
34
+ @motion_accel = params.motion_accel
35
+ end
36
+
37
+ def path
38
+ @path
39
+ end
40
+
41
+
42
+ def params_equal?( params )
43
+ @session_id == params.session_id &&
44
+ @x_pos.approx_equal?( params.x_pos ) &&
45
+ @y_pos.approx_equal?( params.y_pos ) &&
46
+ @x_speed.approx_equal?( params.x_speed ) &&
47
+ @y_speed.approx_equal?( params.y_speed ) &&
48
+ @motion_accel.approx_equal?( params.motion_accel ) &&
49
+ equal_to_local_params?( params )
50
+ end
51
+
52
+ def equal_to_local_args?(args)
53
+ true
54
+ end
55
+
56
+ private
57
+
58
+ def add_point_to_path( tuio_point )
59
+ @path ||= []
60
+ @path << tuio_point
61
+ end
62
+ end
63
+
@@ -0,0 +1,28 @@
1
+ require File.join( File.dirname( __FILE__ ), 'tuio_container' )
2
+
3
+ class TuioCursor < TuioContainer
4
+
5
+ attr_accessor :finger_id
6
+ attr_reader :x_speed, :y_speed, :motion_accel
7
+
8
+ def self.from_params( params )
9
+ new( params.session_id,
10
+ params.x_pos,
11
+ params.y_pos
12
+ )
13
+ end
14
+
15
+ def initialize( session_id, x_pos, y_pos )
16
+ super( session_id, x_pos, y_pos )
17
+
18
+ @x_speed = 0.0
19
+ @y_speed = 0.0
20
+ @motion_accel = 0.0
21
+ end
22
+
23
+
24
+ def equal_to_local_params?( params )
25
+ true
26
+ end
27
+
28
+ end
@@ -0,0 +1,7 @@
1
+ require File.join( File.dirname( __FILE__ ), 'tuio_parameter' )
2
+
3
+ # /tuio/2Dcur set s x y X Y m
4
+
5
+ class TuioCursorParameter < TuioParameter
6
+
7
+ end
@@ -0,0 +1,53 @@
1
+ require File.join( File.dirname( __FILE__ ), 'tuio_container' )
2
+
3
+ class TuioObject < TuioContainer
4
+ attr_reader :angle, :fiducial_id, :rotation_vector, :rotation_accel
5
+
6
+ def self.from_params( params )
7
+ new(
8
+ params.session_id,
9
+ params.fiducial_id,
10
+ params.x_pos,
11
+ params.y_pos,
12
+ params.angle
13
+ )
14
+ end
15
+
16
+
17
+ def initialize( session_id, fiducial_id, x_pos, y_pos, angle )
18
+ super( session_id, x_pos, y_pos )
19
+
20
+ @fiducial_id = fiducial_id
21
+ @angle = angle
22
+
23
+ @rotation_vector = 0.0
24
+ @rotation_accel = 0.0
25
+ end
26
+
27
+ def update_from_params( tuio_params )
28
+ update(
29
+ tuio_params.x_pos,
30
+ tuio_params.y_pos,
31
+ tuio_params.angle,
32
+ tuio_params.x_speed,
33
+ tuio_params.y_speed,
34
+ tuio_params.rotation_vector,
35
+ tuio_params.motion_accel,
36
+ tuio_params.rotation_accel
37
+ )
38
+ end
39
+
40
+ def update( x_pos, y_pos, angle, x_speed, y_speed, rotation_vector, motion_accel, rotation_accel )
41
+ super( x_pos, y_pos, x_speed, y_speed, motion_accel )
42
+
43
+ @angle = angle
44
+ @rotation_vector = rotation_vector
45
+ @rotation_accel = rotation_accel
46
+ end
47
+
48
+ def equal_to_local_params?( params )
49
+ fiducial_id == params.fiducial_id &&
50
+ rotation_vector.approx_equal?( params.rotation_vector ) &&
51
+ rotation_accel.approx_equal?( params.rotation_accel )
52
+ end
53
+ end
@@ -0,0 +1,17 @@
1
+ require File.join( File.dirname( __FILE__ ), 'tuio_parameter' )
2
+
3
+ # /tuio/2Dobj set s i x y a X Y A m r
4
+
5
+
6
+ class TuioObjectParameter < TuioParameter
7
+ attr_reader :angle, :fiducial_id, :rotation_vector, :rotation_accel
8
+
9
+ def initialize( session_id, fiducial_id, x_pos, y_pos, angle, x_speed, y_speed, rotation_vector, motion_accel, rotation_accel )
10
+ super( session_id, x_pos, y_pos, x_speed, y_speed, motion_accel )
11
+
12
+ @fiducial_id = fiducial_id
13
+ @angle = angle
14
+ @rotation_vector = rotation_vector
15
+ @rotation_accel = rotation_accel
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ class TuioParameter
2
+ attr_accessor :session_id, :x_pos, :y_pos, :x_speed, :y_speed, :motion_accel
3
+
4
+ def self.new_from_initial_params( session_id, x_pos, y_pos )
5
+ new session_id, x_pos, y_pos, 0.0, 0.0, 00
6
+ end
7
+
8
+ def initialize( session_id, x_pos, y_pos, x_speed, y_speed, motion_accel )
9
+ @session_id = session_id
10
+ @x_pos = x_pos
11
+ @y_pos = y_pos
12
+ @x_speed = x_speed
13
+ @y_speed = y_speed
14
+ @motion_accel = motion_accel
15
+ end
16
+ end
@@ -0,0 +1,45 @@
1
+ class TuioPoint
2
+ attr_accessor :x_pos, :y_pos, :updated_at
3
+
4
+ def initialize( x_pos, y_pos )
5
+ @x_pos, @y_pos = x_pos, y_pos
6
+ end
7
+
8
+ def update( x_pos, y_pos )
9
+ @x_pos, @y_pos = x_pos, y_pos
10
+
11
+ clear_update_time
12
+ end
13
+
14
+ def distance_to( another_point )
15
+ dx = @x_pos - another_point.x_pos
16
+ dy = @y_pos - another_point.y_pos
17
+
18
+ Math.sqrt( dx*dx + dy*dy )
19
+ end
20
+
21
+ def radians_to( another_point )
22
+ side = another_point.x_pos - @x_pos
23
+ height = another_point.y_pos - @y_pos
24
+ distance = distance_to( another_point )
25
+
26
+ angle = Math.asin( side / distance ) + Math::PI / 2
27
+ angle = 2.0 * Math.PI - angle if height < 0
28
+ angle
29
+ end
30
+
31
+ def degrees_to( another_point )
32
+ ( radians_to( another_point ) / Math::PI ) * 180.0
33
+ end
34
+
35
+ def eql?( another_point )
36
+ @x_pos == another_point.x_pos &&
37
+ @y_pos == another_point.y_pos
38
+ end
39
+
40
+ private
41
+
42
+ def clear_update_time
43
+ @updated_at = nil
44
+ end
45
+ end
data/lib/tuio-ruby.rb ADDED
@@ -0,0 +1,12 @@
1
+ $: << File.dirname( __FILE__ )
2
+
3
+ require 'tuio-ruby/tuio_cursor_parameter'
4
+ require 'tuio-ruby/tuio_object_parameter'
5
+
6
+ require 'tuio-ruby/tuio_container'
7
+ require 'tuio-ruby/tuio_cursor'
8
+ require 'tuio-ruby/tuio_object'
9
+
10
+ require 'tuio-ruby/tuio_client'
11
+
12
+
@@ -0,0 +1,165 @@
1
+ require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
+
3
+ describe "tuio object" do
4
+ before :each do
5
+ setup_server
6
+ end
7
+
8
+ describe "in general" do
9
+ it "should call the creation hook" do
10
+ @server.on_object_creation do | object |
11
+ raise "creation hook called!" if object.session_id == 49
12
+ end
13
+
14
+ lambda {
15
+ send_message( '/tuio/2Dobj', "set", 49, 25, 0.38, 0.35, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
16
+ }.should raise_error
17
+
18
+ lambda {
19
+ send_message( '/tuio/2Dobj', "set", 49, 25, 0.38, 0.35, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
20
+ }.should_not raise_error
21
+ end
22
+
23
+ it "should call the update hook when session_id is set again with different location" do
24
+ @server.on_object_update do | object |
25
+ raise "update hook called!" if object.session_id == 49
26
+ end
27
+
28
+ lambda {
29
+ # this one calls the create hook
30
+ send_message( '/tuio/2Dobj', "set", 49, 25, 0.38, 0.35, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
31
+ send_message( '/tuio/2Dobj', "alive", 49)
32
+
33
+ #this one is the same as before, so nothing to update
34
+ send_message( '/tuio/2Dobj', "set", 49, 25, 0.38, 0.35, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
35
+ send_message( '/tuio/2Dobj', "alive", 49)
36
+ }.should_not raise_error
37
+
38
+
39
+ lambda {
40
+ #this one calls the update hook
41
+ send_message( '/tuio/2Dobj', "set", 49, 25, 0.12, 0.12, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
42
+ send_message( '/tuio/2Dobj', "alive", 49)
43
+
44
+ }.should raise_error
45
+ end
46
+
47
+ it "should call the removal hook when an object is not on the alive list" do
48
+ @server.on_object_removal do | object |
49
+ raise "removal hook called!" if object.session_id == 51
50
+ end
51
+
52
+ send_message( '/tuio/2Dobj', "set", 49, 25, 0.38, 0.35, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
53
+ send_message( '/tuio/2Dobj', "set", 51, 26, 0.12, 0.50, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
54
+
55
+ lambda {
56
+ send_message( '/tuio/2Dobj', "alive", 49)
57
+ }.should raise_error
58
+
59
+ end
60
+ end
61
+
62
+ describe "receiving message" do
63
+ before :each do
64
+ send_message( '/tuio/2Dobj', "set", 49, 25, 0.38, 0.35, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
65
+ end
66
+
67
+ describe "set" do
68
+ it 'should update tracking' do
69
+ @server.tuio_objects.size.should eql( 1 )
70
+ @server.tuio_objects[49].fiducial_id.should == 25
71
+ end
72
+ end
73
+
74
+ describe "alive" do
75
+ it 'should only keep alive the objects the client says are alive' do
76
+ send_message( '/tuio/2Dobj', "set", 51, 26, 0.12, 0.50, 3.14, 0.0, 0.0, 0.0, 0.0, 0.0 )
77
+ send_message( '/tuio/2Dobj', "alive", 49)
78
+
79
+ @server.tuio_objects.size.should == 1
80
+ end
81
+ end
82
+
83
+ describe "fseq" do
84
+ it "should probably have a test!"
85
+ end
86
+ end
87
+ end
88
+
89
+ describe "tuio_cursors" do
90
+ before :each do
91
+ setup_server
92
+ end
93
+
94
+ it 'should update tracking' do
95
+ send_message( '/tuio/2Dcur', "set", 22, 0.38, 0.35, 0.0, 0.0, 0.0 )
96
+
97
+ @server.tuio_cursors.size.should == 1
98
+ end
99
+
100
+ it 'should update tracking for multiples' do
101
+ send_message( '/tuio/2Dcur', "set", 22, 0.38, 0.35, 0.0, 0.0, 0.0 )
102
+ send_message( '/tuio/2Dcur', "set", 27, 0.12, 0.50, 0.0, 0.0, 0.0 )
103
+
104
+
105
+ @server.tuio_cursors.size.should == 2
106
+ end
107
+
108
+ it 'should only keep alive the cursors the client says are alive' do
109
+ send_message( '/tuio/2Dcur', "set", 22, 0.38, 0.35, 0.0, 0.0, 0.0 )
110
+ send_message( '/tuio/2Dcur', "set", 27, 0.12, 0.50, 0.0, 0.0, 0.0 )
111
+
112
+ send_message( '/tuio/2Dcur', "alive", 22)
113
+
114
+ @server.tuio_cursors.size.should == 1
115
+ @server.tuio_cursors[22].session_id.should == 22
116
+ end
117
+
118
+ it "should call the creation hooks" do
119
+ @server.on_cursor_creation do | objects |
120
+ raise "create! hook called!"
121
+ end
122
+
123
+ lambda {
124
+ send_message( '/tuio/2Dcur', "set", 27, 0.12, 0.50, 0.0, 0.0, 0.0 )
125
+ }.should raise_error
126
+ end
127
+
128
+ it "should call the update hooks" do
129
+ @server.on_cursor_update do | objects |
130
+ raise "update hook called!"
131
+ end
132
+
133
+ lambda {
134
+ send_message( '/tuio/2Dcur', "set", 27, 0.12, 0.50, 0.0, 0.0, 0.0 )
135
+ send_message( '/tuio/2Dcur', "alive", 27)
136
+
137
+ send_message( '/tuio/2Dcur', "set", 27, 0.12, 0.50, 0.0, 0.0, 0.0 )
138
+ send_message( '/tuio/2Dcur', "alive", 27)
139
+
140
+ }.should_not raise_error
141
+
142
+ lambda {
143
+ send_message( '/tuio/2Dcur', "set", 27, 0.12, 0.32, 0.0, 0.0, 0.0 )
144
+ send_message( '/tuio/2Dcur', "alive", 27)
145
+
146
+ }.should raise_error
147
+
148
+ end
149
+
150
+ it "should call the removal hooks" do
151
+ @server.on_cursor_removal do | objects |
152
+ raise "removal hook called!"
153
+ end
154
+
155
+ lambda {
156
+ send_message( '/tuio/2Dcur', "set", 27, 0.12, 0.50, 0.0, 0.0, 0.0 )
157
+ send_message( '/tuio/2Dcur', "set", 32, 0.18, 0.98, 0.0, 0.0, 0.0 )
158
+ }.should_not raise_error
159
+
160
+ lambda {
161
+ send_message( '/tuio/2Dcur', "alive", 27)
162
+
163
+ }.should raise_error
164
+ end
165
+ end
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'rr'
4
+ require 'osc'
5
+
6
+ $: << File.join( File.dirname( __FILE__ ), '..', 'lib' )
7
+
8
+ require 'tuio-ruby'
9
+
10
+ Spec::Runner.configure do |config|
11
+ config.mock_with RR::Adapters::Rspec
12
+ end
13
+
14
+ # monkey patch to get at osc core to send messages
15
+ class TuioClient
16
+ def osc
17
+ @osc
18
+ end
19
+ end
20
+
21
+ # helper method for integration tests
22
+ def send_message( pattern, *msg )
23
+ osc_msg = OSC::Message.new( pattern, nil, *msg)
24
+
25
+ @server.osc.send( :sendmesg, osc_msg )
26
+ end
27
+
28
+ def setup_server
29
+ mock( socket = Object.new )
30
+
31
+ # stub out networking
32
+ stub(socket).bind("", 3333)
33
+ stub(UDPSocket).new { socket }
34
+
35
+ @server = TuioClient.new
36
+ end
@@ -0,0 +1,74 @@
1
+ # require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
+ #
3
+ # class TuioContainer
4
+ # # we want to be able to instantiate this class for testing
5
+ # def self.abstract?
6
+ # false
7
+ # end
8
+ # end
9
+ #
10
+ # describe TuioContainer do
11
+ # before :each do
12
+ # @session_id = 42
13
+ # @x_pos = 0.8
14
+ # @y_pos = 0.3
15
+ # @tc = TuioContainer.new( @session_id, @x_pos, @y_pos )
16
+ # end
17
+ #
18
+ # describe "in general" do
19
+ # it "should know it's session id" do
20
+ # @tc.session_id.should == @session_id
21
+ # end
22
+ #
23
+ # it "should know it's x position" do
24
+ # @tc.x_pos.should == @x_pos
25
+ # end
26
+ #
27
+ # it "should know its y position" do
28
+ # @tc.y_pos.should == @y_pos
29
+ # end
30
+ # end
31
+ #
32
+ # describe "updates" do
33
+ # before :each do
34
+ # @x_pos2 = 0.7
35
+ # @y_pos2 = 0.4
36
+ # @x_speed = 0.1
37
+ # @y_speed = 0.1
38
+ # @motion_accel = 0.1
39
+ #
40
+ # @tc.update( @x_pos2, @y_pos2, @x_speed, @y_speed, @motion_accel )
41
+ # end
42
+ #
43
+ # it "should know it's new x position" do
44
+ # @tc.x_pos.should == @x_pos2
45
+ # end
46
+ #
47
+ # it "should know it's new y position" do
48
+ # @tc.y_pos.should == @y_pos2
49
+ # end
50
+ #
51
+ # it "should know it's x speed" do
52
+ # @tc.x_speed.should == @x_speed
53
+ # end
54
+ #
55
+ # it "should know it's y speed" do
56
+ # @tc.y_speed.should == @y_speed
57
+ # end
58
+ #
59
+ # it "should know it's motion acceleration" do
60
+ # @tc.motion_accel.should == @motion_accel
61
+ # end
62
+ #
63
+ # it "should know the path it's traveled" do
64
+ # first = @tc.path.first
65
+ # second = @tc.path.last
66
+ #
67
+ # first.x_pos.should == 0.8
68
+ # first.y_pos.should == 0.3
69
+ #
70
+ # second.x_pos.should == 0.7
71
+ # second.y_pos.should == 0.4
72
+ # end
73
+ # end
74
+ # end
@@ -0,0 +1,39 @@
1
+ require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
+ require File.join( File.dirname(__FILE__) , 'tuio_parameter_spec' )
3
+
4
+ # /tuio/2Dcur set s x y X Y m
5
+
6
+ describe TuioObjectParameter do
7
+ describe "cursor creation" do
8
+ before :each do
9
+ args = [ @session_id = 12,
10
+ @x_pos = 0.1,
11
+ @y_pos = 0.2]
12
+
13
+ @tuio_param = TuioCursorParameter.new_from_initial_params( *args )
14
+ end
15
+ it "should have propper values set" do
16
+ @tuio_param.session_id == @session_id
17
+ @tuio_param.x_pos == @x_pos
18
+ @tuio_param.y_pos == @y_pos
19
+ end
20
+ end
21
+
22
+ describe "in general" do
23
+ before :each do
24
+ args = [
25
+ @session_id = 12,
26
+ @x_pos = 0.1,
27
+ @y_pos = 0.2,
28
+ @x_speed = 0.01,
29
+ @y_speed = 0.02,
30
+ @motion_accel = 0.03,
31
+ ]
32
+
33
+ @tuio_param = TuioCursorParameter.new( *args )
34
+ end
35
+
36
+ it_should_behave_like "TuioParameter"
37
+ end
38
+
39
+ end
@@ -0,0 +1,35 @@
1
+ require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
+
3
+ describe TuioCursor do
4
+ before :each do
5
+ @args1 = [
6
+ @session_id = 42,
7
+ @x_pos = 0.8,
8
+ @y_pos = 0.4,
9
+ @x_speed = 0.01,
10
+ @y_speed = 0.03,
11
+ @motion_accel = 0.02
12
+ ]
13
+ @params = TuioCursorParameter.new( *@args1 )
14
+ @tc = TuioCursor.from_params( @params )
15
+ end
16
+
17
+ describe "update" do
18
+ before :each do
19
+ @args2 = [
20
+ @session_id = 42,
21
+ @x_pos2 = 0.23,
22
+ @y_pos2 = 0.54,
23
+ @x_speed = 0.01,
24
+ @y_speed = 0.03,
25
+ @motion_accel = 0.02
26
+ ]
27
+ @update_params = TuioCursorParameter.new( *@args2 )
28
+ @tc.update_from_params( @update_params )
29
+ end
30
+
31
+ it "should it is equal to some arguments" do
32
+ @tc.params_equal?( @update_params )
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,41 @@
1
+ require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
+ require File.join( File.dirname(__FILE__) , 'tuio_parameter_spec' )
3
+
4
+ # /tuio/2Dobj set s i x y a X Y A m r
5
+ # /tuio/2Dcur set s x y X Y m
6
+ #def initialize( session_id, fiducial_id, x_pos, y_pos, angle,
7
+ # x_speed, y_speed, rotation_vector, motion_accel, rotation_accel )
8
+
9
+ describe TuioObjectParameter do
10
+
11
+ before :each do
12
+ args = [
13
+ @session_id = 12,
14
+ @fiducial_id = 41,
15
+ @x_pos = 0.1,
16
+ @y_pos = 0.2,
17
+ @angle = 3,
18
+ @x_speed = 0.01,
19
+ @y_speed = 0.02,
20
+ @rotation_vector = 0.4,
21
+ @motion_accel = 0.03,
22
+ @rotation_accel = 0.02
23
+ ]
24
+
25
+ @tuio_param = TuioObjectParameter.new( *args )
26
+ end
27
+
28
+ it_should_behave_like "TuioParameter"
29
+
30
+ it "should fetch angle" do
31
+ @tuio_param.angle.should == @angle
32
+ end
33
+
34
+ it "should fetch rotation vector" do
35
+ @tuio_param.rotation_vector.should == @rotation_vector
36
+ end
37
+
38
+ it "should fetch rotation acceleration" do
39
+ @tuio_param.rotation_accel.should == @rotation_accel
40
+ end
41
+ end
@@ -0,0 +1,94 @@
1
+ require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
+
3
+ describe TuioObject do
4
+ before :each do
5
+ @args1 = [
6
+ @session_id = 42,
7
+ @fiducial_id = 1,
8
+ @x_pos = 0.8,
9
+ @y_pos = 0.4,
10
+ @angle = 1,
11
+ @x_speed = 0.1,
12
+ @y_speed = 0.2,
13
+ @rotation_vector = 0.11,
14
+ @motion_accel = 0.12,
15
+ @rotation_accel = 0.13
16
+ ]
17
+ @params = TuioObjectParameter.new( *@args1 )
18
+ @to = TuioObject.from_params( @params )
19
+ end
20
+
21
+ describe "in general" do
22
+ it "should know it's session id" do
23
+ @to.session_id.should == @session_id
24
+ end
25
+
26
+ it "should know it's fiducial id" do
27
+ @to.fiducial_id.should == @fiducial_id
28
+ end
29
+
30
+ it "should know it's x position" do
31
+ @to.x_pos.should == @x_pos
32
+ end
33
+
34
+ it "should know it's y postion" do
35
+ @to.y_pos.should == @y_pos
36
+ end
37
+
38
+ it "should know it's angle" do
39
+ @to.angle.should == @angle
40
+ end
41
+ end
42
+
43
+ describe "on update" do
44
+
45
+ before :each do
46
+ @args2 = [
47
+ @sesssion_id = 42,
48
+ @fiducial_id = 1,
49
+ @x_pos2 = 0.7,
50
+ @y_pos2 = 0.4,
51
+ @angle2 = 1.1,
52
+ @x_speed = 0.1,
53
+ @y_speed = 0.2,
54
+ @rotation_vector = 0.11,
55
+ @motion_accel = 0.12,
56
+ @rotation_accel = 0.13
57
+ ]
58
+ @update_params = TuioObjectParameter.new( *@args2 )
59
+ @to.update_from_params( @update_params )
60
+ end
61
+
62
+ it "should be able to compare it's args" do
63
+ @to.params_equal?( @update_params ).should be_true
64
+ end
65
+
66
+ it "should know it's new x position" do
67
+ @to.x_pos.should == @x_pos2
68
+ end
69
+
70
+ it "should know it's new y position" do
71
+ @to.y_pos.should == @y_pos2
72
+ end
73
+
74
+ it "should know it's new angle" do
75
+ @to.angle.should == @angle2
76
+ end
77
+
78
+ it "should know it's x speed" do
79
+ @to.x_speed.should == @x_speed
80
+ end
81
+
82
+ it "should know it's y speed" do
83
+ @to.y_speed.should == @y_speed
84
+ end
85
+
86
+ it "should know it's rotation vector" do
87
+ @to.rotation_vector.should == @rotation_vector
88
+ end
89
+
90
+ it "should know it's rotation accel" do
91
+ @to.rotation_accel.should == @rotation_accel
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,32 @@
1
+ require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
+
3
+ # /tuio/2Dobj set s i x y a X Y A m r
4
+ # /tuio/2Dcur set s x y X Y m
5
+
6
+ # session_id, x, y, X, Y, m
7
+ shared_examples_for "TuioParameter" do
8
+
9
+ it "should fetch session id" do
10
+ @tuio_param.session_id.should == @session_id
11
+ end
12
+
13
+ it "should fetch x position" do
14
+ @tuio_param.x_pos.should == @x_pos
15
+ end
16
+
17
+ it "should fetch y position" do
18
+ @tuio_param.y_pos.should == @y_pos
19
+ end
20
+
21
+ it "should fetch x speed" do
22
+ @tuio_param.x_speed.should == @x_speed
23
+ end
24
+
25
+ it "should fetch y speed" do
26
+ @tuio_param.y_speed.should == @y_speed
27
+ end
28
+
29
+ it "should fetch motion acceleration" do
30
+ @tuio_param.motion_accel.should == @motion_accel
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
+
3
+ describe TuioPoint do
4
+ before :each do
5
+ @location1 = [0.1, 0.1]
6
+ @location2 = [0.1, 0.21]
7
+
8
+ @point1 = TuioPoint.new( *@location1 )
9
+ @point2 = TuioPoint.new( *@location2 )
10
+ end
11
+
12
+ describe "in general" do
13
+ it "should know the distance to another point" do
14
+ # not a wonderful test, but a sanity check
15
+ @point1.distance_to( @point2 ).should be_close( 0.11, 0.00001 )
16
+ end
17
+
18
+ it "should know the angle to another point" do
19
+ # not a wonderful test, but a sanity check
20
+ @point1.radians_to( @point2 ).should be_close( 1.5707963, 0.00001 )
21
+ end
22
+
23
+ it "should know when it was last updated" do
24
+ @point1.should respond_to(:updated_at)
25
+ end
26
+
27
+ it "should know if it is equal to another point" do
28
+ @other_point = TuioPoint.new( *@location1 )
29
+
30
+ @point1.should be_eql( @other_point )
31
+ end
32
+ end
33
+
34
+ describe "updates" do
35
+ before :each do
36
+ @point1.updated_at = Time.now
37
+
38
+ @point1.update( *@location2 )
39
+ end
40
+
41
+ it "should clear the updated at time" do
42
+ @point1.updated_at.should == nil
43
+ end
44
+ end
45
+
46
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tuio-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - aberant
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-16 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: osc-ruby
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.6
24
+ version:
25
+ description:
26
+ email: qzzzq1@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - Rakefile
36
+ - examples/tuio_dump.rb
37
+ - lib/tuio-ruby.rb
38
+ - lib/tuio-ruby/core_ext/float.rb
39
+ - lib/tuio-ruby/core_ext/object.rb
40
+ - lib/tuio-ruby/tuio_client.rb
41
+ - lib/tuio-ruby/tuio_container.rb
42
+ - lib/tuio-ruby/tuio_cursor.rb
43
+ - lib/tuio-ruby/tuio_cursor_parameter.rb
44
+ - lib/tuio-ruby/tuio_object.rb
45
+ - lib/tuio-ruby/tuio_object_parameter.rb
46
+ - lib/tuio-ruby/tuio_parameter.rb
47
+ - lib/tuio-ruby/tuio_point.rb
48
+ - LICENSE
49
+ - README.rdoc
50
+ has_rdoc: true
51
+ homepage: http://github.com/aberant/tuio-ruby
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --charset=UTF-8
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project: tuio-ruby
72
+ rubygems_version: 1.3.1
73
+ signing_key:
74
+ specification_version: 2
75
+ summary: library to interface with TUIO protocol
76
+ test_files:
77
+ - spec/integration/tuio_event_spec.rb
78
+ - spec/spec_helper.rb
79
+ - spec/unit/tuio_container_spec.rb
80
+ - spec/unit/tuio_cursor_parameter_spec.rb
81
+ - spec/unit/tuio_cursor_spec.rb
82
+ - spec/unit/tuio_object_parameter_spec.rb
83
+ - spec/unit/tuio_object_spec.rb
84
+ - spec/unit/tuio_parameter_spec.rb
85
+ - spec/unit/tuio_point_spec.rb