1 '''Access to the Wiimote in pygame
3 I tried to mimic the Joystick interface already in pygame.
7 init the module telling it the maximum number of wiimotes and the timeout
8 get_count to determine how many you got
9 Wiimote(n) to get an object referencing the nth wiimote
11 Free for any use. If you or your lawyer are stupid enough to believe I have any liability for
12 this, then don't use it; otherwise be my guest.
14 Gary Bishop January 2008
19 from threading
import Thread
20 from Queue
import Queue
, Empty
23 # events to use. Is there a way to get ones known to be unused?
24 base
= pygame
.USEREVENT
25 WIIMOTE_BUTTON_PRESS
= base
+ 1
26 WIIMOTE_BUTTON_RELEASE
= base
+ 2
27 WIIMOTE_ACCEL
= base
+ 3
29 NUNCHUK_BUTTON_PRESS
= base
+ 5
30 NUNCHUK_BUTTON_RELEASE
= base
+ 6
31 NUNCHUK_ACCEL
= base
+ 7
32 NUNCHUK_JOY
= base
+ 8
33 WIIMOTE_STATUS
= base
+ 9
34 WIIMOTE_DISCONNECT
= base
+ 10
36 wiiuse
= None # import within the thread, why do I have to do this?
38 class wiimote_thread(Thread
):
39 '''Manage the wiiuse interface'''
40 def __init__(self
, nmotes
=1, timeout
=5):
41 Thread
.__init
__(self
, name
='wiimote')
43 self
.startup
= Queue()
45 self
.timeout
= timeout
48 self
.startup
.get(True) # wait for the thread to get started and acquire the motes
51 '''This runs in a separate thread'''
53 import PyWiiUse
as wiiuse
# import here to avoid thread problems on windows
54 self
.wiimotes
= wiiuse
.init(self
.nmotes
)
55 found
= wiiuse
.find(self
.wiimotes
, self
.nmotes
, self
.timeout
)
56 self
.actual_nmotes
= wiiuse
.connect(self
.wiimotes
, self
.nmotes
)
58 for i
in range(self
.nmotes
):
59 wiiuse
.set_leds(self
.wiimotes
[i
], wiiuse
.LED
[i
])
61 self
.go
= self
.actual_nmotes
!= 0
63 self
.startup
.put(self
.go
)
67 if wiiuse
.poll(self
.wiimotes
, self
.nmotes
) :
68 for i
in range(self
.nmotes
):
70 if m
[0].event
== wiiuse
.EVENT
:
75 # allow executing functions in this thread
78 func
, args
= self
.queue
.get_nowait()
83 def do(self
, func
, *args
):
84 '''Run the function in the thread handling the wiimote'''
85 self
.queue
.put((func
, args
))
87 def event_cb(self
, wmp
):
88 '''Called when the library has some data for the user.'''
91 for name
,b
in wiiuse
.button
.items():
92 if wiiuse
.is_just_pressed(wm
, b
):
93 pygame
.event
.post(pygame
.event
.Event(WIIMOTE_BUTTON_PRESS
, button
=name
,
98 for name
,b
in wiiuse
.button
.items():
99 if wiiuse
.is_released(wm
, b
):
100 pygame
.event
.post(pygame
.event
.Event(WIIMOTE_BUTTON_RELEASE
, button
=name
,
105 pygame
.event
.post(pygame
.event
.Event(WIIMOTE_ACCEL
,
106 orient
=(wm
.orient
.roll
, wm
.orient
.pitch
,
108 accel
=(wm
.gforce
.x
, wm
.gforce
.y
, wm
.gforce
.z
),
112 dots
= [ (wm
.ir
.dot
[i
].visible
, wm
.ir
.dot
[i
].x
, wm
.ir
.dot
[i
].y
) for i
in range(4) ]
113 pygame
.event
.post(pygame
.event
.Event(WIIMOTE_IR
,
115 cursor
=(wm
.ir
.x
, wm
.ir
.y
, wm
.ir
.z
),
119 if wm
.exp
.type == wiiuse
.EXP_NUNCHUK
:
120 nc
= wm
.exp
.u
.nunchuk
122 for name
,b
in wiiuse
.nunchuk_button
.items():
123 if wiiuse
.is_just_pressed(nc
, b
):
124 pygame
.event
.post(pygame
.event
.Event(NUNCHUK_BUTTON_PRESS
, button
=name
,
127 elif wiiuse
.is_released(nc
, b
):
128 pygame
.event
.post(pygame
.event
.Event(NUNCHUK_BUTTON_RELEASE
, button
=name
,
132 pygame
.event
.post(pygame
.event
.Event(NUNCHUK_ACCEL
,
133 orient
=(nc
.orient
.roll
, nc
.orient
.pitch
,
135 accel
=(nc
.gforce
.x
, nc
.gforce
.y
, nc
.gforce
.z
),
138 pygame
.event
.post(pygame
.event
.Event(NUNCHUK_JOY
,
144 def control_cb(self
, wmp
, attachment
, speaker
, ir
, led
, battery
):
145 '''Could check the battery level and such here'''
146 pygame
.event
.post(pygame
.event
.Event(WIIMOTE_STATUS
,
147 attachment
=attachment
,
150 led
=[led
[i
] for i
in range(4)],
154 def disconnect_cb(self
, wmp
):
155 '''What should we do here?'''
156 pygame
.event
.post(pygame
.event
.Event(WIIMOTE_DISCONNECT
,
161 for i
in range(self
.nmotes
):
162 wiiuse
.set_leds(self
.wiimotes
[i
], 0)
163 wiiuse
.disconnect(self
.wiimotes
[i
])
168 def init(nmotes
, timeout
):
169 '''Initialize the module.'''
173 WT
= wiimote_thread(nmotes
, timeout
)
176 '''How many Wiimotes were found?'''
177 return WT
.actual_nmotes
180 '''Gracefully shutdown the connection and turn off the wiimote leds'''
184 class wiimote(object):
185 '''Object representing a Wiimote'''
186 def __init__(self
, n
):
187 self
.wm
= WT
.wiimotes
[n
]
189 def enable_leds(self
, m
):
190 '''Control leds. The lower 4 bits map to the 4 leds'''
191 WT
.do(wiiuse
.set_leds
, self
.wm
, sum([wiiuse
.LED
[i
] for i
in range(4) if m
& (1<<i
)]))
193 def enable_rumble(self
, on
):
195 WT
.do(wiiuse
.rumble
, self
.wm
, on
)
197 def enable_accels(self
, on
):
198 '''Control reporting of accelerometer data.'''
199 WT
.do(wiiuse
.motion_sensing
, self
.wm
, on
)
201 def enable_ir(self
, on
, vres
=None, position
=None, aspect
=None):
202 '''Control reporting IR data.'''
203 WT
.do(wiiuse
.set_ir
, self
.wm
, on
)
205 WT
.do(wiiuse
.set_ir_vres
, self
.wm
, vres
)
206 if position
is not None:
207 WT
.do(wiiuse
.set_ir_position
, self
.wm
, position
)
208 if aspect
is not None:
209 WT
.do(wiiuse
.set_aspect_ratio
, self
.wm
, aspect
)
211 def set_flags(self
, smoothing
=None, continuous
=None, threshold
=None):
212 '''Set flags SMOOTHING, CONTINUOUS, ORIENT_THRESH'''
214 if smoothing
is not None:
216 enable |
= wiiuse
.SMOOTHING
218 disable |
= wiiuse
.SMOOTHING
219 if continuous
is not None:
221 enable |
= wiiuse
.CONTINUOUS
223 disable |
= wiiuse
.CONTINUOUS
224 if threshold
is not None:
226 enable |
= wiiuse
.ORIENT_THRESH
228 disable |
= wiiuse
.ORIENT_THRESH
229 print enable
, disable
230 WT
.do(wiiuse
.set_flags
, self
.wm
, enable
, disable
)
232 def set_orient_thresh(self
, thresh
):
233 '''Set orientation threshold'''
234 WT
.do(wiiuse
.set_orient_threshold
, self
.wm
, thresh
)
237 '''Trigger a status callback.'''
238 WT
.do(wiiuse
.status
, self
.wm
)
240 def disconnect(self
):
241 '''Disconnect this Wiimote'''
242 WT
.do(wiiuse
.disconnect(self
.wm
))
245 '''Get the object for the nth Wiimote'''