Hatena::ブログ(Diary)

urekatのスカンク日記3 このページをアンテナに追加 RSSフィード

2007-06-27

[][][]RubyWiiリモコンをつなぐ

WiiRemoteFrameworkを使うにはCocoaの知識が必要だしメソッド名もCocoa的で

Rubyぽくないのでラッパーをつくった。

require 'osx/cocoa'
OSX.require_framework "WiiRemote"

class WiiRemo < OSX::NSObject
  @@instance = nil
  def self.start_search(&found_block)
    raise "already initialized" if @@instance
    @@instance = WiiRemo.alloc.init(&found_block)
    puts @@instance.inspect
  end
  def self.stop_search
    @@instance.stop
    @@instance = nil
  end

  def initialize
    @discovery = nil
  end

  def init(&found_block)
    @discovery = OSX::WiiRemoteDiscovery.alloc.init
    @discovery.setDelegate(self)
    @found_block = found_block
    @discovery.start
    return self
  end
  
  def stop
    @discovery.stop
  end

  def WiiRemoteDiscovered(remote)
    puts "WiiRemoteDiscovered remote=#{remote.inspect}"
    remote_proxy = RemoteProxy.alloc.init(remote)
    @found_block.call(remote_proxy)
  end

  def WiiRemoteDiscoveryError(code)
    #puts "WiiRemoteDiscoveryError code=%x" % code
  end

  ## WiiRemoteDiscovery callback
  objc_method :WiiRemoteDiscovered,     %w{void id}
  objc_method :WiiRemoteDiscoveryError, %w{void int}
  
  class RemoteProxy < OSX::NSObject
    def init(remote)
      @remote = remote
      @remote.setDelegate(self)
      setup_observers
      return self
    end
    
    def setup_observers
      OSX::NSNotificationCenter.defaultCenter.addObserver_selector_name_object(self, 
                                 :WiiRemoteExpansionPortChangedNotification, 
                                 "WiiRemoteExpansionPortChangedNotification", nil)
      # TODO others
    end
    
    def cleanup_observers
      # todo
    end

    def bind(client)
      @client = client
      @client.connected(self)
      
      # auto???
      @remote.setMotionSensorEnabled(true)
      @remote.setIRSensorEnabled(true)
      @remote.setExpansionPortEnabled(true)
    end

    def irPointMovedX_Y_wiiRemote(px, py, wiiRemote)
      @client.ir_point(px, py)
    end

    def buttonChanged_isPressed_wiiRemote(btn_type, is_pressed, wiiRemote)
      @client.button(btn_type, is_pressed)
    end

    def accelerationChanged_accX_accY_accZ_wiiRemote(type, ax, ay, az, wiiRemote)
      case type
      when 0: @client.main_acc(ax, ay, az)
      when 1: @client.nuncyaku_acc(ax, ay, az)
      else raise "unknown acc type #{type}"
      end
    end

    def joyStickChanged_tiltX_tiltY_wiiRemote(type, tilt_x, tilt_y, wiiRemote)
      case type
      when 0: @client.nuncyaku_joystick(tilt_x, tilt_y)
      when 1: @client.classic_controller_left_joystick(tilt_x, tilt_y)
      when 2: @client.classic_controller_right_joystick(tilt_x, tilt_y)
      else raise "unknown joystick type #{type}"
      end
    end

    def wiiRemoteDisconnected(device)
      @client.disconnected
      cleanup_observers
    end
    
    def WiiRemoteExpansionPortChangedNotification(n)
      if n.object.__ocid__==@remote.__ocid__
        @client.expansion_port_changed
        @remote.setExpansionPortEnabled(true)
      end
    end

    ## WiiRemote callback

    objc_method :irPointMovedX_Y_wiiRemote, %w{void float float id}
    objc_method :buttonChanged_isPressed_wiiRemote, %w{void ushort char id}
    objc_method :accelerationChanged_accX_accY_accZ_wiiRemote, %w{void ushort uchar uchar uchar id}
    objc_method :joyStickChanged_tiltX_tiltY_wiiRemote, %w{void ushort uchar uchar id}
    objc_method :wiiRemoteDisconnected, %w{void id}
    # TODO (void) analogButtonChanged:(WiiButtonType)type amount:(unsigned)press wiiRemote:(WiiRemote*)wiiRemote;

    ## notification
    #objc_method :WiiRemoteExpansionPortChangedNotification, %w{void id}
  end
end

if __FILE__ == $0
  class MyClient
    def connected(remote)
      p "connected"
      @remote = remote
    end
    def button(btn, press)
      p "button #{btn} #{press}"
    end
    def main_acc(x, y, z)
      x = ((x-130)*0.5).round
      y = ((y-130)*0.5).round
      z = ((z-130)*0.5).round
      puts "main_acc(%d,%d,%d)" % [x,y,z]
      if false
        div = 3
        s = (" " * (256/div))+"|"
        s[x/div] = "x"
        s[y/div] = "y"
        s[z/div] = "z"
        puts s
      end
=begin
普通:131,133,157
左  :105,132,130
右  :157,133,130
裏  :131,132,102
=end
    end
    def nuncyaku_acc(x, y, z)
      #puts "nuncyaku_acc(%d,%d,%d)" % [x,y,z]
    end
    def nuncyaku_joystick(x, y)
      #puts "nuncyaku_joystick #{x} #{y}"
    end
    def classic_controller_left_joystick(x, y)
    end
    def classic_controller_right_joystick(x, y)
    end
    def ir_point(x, y)
    end
    def disconnected
      p "disconnected"
    end
    def expansion_port_changed
      p "expansion_port_changed"
    end
  end

  WiiRemo.start_search{|r|
    r.bind(MyClient.new)
    WiiRemo.stop_search
  }
  OSX::NSRunLoop.currentRunLoop.run
end

ODEにつなごうとしたんだけどQuaternionがわからなくて飽きてしまった!!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト

コメントを書くには、なぞなぞ認証に回答する必要があります。

トラックバック - http://d.hatena.ne.jp/urekat/20070627/1182919180