require 'leap_motion.so' require 'set' require 'thread' module LeapMotion VERSION = '1.0.2' class HandList; include Enumerable; end class FingerList; include Enumerable; end class PointableList; include Enumerable; end class ToolList; include Enumerable; end class GestureList; include Enumerable; end class Controller EVENTS = [:init, :connect, :disconnect, :frame, :focus_gained, :focus_lost] def initialize super @listeners = Set.new @mutex = Mutex.new ios = EVENTS.map { |event| IO.new send "#{event}_fd" } @listener = start_listener ios end def join; @listener.join; end def each_frame reader = IO.new frame_fd listen! loop do rs, = IO.select [reader] rs.each { |io| io.read 1 yield frame } end ensure unlisten! if @listeners.empty? end def add_listener listener @mutex.synchronize do return false if @listeners.include? listener @listeners = @listeners.dup.add listener listen! end end def remove_listener listener @mutex.synchronize do return false unless @listeners.include? listener @listeners = @listeners.dup.delete listener unlisten! if @listeners.empty? end end private def start_listener ios methods = EVENTS.map { |e| "on_#{e}" } dispatch = Hash[ios.zip(methods)] Thread.new do loop do rs, = IO.select ios rs.each { |io| io.read 1 send dispatch[io] } end end end EVENTS.each do |event| class_eval <<-EORUBY, __FILE__, __LINE__ + 1 def on_#{event} @listeners.each { |l| l.on_#{event} self } end EORUBY end end module Events def on_init controller; end def on_connect controller; end def on_disconnect controller; end def on_exit controller; end def on_frame controller; end def on_focus_gained controller; end def on_focus_lost controller; end end class Pointable def finger?; false; end def tool?; false; end end class Finger < Pointable def finger?; true; end end class Tool < Pointable def tool?; true; end end class Listener include Events end class Vector UP = new 0, 1, 0 DOWN = new 0, -1, 0 FORWARD = new 0, 0, -1 BACKWARD = new 0, 0, 1 LEFT = new(-1, 0, 0) RIGHT = new 1, 0, 0 X_AXIS = new 1, 0, 0 Y_AXIS = new 0, 1, 0 Z_AXIS = new 0, 0, 1 ZERO = new 0, 0, 0 def to_a [x, y, z] end def [] idx to_a.fetch(idx, 0.0) end end end