Hatena::¥Ö¥í¥°(Diary)

urekat¤Î¥¹¥«¥ó¥¯Æüµ­£³ ¤³¤Î¥Ú¡¼¥¸¤ò¥¢¥ó¥Æ¥Ê¤ËÄɲà RSS¥Õ¥£¡¼¥É

2007-06-27

¢£[][][]Ruby¤ÈWii¥ê¥â¥³¥ó¤ò¤Ä¤Ê¤°

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¤¬¤ï¤«¤é¤Ê¤¯¤ÆË°¤­¤Æ¤·¤Þ¤Ã¤¿¡ª¡ª

¥¹¥Ñ¥àÂкö¤Î¤¿¤á¤Î¥À¥ß¡¼¤Ç¤¹¡£¤â¤·¸«¤¨¤Æ¤â²¿¤âÆþÎϤ·¤Ê¤¤¤Ç¤¯¤À¤µ¤¤
¥²¥¹¥È

¥³¥á¥ó¥È¤ò½ñ¤¯¤Ë¤Ï¡¢¤Ê¤¾¤Ê¤¾Ç§¾Ú¤Ë²óÅú¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£