leap-motion-ws 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad2f348b76ec5ba36959631f0358b128a2501d6a
4
- data.tar.gz: 138cf8fac6634bcce856f07b344cefb2d576d556
3
+ metadata.gz: b27639657797b35580926d29c4c602055b3a6fb5
4
+ data.tar.gz: 0b2e9b8fe95693bc7c16a14124d253fb51807d1e
5
5
  SHA512:
6
- metadata.gz: b93617d0af9307fc94903677f85aade0b54fae4e26e969ebf98aa556dca609b8aee1ec98b02d4980ed01ba6e3da17652cae102f42f13fa75cf9215b6cc3384bb
7
- data.tar.gz: 751881faa2cc40ae20ba740aeb44659aad1c65b3312c25e7866a64cb53ada4c833cc67c5429d7d30f4b7d62b10d25831b424e2b90cf6f00d00c8070ba974cbb4
6
+ metadata.gz: d7d3271db65abf83b26933269c6bd7485bf75620b0a91689156a404656e84a16c6ca0ff0259e1105723dad5e7e1f9050524883b86942fdc11e7fb2a2463b792d
7
+ data.tar.gz: 89a2ab1d862e865d529e02065965fa79658ab086701bf8919ff26624451e349ae178fa7a12f1ef6ecbce186e0294a381c02983ce67260f6f4a9c2f1f7f14ac19
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- leap-motion-ws (0.0.1)
4
+ leap-motion-ws (0.0.2)
5
5
  json
6
6
  websocket-eventmachine-client
7
7
 
@@ -11,25 +11,19 @@ GEM
11
11
  activesupport (3.2.13)
12
12
  i18n (= 0.6.1)
13
13
  multi_json (~> 1.0)
14
- bourne (1.4.0)
15
- mocha (~> 0.13.2)
16
14
  eventmachine (1.0.3)
17
15
  i18n (0.6.1)
18
16
  json (1.7.7)
19
- metaclass (0.0.1)
20
- mocha (0.13.3)
21
- metaclass (~> 0.0.1)
22
17
  multi_json (1.7.3)
23
18
  rake (10.0.4)
24
19
  rdoc (4.0.1)
25
20
  json (~> 1.4)
26
- shoulda (3.4.0)
21
+ shoulda (3.5.0)
27
22
  shoulda-context (~> 1.0, >= 1.0.1)
28
- shoulda-matchers (~> 1.0, >= 1.4.1)
23
+ shoulda-matchers (>= 1.4.1, < 3.0)
29
24
  shoulda-context (1.1.1)
30
- shoulda-matchers (1.5.6)
25
+ shoulda-matchers (2.1.0)
31
26
  activesupport (>= 3.0.0)
32
- bourne (~> 1.3)
33
27
  websocket (1.0.7)
34
28
  websocket-eventmachine-base (1.0.2)
35
29
  eventmachine (~> 1.0)
data/Rakefile CHANGED
@@ -10,7 +10,6 @@ Rake::TestTask.new(:test) do |test|
10
10
  test.pattern = 'test/**/test_*.rb'
11
11
  test.verbose = true
12
12
  end
13
- task :test => :compile
14
13
 
15
14
  task :default => :test
16
15
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
 
11
11
  s.authors = ["Gregoire Lejeune"]
12
12
  s.email = "gregoire.lejeune@free.fr"
13
- s.homepage = "http://github.com/glejeune/leap-motion-ws"
13
+ s.homepage = "https://github.com/glejeune/ruby-leap-motion-ws"
14
14
  s.license = "MIT"
15
15
 
16
16
  s.files = `git ls-files`.split("\n")
@@ -0,0 +1,25 @@
1
+ module LEAP
2
+ class Motion
3
+ module Utils
4
+ class History < Array
5
+ attr_reader :max_size
6
+
7
+ def initialize(max_size, enum = nil)
8
+ @max_size = max_size
9
+ enum.each { |e| self << e } if enum
10
+ end
11
+
12
+ def <<(el)
13
+ if self.size < @max_size || @max_size.nil?
14
+ super
15
+ else
16
+ self.shift
17
+ self.push(el)
18
+ end
19
+ end
20
+
21
+ alias :push :<<
22
+ end
23
+ end
24
+ end
25
+ end
@@ -2,56 +2,154 @@ require 'rubygems'
2
2
  require 'websocket-eventmachine-client'
3
3
  require 'json'
4
4
  require 'leap/motion/ws/frame'
5
+ require 'leap/motion/utils/history'
5
6
 
6
7
  module LEAP
7
8
  class Motion
9
+ # Public: Class to be subclassed to interface with the Leap Motion
10
+ #
11
+ # Example
12
+ #
13
+ # class MyLeap < LEAP::Motion::WS
14
+ # def initialize(...)
15
+ # #...
16
+ # end
17
+ #
18
+ # def on_frame(frame)
19
+ # # ...
20
+ # end
21
+ #
22
+ # def on_connect
23
+ # # ...
24
+ # end
25
+ #
26
+ # def on_disconnect
27
+ # # ...
28
+ # end
29
+ #
30
+ # def on_error(message)
31
+ # # ...
32
+ # end
33
+ # end
34
+ #
35
+ # on-frame is the only mandatory function.
8
36
  class WS
37
+ # Public: Initialize a LEAP::Motion::WS
38
+ #
39
+ # options - The Hash options used to initialize the Leap access (default: {:uri => "ws://127.0.0.1:6437", :enable_gesture => false, :history_size => 1000}):
40
+ # :uri - the String uri for the WebSocket::EventMachine::Client connection (optional)
41
+ # :enable_gesture - boolean to indicate if we want to enable gesture or not (optional)
42
+ # :history_size : the Integer size of the history ()
9
43
  def initialize(options = {})
10
- @options = {:uri => "ws://127.0.0.1:6437", :enable_gesture => false}.merge(options)
11
- @gesture_enables = false
12
- @ws = nil
44
+ @options = {:uri => "ws://127.0.0.1:6437", :enable_gesture => false, :history_size => 1000}.merge(options)
45
+ @history = LEAP::Motion::Utils::History.new(@options[:history_size])
13
46
  end
14
47
 
48
+ # Public: Return true if gestures are enabled, false otherwise
15
49
  def gestures?
16
- @gesture_enables
50
+ options[:enable_gesture]
17
51
  end
18
52
 
53
+ # Public: Return the Frame History
54
+ def history
55
+ @history ||= LEAP::Motion::Utils::History.new(options[:history_size])
56
+ end
57
+
58
+ # Public: Enable gestures
59
+ #
60
+ # Return nothing.
19
61
  def gesture!
20
62
  unless @ws.nil?
21
63
  data = JSON "enableGestures" => true
22
- @ws.send data
64
+ options[:enable_gesture] = ws.send data
23
65
  end
24
66
  end
25
67
 
68
+ # Public: Start the interface
69
+ #
70
+ # enable_gesture : boolean to indicate if we want to enable gesture or not (default: false)
71
+ #
72
+ # Examples
73
+ #
74
+ # class MyLeap < LEAP::Motion::WS
75
+ # ...
76
+ # end
77
+ # MyLeap.new.start
78
+ #
79
+ # Returns self
26
80
  def start(enable_gesture = false)
27
81
  EM.run do
28
- @ws = WebSocket::EventMachine::Client.connect(:uri => @options[:uri])
29
-
30
- @ws.onopen do
82
+ ws.onopen do
31
83
  on_connect if respond_to? :on_connect
32
- gesture! if enable_gesture or @options[:enable_gesture]
84
+ gesture! if enable_gesture or options[:enable_gesture]
33
85
  end
34
86
 
35
- @ws.onmessage do |msg, type|
87
+ ws.onmessage do |msg, type|
36
88
  message = JSON(msg)
37
89
  if message.key?("id") and message.key?("timestamp")
38
- on_frame LEAP::Motion::WS::Frame.new(message)
90
+ frame = LEAP::Motion::WS::Frame.new(message)
91
+ history << frame
92
+ on_frame frame
39
93
  end
40
94
  end
41
95
 
42
- @ws.onerror do |err|
96
+ ws.onerror do |err|
43
97
  on_error(err) if respond_to? :on_error
44
98
  end
45
99
 
46
- @ws.onclose do
100
+ ws.onclose do
47
101
  on_disconnect if respond_to? :on_disconnect
48
102
  end
49
103
  end
104
+
105
+ return self
106
+ end
107
+
108
+ # Public: Start the interface
109
+ #
110
+ # enable_gesture : boolean to indicate if we want to enable gesture or not (default: false)
111
+ #
112
+ # Examples
113
+ #
114
+ # class MyLeap < LEAP::Motion::WS
115
+ # ...
116
+ # end
117
+ # MyLeap.start
118
+ #
119
+ # Returns the LEAP::Motion::WS subclass object
120
+ def self.start(enable_gesture = false)
121
+ _leap = new
122
+ _leap.start(enable_gesture)
50
123
  end
51
124
 
125
+
126
+ # Public: Stop the interface
127
+ #
128
+ # Examples
129
+ #
130
+ # class MyLeap < LEAP::Motion::WS
131
+ # ...
132
+ # end
133
+ # my_leap = MyLeap.start
134
+ # ...
135
+ # my_leap.stop
136
+ #
137
+ # Returns self
52
138
  def stop
53
139
  EM::stop_event_loop
54
140
  end
141
+
142
+ private
143
+
144
+ # private: Get the options hash
145
+ def options
146
+ @options ||= {:uri => "ws://127.0.0.1:6437", :enable_gesture => false, :history_size => 1000}
147
+ end
148
+
149
+ # Private: Get the WebSocket::EventMachine::Client connection
150
+ def ws
151
+ @ws ||= WebSocket::EventMachine::Client.connect(:uri => options[:uri])
152
+ end
55
153
  end
56
154
  end
57
155
  end
@@ -1,24 +1,65 @@
1
1
  module LEAP
2
2
  class Motion
3
3
  class WS
4
+ # Recognized movement by the user
5
+ #
6
+ # There is 4 Gesture subclasses :
7
+ #
8
+ # Circle - A circular movement by a finger.
9
+ # Swipe - A straight line movement by the hand with fingers extended.
10
+ # KeyTap - A downward tapping movement by a finger.
11
+ # ScreenTap - A forward tapping movement by a finger.
4
12
  class Gesture
13
+ class Error < StandardError; end
14
+
5
15
  def self.list(data)
6
16
  gestures = []
7
17
  if data["gestures"]
8
18
  data["gestures"].each do |gesture|
9
- gestures << LEAP::Motion::WS::Gesture.new(gesture)
19
+ gestures << make_gesture(gesture)
10
20
  end
11
21
  end
12
22
  return gestures
13
23
  end
14
24
 
15
- def initialize(data)
16
- @data = data
25
+ def self.make_gesture(data)
26
+ unless data.has_key? "type"
27
+ raise Error, "gesture type unknown"
28
+ end
29
+ name = data["type"][0].upcase << data["type"][1..-1]
30
+ unless class_exists?(name)
31
+ raise Error, "gesture class `#{self}::#{name}' invalid"
32
+ end
33
+ const_get(name).new(data)
17
34
  end
18
35
 
19
- def method_missing(mid)
20
- @data[mid.id2name]
36
+ private
37
+
38
+ def self.class_exists?(class_name)
39
+ klass = const_get(class_name)
40
+ return klass.is_a?(Class)
41
+ rescue NameError
42
+ return false
21
43
  end
44
+
45
+ def self.define_gesture *names
46
+ names.each do |n|
47
+ name = n.to_s
48
+ unless class_exists?(name)
49
+ c = Class.new(self) do
50
+ def initialize(data)
51
+ data.each do |k, v|
52
+ instance_variable_set("@#{k}", v)
53
+ self.class.send(:define_method, k.to_sym, lambda { instance_variable_get("@#{k}") })
54
+ end
55
+ end
56
+ end
57
+ const_set name, c
58
+ end
59
+ end
60
+ end
61
+
62
+ define_gesture :Circle, :KeyTap, :ScreenTap, :Swipe
22
63
  end
23
64
  end
24
65
  end
@@ -13,11 +13,10 @@ module LEAP
13
13
  end
14
14
 
15
15
  def initialize(data)
16
- @data = data
17
- end
18
-
19
- def method_missing(mid)
20
- @data[mid.id2name]
16
+ data.each do |k, v|
17
+ instance_variable_set("@#{k}", v)
18
+ self.class.send(:define_method, k.to_sym, lambda { instance_variable_get("@#{k}") })
19
+ end
21
20
  end
22
21
  end
23
22
  end
@@ -13,11 +13,10 @@ module LEAP
13
13
  end
14
14
 
15
15
  def initialize(data)
16
- @data = data
17
- end
18
-
19
- def method_missing(mid)
20
- @data[mid.id2name]
16
+ data.each do |k, v|
17
+ instance_variable_set("@#{k}", v)
18
+ self.class.send(:define_method, k.to_sym, lambda { instance_variable_get("@#{k}") })
19
+ end
21
20
  end
22
21
  end
23
22
  end
@@ -0,0 +1,38 @@
1
+ $:.unshift "../lib"
2
+
3
+ require 'leap-motion-ws'
4
+
5
+ class LeapTest < LEAP::Motion::WS
6
+ def on_connect
7
+ puts "Connect"
8
+ end
9
+
10
+ def on_frame frame
11
+ puts "Frame ##{frame.id}, timestamp: #{frame.timestamp}, hands: #{frame.hands.size}, pointables: #{frame.pointables.size}" if frame.gestures.size > 0
12
+ frame.gestures.each do |gesture|
13
+ puts " -> ##{gesture.id} : #{gesture.type} / #{gesture.state}"
14
+ end
15
+ end
16
+
17
+ def on_disconnect
18
+ puts "disconect"
19
+ stop
20
+ end
21
+ end
22
+
23
+ leap = LeapTest.new(:enable_gesture => true)
24
+
25
+ Signal.trap("TERM") do
26
+ puts "Terminating..."
27
+ leap.stop
28
+ end
29
+ Signal.trap("KILL") do
30
+ puts "Terminating..."
31
+ leap.stop
32
+ end
33
+ Signal.trap("INT") do
34
+ puts "Terminating..."
35
+ leap.stop
36
+ end
37
+
38
+ leap.start
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'test/unit'
4
+ require 'shoulda'
5
+ require 'pathname'
6
+
7
+ cur = Pathname.new(File.expand_path("..", __FILE__))
8
+ lib = cur.join('..', 'lib')
9
+
10
+ $LOAD_PATH.unshift(lib.to_s, cur.to_s)
11
+ require 'leap-motion-ws'
12
+
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+
3
+ class TestHistory < Test::Unit::TestCase
4
+ context "a new history" do
5
+ setup do
6
+ @h = LEAP::Motion::Utils::History.new(3)
7
+ end
8
+
9
+ should "be empty with a max_size of 3" do
10
+ assert_equal 0, @h.size
11
+ assert_equal 3, @h.max_size
12
+ end
13
+
14
+ should "have 3 elements" do
15
+ @h << "one"
16
+ @h << "two"
17
+ @h << "three"
18
+ assert_equal 3, @h.size
19
+ assert_equal 3, @h.max_size
20
+ assert_equal true, @h.include?("one")
21
+
22
+ @h << "four"
23
+ assert_equal 3, @h.size
24
+ assert_equal 3, @h.max_size
25
+ assert_equal false, @h.include?("one")
26
+ end
27
+ end
28
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leap-motion-ws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregoire Lejeune
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-07 00:00:00.000000000 Z
11
+ date: 2013-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: websocket-eventmachine-client
@@ -111,17 +111,19 @@ files:
111
111
  - VERSION
112
112
  - leap-motion-ws.gemspec
113
113
  - lib/leap-motion-ws.rb
114
- - lib/leap/motion/utils/ring.rb
114
+ - lib/leap/motion/utils/history.rb
115
115
  - lib/leap/motion/ws.rb
116
116
  - lib/leap/motion/ws/frame.rb
117
117
  - lib/leap/motion/ws/gesture.rb
118
118
  - lib/leap/motion/ws/hand.rb
119
119
  - lib/leap/motion/ws/pointable.rb
120
120
  - samples/itunes_controller.rb
121
- - samples/motion_ws_sample.rb
122
- - samples/ring_sample.rb
121
+ - samples/motion_gesture_sample.rb
122
+ - samples/motion_sample.rb
123
123
  - samples/rock_paper_scissors.rb
124
- homepage: http://github.com/glejeune/leap-motion-ws
124
+ - test/helper.rb
125
+ - test/test_history.rb
126
+ homepage: https://github.com/glejeune/ruby-leap-motion-ws
125
127
  licenses:
126
128
  - MIT
127
129
  metadata: {}
@@ -141,8 +143,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
143
  version: '0'
142
144
  requirements: []
143
145
  rubyforge_project:
144
- rubygems_version: 2.0.3
146
+ rubygems_version: 2.0.0
145
147
  signing_key:
146
148
  specification_version: 4
147
149
  summary: Ruby interface to the Leap Motion Controller (via WebSocket)
148
- test_files: []
150
+ test_files:
151
+ - test/helper.rb
152
+ - test/test_history.rb
@@ -1,19 +0,0 @@
1
- class Ring < Array
2
- attr_reader :max_size
3
-
4
- def initialize(max_size, enum = nil)
5
- @max_size = max_size
6
- enum.each { |e| self << e } if enum
7
- end
8
-
9
- def <<(el)
10
- if self.size < @max_size || @max_size.nil?
11
- super
12
- else
13
- self.shift
14
- self.push(el)
15
- end
16
- end
17
-
18
- alias :push :<<
19
- end
@@ -1,19 +0,0 @@
1
- $:.unshift "../lib"
2
-
3
- require 'leap/motion/utils/ring'
4
-
5
- x = Ring.new(3)
6
-
7
- x << "A"
8
- x << "B"
9
- x << "C"
10
- p x
11
-
12
- x << "D"
13
- p x
14
-
15
- x << "E"
16
- p x
17
-
18
- x << "F"
19
- p x