tuio-ruby 0.2.2

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/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