Wiimote code

A small python programm that allows you to use the wiimote to replace the mouse and some buttons. It works on a linux system with x-server and uses the cwiid library for python to interface with the wiimote.

#!/usr/bin/python

# Author: most of the code by Norbert Feurle
# Date: 21.12.2011
#
# Description: Code for linux to Controll the mouse pointer and some 
# click actions with the Wimote ( uses IR cammera )
# Using a lot of globals to make the program short
# Implementing singel clicks and autorepeated clicks if you press a button longer 
#
# Additional Pythonpackages needed: cwiid -> for connecting over bluetooth to wiimoote
# Xlib -> To move the mouse and fake inputs under linux 

import Xlib.display
import Xlib.ext.xtest
from Xlib import XK
from time import sleep
import cwiid
import thread

globals()["KeepRunning"]=False

class X1Control:
 def __init__(self):
    self.display = Xlib.display.Display()
    self.screen = self.display.screen()
    self.root = self.screen.root

 def mouse_click(self, button):
    self.mouse_down(button)
    self.mouse_up(button)

 def mouse_down(self, button): #button= 1 left, 2 middle, 3 right
    Xlib.ext.xtest.fake_input(self.display,Xlib.X.ButtonPress, button)
    self.display.sync()

 def mouse_up(self, button):
    Xlib.ext.xtest.fake_input(self.display,Xlib.X.ButtonRelease, button)
    self.display.sync() 

 def mouse_warp(self, x,y):
    self.root.warp_pointer(x,y)
    self.display.sync()

 def key_down(self,key):
    Xlib.ext.xtest.fake_input(self.display,Xlib.X.KeyPress, key)
    self.display.sync() 

 def key_up(self,key):
    Xlib.ext.xtest.fake_input(self.display,Xlib.X.KeyRelease, key)
    self.display.sync() 

 def key_click(self, key):
    self.key_down(key)
    self.key_up(key)

 def get_screen_resolution(self):
    return self.screen['width_in_pixels'], self.screen['height_in_pixels']

#MouseMove=True
DeactivatedbyRepeat=0
IR_enabled=True
def ToggleMouseMove(para):
  global wm,ButtonPressMap,DeactivatedbyRepeat,IR_enabled
  if IR_enabled: #wm.state.has_key('ir_src'):
    #wm.rpt_mode = cwiid.RPT_BTN
    IR_enabled=False
    wm.led=0
    DeactivatedbyRepeat=para
    ButtonPressMap[cwiid.BTN_A]=(k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Enter))
    #MouseMove=False
  else:
    DeactivatedbyRepeat=0
    wm.led=1
    IR_enabled=True
    #wm.rpt_mode = cwiid.RPT_BTN | cwiid.RPT_IR is not 100% garanteed to work
    ButtonPressMap[cwiid.BTN_A]=(k.mouse_down,1)
    #MouseMove=True

def RunWii():
  global lab,wm,k,ButtonPressMap,ButtonReleaseMap,ButtonRepeatMap
  #print "To Connect press (1+2) on Wiimote"
  #reload(cwiid)
  wm=None
  try:
    wm = cwiid.Wiimote()
    lab['text']="Connection Successfull"
  except:
    lab['text']="Could not establish Connection"
    globals()["KeepRunning"]=False
    return

  wm.led=1
  wm.rpt_mode = cwiid.RPT_BTN | cwiid.RPT_IR  # cwiid.RPT_ACC|

  k=X1Control()

  ButtonPressMap={cwiid.BTN_A:(k.mouse_down,1),
	    cwiid.BTN_PLUS:(k.mouse_click,3),
	    cwiid.BTN_MINUS:(k.key_down,k.display.keysym_to_keycode(XK.XK_Shift_L) ),
	    cwiid.BTN_B:(k.mouse_click,1),
	    cwiid.BTN_HOME:(ToggleMouseMove,0),
	    cwiid.BTN_UP: (k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Up) ),
	    cwiid.BTN_LEFT: (k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Left) ),
	    cwiid.BTN_RIGHT: (k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Right) ),
	    cwiid.BTN_DOWN:(k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Down) )}

  ButtonReleaseMap={cwiid.BTN_A:(k.mouse_up,1),
		    cwiid.BTN_MINUS:(k.key_up,k.display.keysym_to_keycode(XK.XK_Shift_L) )}

  ButtonRepeatMap={cwiid.BTN_PLUS:(ToggleMouseMove,1,-9000),    ## last parameter is additional time increase for autorepeates of the button, -9000 nearly avoids repeats in line
	      cwiid.BTN_B:(ToggleMouseMove,1,-9000),
	      cwiid.BTN_UP: (k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Up) ,0),
	    cwiid.BTN_LEFT: (k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Left) ,0),
	    cwiid.BTN_RIGHT: (k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Right) ,0),
	    cwiid.BTN_DOWN:(k.key_click,k.display.keysym_to_keycode(XK.XK_KP_Down) ,0)}

  widthx,widthy=k.get_screen_resolution()
  x,y=(0,0)
  Buttonlast=False
  waitRepeat_count=0
  while globals()["KeepRunning"]:
      State_Read=wm.state # & cwiid.BTN_A)
      ButtonActual=State_Read['buttons']
      diff=ButtonActual-Buttonlast

      ### do button events on change
      if diff>0:
	waitRepeat_count=0
	if ButtonPressMap.has_key(abs(diff)):
	  ButtonPressMap[diff][0](ButtonPressMap[diff][1]);
	  ### ugly magic now here
	  if DeactivatedbyRepeat and diff==cwiid.BTN_A:
	    ToggleMouseMove(0)

      elif diff<0:
	waitRepeat_count=0
	if ButtonReleaseMap.has_key(abs(diff)):
	  ButtonReleaseMap[abs(diff)][0](ButtonReleaseMap[abs(diff)][1]);
      Buttonlast=ButtonActual

      #move mousepointer if ir_src is activated and wii detects a ir point:
      irSrcActive=State_Read.has_key('ir_src') and IR_enabled
      if irSrcActive and State_Read['ir_src'][0]!=None:
	x,y=State_Read['ir_src'][0]['pos']
	k.mouse_warp(((1024-x)*widthx*1.4/1024.0)-widthx*0.2,(y*widthy*1.4/768.0)-widthy*0.2)

      ## Do the button repeat
      if ButtonActual>0:
	waitRepeat_count=waitRepeat_count+1
	if waitRepeat_count>(40-(not irSrcActive)*34):
	  waitRepeat_count=35-(not irSrcActive)*29
	  if ButtonRepeatMap.has_key(abs(ButtonActual)):
	    ButtonRepeatMap[ButtonActual][0](ButtonRepeatMap[ButtonActual][1]);
	    waitRepeat_count=waitRepeat_count+ButtonRepeatMap[ButtonActual][2]
      else:
	waitRepeat_count=0

      ### increase sleep time if ir_src is not active
      sleep(0.01+(not irSrcActive)*0.05)
  wm.close()
  lab['text']="Disconnected from Wiimote"

import Tkinter
root=Tkinter.Tk()
root.title("Wii Input")

def buttonCommand():
  globals()["KeepRunning"]=False
def connectCommand():
  global lab
  if globals()["KeepRunning"]==False:
    globals()["KeepRunning"]=True
    lab['text']="To Connect press (1+2) on Wiimote"
    thread.start_new_thread(RunWii,())
  else:
    lab['text']="Wiimote is allready Connected"

bb1=Tkinter.Button(root,text="Connect to Wiimote",command=connectCommand)
bb=Tkinter.Button(root,text="Close Wiimote Connection",command=buttonCommand)
lab=Tkinter.Label(text="Not Connected to Wiimote")
bb1.grid()
bb.grid()
lab.grid()
Tkinter.mainloop()
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: