1 /// NOTE: this code is still in an experimental state and only works on Linux, if compiled with Wii support.
2 /// Therefor, it also has no helpfile yet
3 /// This code may change without notice; do not use this code, unless you really want to and don't mind
4 /// having to change your code in the future.
5 /// Expect this code to be fully functional by version 3.2
6 /// - october 2007 - nescivi
9 var <accX_zero, <accY_zero, <accZ_zero, <accX_lg, <accY_lg, <accZ_lg;
10 var <nAccX_zero, <nAccY_zero, <nAccZ_zero, <nAccX_lg, <nAccY_lg, <nAccZ_lg;
11 var <nX_max, <nX_min, <nX_center, <nY_max, <nY_min, <nY_center;
15 << this.class.name << $(
16 << "accX_zero: " << accX_zero << ", "
17 << "accY_zero: " << accY_zero << ", "
18 << "accZ_zero: " << accZ_zero << ", "
19 << "accX_lg: " << accX_lg << ", "
20 << "accY_lg: " << accY_lg << ", "
21 << "accZ_lg: " << accZ_lg << ", "
22 << "nunchuk accX_zero: " << nAccX_zero << ", "
23 << "nunchuk accY_zero: " << nAccY_zero << ", "
24 << "nunchuk accZ_zero: " << nAccZ_zero << ", "
25 << "nunchuk accX_lg: " << nAccX_lg << ", "
26 << "nunchuk accY_lg: " << nAccY_lg << ", "
27 << "nunchuk accZ_lg: " << nAccZ_lg << ", "
28 << "nunchuk x_min: " << nX_min << ", "
29 << "nunchuk x_max: " << nX_max << ", "
30 << "nunchuk x_center: " << nX_center << ", "
31 << "nunchuk y_min: " << nY_min << ", "
32 << "nunchuk y_max: " << nY_max << ", "
33 << "nunchuk y_center: " << nY_center
39 var <>id, <>valid, <>posx, <>posy, <>size;
44 var dataPtr, <spec, <actionSpec; // <slots
48 var <>closeAction, <>connectAction, <>disconnectAction;
50 var <remote_led, <>remote_buttons, <>remote_motion, <>remote_ir;
51 var <>nunchuk_buttons, <>nunchuk_motion, <>nunchuk_stick;
52 var <>classic_buttons, <>classic_stick1, <>classic_stick2, <>classic_analog;
53 var <>dumpEvents = false;
55 classvar < eventLoopIsRunning = false;
56 // classvar < updateDataTask, <updateTask;
66 \bA, \bB, \bOne, \bTwo,
67 \bMinus, \bHome, \bPlus, \bUp, \bDown, \bLeft, \bRight,
68 \led1, \led2, \led3, \led4,
72 \nax, \nay, \naz, \nao, \nsx, \nsy, \nbZ, \nbC
75 \cbX, \cbY, \cbA, \cbB, \cbL, \cbR,
77 \cbUp, \cbDown, \cbLeft, \cbRight,
78 \cbMinus, \cbHome, \cbPlus,
79 \csx1, \csy1, \csx2, \csy2,
88 led1: { remote_led[0] },
89 led2: { remote_led[1] },
90 led3: { remote_led[2] },
91 led4: { remote_led[3] },
92 ax: { remote_motion[0] },
93 ay: { remote_motion[1] },
94 az: { remote_motion[2] },
95 ao: { remote_motion[3] },
97 bA: { remote_buttons[0] },
98 bB: { remote_buttons[1] },
99 bOne: { remote_buttons[2] },
100 bTwo: { remote_buttons[3] },
101 bMinus: { remote_buttons[4] },
102 bHome: { remote_buttons[5] },
103 bPlus: { remote_buttons[6] },
104 bUp: { remote_buttons[7] },
105 bDown: { remote_buttons[8] },
106 bLeft: { remote_buttons[9] },
107 bRight: { remote_buttons[10] },
109 /* px: { remote_ir[0] },
110 py: { remote_ir[1] },
111 angle: { remote_ir[2] },
112 tracking: { remote_ir[3] },
115 nax: { nunchuk_motion[0] },
116 nay: { nunchuk_motion[1] },
117 naz: { nunchuk_motion[2] },
118 nao: { nunchuk_motion[3] },
120 nsx: { nunchuk_stick[0] },
121 nsy: { nunchuk_stick[1] },
123 nbZ: { nunchuk_buttons[0] },
124 nbC: { nunchuk_buttons[1] },
126 cbX: { classic_buttons[0] },
127 cbY: { classic_buttons[1] },
128 cbA: { classic_buttons[2] },
129 cbB: { classic_buttons[3] },
130 cbL: { classic_buttons[4] },
131 cbR: { classic_buttons[5] },
132 cbZL: { classic_buttons[6] },
133 cbZR: { classic_buttons[7] },
134 cbUp: { classic_buttons[8] },
135 cbDown: { classic_buttons[9] },
136 cbLeft: { classic_buttons[10] },
137 cbRight: { classic_buttons[11] },
138 cbMinus: { classic_buttons[12] },
139 cbHome: { classic_buttons[13] },
140 cbPlus: { classic_buttons[14] },
142 csx1: { classic_stick1[0] },
143 csy1: { classic_stick1[1] },
145 csx2: { classic_stick2[0] },
146 csy2: { classic_stick2[1] },
148 caleft: { classic_analog[0] },
149 caright: { classic_analog[1] }
157 all.copy.do({ | dev | dev.close });
160 ^super.new.id_(id).prInit();
179 setAddress{ |address|
180 ^this.prSetAddress( address );
187 try { all.remove( this ) };
189 setAction{ |key,keyAction|
190 actionSpec.put( key, keyAction );
193 actionSpec.removeAt( key );
196 ^this.spec.atFail(controlName, {
197 Error("invalid control name").throw
202 this.prWiiGetLED( remote_led );
205 setLEDState { |id,state|
207 remote_led[id] = state;
208 actionSpec.at( (\led ++ (id+1) ).asSymbol ).value( state );
209 r = this.prWiiSetLED( remote_led );
215 ^this.prGetExpansion;
219 this.prEnable( onoff );
222 enableExpansion{ |onoff|
223 this.prEnableExpansion( onoff );
226 enableButtons{ |onoff|
227 this.prEnableButtons( onoff );
230 enableMotionSensor{ |onoff|
231 this.prEnableMotionSensor( onoff );
234 enableIRSensor{ |onoff|
235 this.prEnableIRSensor( onoff );
239 this.prSetVibration( onoff );
243 playSample{ |play,freq,vol,sample=0|
244 this.prPlaySpeaker( play, freq, vol, sample );
248 this.prMuteSpeaker( onoff );
251 enableSpeaker{ |onoff|
252 this.prEnableSpeaker( onoff );
255 initSpeaker{ |format=0|
256 this.prInitSpeaker( format );
261 UI.registerForShutdown({
265 this.prStart( updtime );
266 eventLoopIsRunning = true;
270 var newid, newwii, newall;
271 if ( eventLoopIsRunning.not, { this.start; } );
273 newwii = WiiMote.new;
274 "To discover the WiiMote, please press buttons 1 and 2 on the device and wait till the LEDs stop blinking".postln;
275 newall = all.copy.add(newwii);
276 if(this.prDiscover( newid, newall )) {
277 // prDiscover returns true if the device was added, so then update the 'all' array.
285 eventLoopIsRunning = false;
290 remote_led = Array.fill( 4, 0 );
291 remote_buttons = Array.fill( 11, 0 );
292 remote_motion = Array.fill( 4, 0 );
293 remote_ir = Array.fill( 4, { WiiMoteIRObject.new } );
294 nunchuk_buttons = Array.fill( 2, 0 );
295 nunchuk_motion = Array.fill( 4, 0 );
296 nunchuk_stick = Array.fill( 2, 0 );
297 classic_buttons = Array.fill( 15, 0 );
298 classic_stick1 = Array.fill( 2, 0 );
299 classic_stick2 = Array.fill( 2, 0 );
300 classic_analog = Array.fill( 2, 0 );
307 disconnectAction = {};
309 // // this.prWiiGetLED( remote_led );
310 // calibration = this.prCalibration(WiiCalibrationInfo.new);
312 spec = this.deviceSpec;
313 actionSpec = IdentityDictionary.new;
315 *prStart { |updtime=0.05|
317 ^this.primitiveFailed
321 ^this.primitiveFailed
323 *prDiscover { |newid,alldevices|
325 ^this.primitiveFailed
329 ^this.primitiveFailed
333 ^this.primitiveFailed
335 prAddress { |address|
337 ^this.primitiveFailed
340 prSetAddress { |address|
342 ^this.primitiveFailed
346 ^this.primitiveFailed
350 ^this.primitiveFailed
352 prCalibration { |calib|
354 ^this.primitiveFailed
358 ^this.primitiveFailed
362 ^this.primitiveFailed
366 ^this.primitiveFailed
368 prEnableExpansion { |onoff|
369 _Wii_EnableExpansion;
370 ^this.primitiveFailed
372 prEnableIRSensor { |onoff|
374 ^this.primitiveFailed
376 prEnableMotionSensor { |onoff|
377 _Wii_EnableMotionSensor;
378 ^this.primitiveFailed
380 prEnableButtons { |onoff|
382 ^this.primitiveFailed
384 prSetVibration { |onoff|
386 ^this.primitiveFailed
389 prPlaySpeaker { |play, freq, vol, sample |
391 ^this.primitiveFailed
393 prMuteSpeaker { |onoff |
395 ^this.primitiveFailed
397 prInitSpeaker { |format|
399 ^this.primitiveFailed
401 prEnableSpeaker { |onoff |
403 ^this.primitiveFailed
406 /* prWiiGetLED { | states |
408 ^this.primitiveFailed
410 prWiiSetLED { |states|
412 ^this.primitiveFailed
415 prHandleBatteryEvent{ |batlevel|
417 actionSpec.at( \battery ).value( spec.at( \battery ).value );
421 prHandleExtensionEvent{ |exttype|
425 prHandleButtonEvent{ |buttonData|
426 // buttonData are bits that decode to separate buttons (do in Primitive internally, and pass on Array?
427 //("handle button Event"+buttonData).postln;
428 remote_buttons = buttonData;
430 [ \bA, \bB, \bOne, \bTwo, \bMinus, \bHome, \bPlus, \bUp, \bDown, \bLeft, \bRight ].do{ |key|
431 actionSpec.at( key ).value( spec.at(key).value );
432 if ( dumpEvents, { (key + spec.at(key).value.round(0.00001)).postln; });
436 prHandleNunchukEvent{ |nunchukButtons, nunJoyX, nunJoyY, nunAccX, nunAccY, nunAccZ|
438 // buttonData are bits that decode to separate buttons (do in Primitive)
439 nunchuk_buttons = nunchukButtons;
440 nunchuk_motion = [ nunAccX, nunAccY, nunAccZ, 0 ];
441 nunchuk_stick = [ nunJoyX, nunJoyY ];
443 [ \nax, \nay, \naz, \nsx, \nsy, \nbZ, \nbC ].do{ |key|
444 actionSpec.at( key ).value( spec.at(key).value );
445 if ( dumpEvents, { (key + spec.at(key).value.round(0.00001)).postln; });
449 prHandleClassicEvent{ |clasButtons, clasJoy1X, clasJoy1Y, clasJoy2X, clasJoy2Y, clasL, clasR|
451 // buttonData are bits that decode to separate buttons (do in Primitive)
452 classic_buttons = clasButtons;
453 classic_stick1 = [clasJoy1X, clasJoy1Y];
454 classic_stick2 = [clasJoy2X, clasJoy2Y];
455 classic_analog = [clasL, clasR];
457 [ \cbX, \cbY, \cbA, \cbB, \cbL, \cbR, \cbZL, \cbZR, \cbUp, \cbDown, \cbLeft, \cbRight, \cbMinus, \cbHome, \cbPlus, \csx1, \csy1, \csx2, \csy2, \caleft, \caright ].do{ |key|
458 actionSpec.at( key ).value( spec.at(key).value );
459 if ( dumpEvents, { (key + spec.at(key).value.round(0.00001)).postln; });
463 prHandleIREvent{ |id,valid,posx,posy,size|
464 // make ir an array of WiiMoteIRObject's and assign data to right IR object, and do actions
465 remote_ir[id].valid_( valid ).posx_( posx ).posy_( posy ).size_( size ).action.value;
468 prHandleAccEvent{ |accX,accY,accZ|
469 remote_motion = [ accX, accY, accZ, 0 ];
471 [ \ax, \ay, \az ].do{ |key|
472 actionSpec.at( key ).value( spec.at(key).value );
473 if ( dumpEvents, { (key + spec.at(key).value.round(0.00001)).postln; });
478 | buttonData, posX, posY, angle, tracking, accX, accY, accZ, orientation, extType, eButtonData, eData1, eData2, eData3, eData4, eData5, eData6, batteryLevel |
479 battery = batteryLevel;
480 remote_buttons = buttonData;
481 remote_motion = [ accX, accY, accZ, orientation/3 ];
482 remote_ir = [ posX, posY, angle, tracking ];
485 nunchuk_buttons = eButtonData;
486 nunchuk_motion = [ eData3, eData4, eData5, eData6/3 ];
487 nunchuk_stick = [ eData1, eData2 ];
490 // classic_buttons.do{ |it,i| classic_buttons[i] = eButtonData.bitTest( i ).asInteger };
491 classic_buttons = eButtonData;
492 classic_stick1 = [eData1, eData2];
493 classic_stick2 = [eData3, eData4];
494 classic_analog = [eData5, eData6];
498 spec.keysValuesDo{ |key,val,i|
499 actionSpec.at( key ).value( val.value );
500 if ( dumpEvents, { (key + val.value.round(0.00001)).postln; });
506 "WiiMote read error".warn;
511 "WiiMote connected".postln;
516 "WiiMote disconnected!".warn;
517 disconnectAction.value;