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 );
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.
286 eventLoopIsRunning = false;
291 remote_led = Array.fill( 4, 0 );
292 remote_buttons = Array.fill( 11, 0 );
293 remote_motion = Array.fill( 4, 0 );
294 remote_ir = Array.fill( 4, { WiiMoteIRObject.new } );
295 nunchuk_buttons = Array.fill( 2, 0 );
296 nunchuk_motion = Array.fill( 4, 0 );
297 nunchuk_stick = Array.fill( 2, 0 );
298 classic_buttons = Array.fill( 15, 0 );
299 classic_stick1 = Array.fill( 2, 0 );
300 classic_stick2 = Array.fill( 2, 0 );
301 classic_analog = Array.fill( 2, 0 );
308 disconnectAction = {};
310 // // this.prWiiGetLED( remote_led );
311 // calibration = this.prCalibration(WiiCalibrationInfo.new);
313 spec = this.deviceSpec;
314 actionSpec = IdentityDictionary.new;
316 *prStart { |updtime=0.05|
318 ^this.primitiveFailed
322 ^this.primitiveFailed
324 *prDiscover { |newid,alldevices|
326 ^this.primitiveFailed
330 ^this.primitiveFailed
334 ^this.primitiveFailed
336 prAddress { |address|
338 ^this.primitiveFailed
341 prSetAddress { |address|
343 ^this.primitiveFailed
347 ^this.primitiveFailed
351 ^this.primitiveFailed
353 prCalibration { |calib|
355 ^this.primitiveFailed
359 ^this.primitiveFailed
363 ^this.primitiveFailed
367 ^this.primitiveFailed
369 prEnableExpansion { |onoff|
370 _Wii_EnableExpansion;
371 ^this.primitiveFailed
373 prEnableIRSensor { |onoff|
375 ^this.primitiveFailed
377 prEnableMotionSensor { |onoff|
378 _Wii_EnableMotionSensor;
379 ^this.primitiveFailed
381 prEnableButtons { |onoff|
383 ^this.primitiveFailed
385 prSetVibration { |onoff|
387 ^this.primitiveFailed
390 prPlaySpeaker { |play, freq, vol, sample |
392 ^this.primitiveFailed
394 prMuteSpeaker { |onoff |
396 ^this.primitiveFailed
398 prInitSpeaker { |format|
400 ^this.primitiveFailed
402 prEnableSpeaker { |onoff |
404 ^this.primitiveFailed
407 /* prWiiGetLED { | states |
409 ^this.primitiveFailed
411 prWiiSetLED { |states|
413 ^this.primitiveFailed
416 prHandleBatteryEvent{ |batlevel|
418 actionSpec.at( \battery ).value( spec.at( \battery ).value );
422 prHandleExtensionEvent{ |exttype|
426 prHandleButtonEvent{ |buttonData|
427 // buttonData are bits that decode to separate buttons (do in Primitive internally, and pass on Array?
428 //("handle button Event"+buttonData).postln;
429 remote_buttons = buttonData;
431 [ \bA, \bB, \bOne, \bTwo, \bMinus, \bHome, \bPlus, \bUp, \bDown, \bLeft, \bRight ].do{ |key|
432 actionSpec.at( key ).value( spec.at(key).value );
433 if ( dumpEvents, { (key + spec.at(key).value.round(0.00001)).postln; });
437 prHandleNunchukEvent{ |nunchukButtons, nunJoyX, nunJoyY, nunAccX, nunAccY, nunAccZ|
439 // buttonData are bits that decode to separate buttons (do in Primitive)
440 nunchuk_buttons = nunchukButtons;
441 nunchuk_motion = [ nunAccX, nunAccY, nunAccZ, 0 ];
442 nunchuk_stick = [ nunJoyX, nunJoyY ];
444 [ \nax, \nay, \naz, \nsx, \nsy, \nbZ, \nbC ].do{ |key|
445 actionSpec.at( key ).value( spec.at(key).value );
446 if ( dumpEvents, { (key + spec.at(key).value.round(0.00001)).postln; });
450 prHandleClassicEvent{ |clasButtons, clasJoy1X, clasJoy1Y, clasJoy2X, clasJoy2Y, clasL, clasR|
452 // buttonData are bits that decode to separate buttons (do in Primitive)
453 classic_buttons = clasButtons;
454 classic_stick1 = [clasJoy1X, clasJoy1Y];
455 classic_stick2 = [clasJoy2X, clasJoy2Y];
456 classic_analog = [clasL, clasR];
458 [ \cbX, \cbY, \cbA, \cbB, \cbL, \cbR, \cbZL, \cbZR, \cbUp, \cbDown, \cbLeft, \cbRight, \cbMinus, \cbHome, \cbPlus, \csx1, \csy1, \csx2, \csy2, \caleft, \caright ].do{ |key|
459 actionSpec.at( key ).value( spec.at(key).value );
460 if ( dumpEvents, { (key + spec.at(key).value.round(0.00001)).postln; });
464 prHandleIREvent{ |id,valid,posx,posy,size|
465 // make ir an array of WiiMoteIRObject's and assign data to right IR object, and do actions
466 remote_ir[id].valid_( valid ).posx_( posx ).posy_( posy ).size_( size ).action.value;
469 prHandleAccEvent{ |accX,accY,accZ|
470 remote_motion = [ accX, accY, accZ, 0 ];
472 [ \ax, \ay, \az ].do{ |key|
473 actionSpec.at( key ).value( spec.at(key).value );
474 if ( dumpEvents, { (key + spec.at(key).value.round(0.00001)).postln; });
479 | buttonData, posX, posY, angle, tracking, accX, accY, accZ, orientation, extType, eButtonData, eData1, eData2, eData3, eData4, eData5, eData6, batteryLevel |
480 battery = batteryLevel;
481 remote_buttons = buttonData;
482 remote_motion = [ accX, accY, accZ, orientation/3 ];
483 remote_ir = [ posX, posY, angle, tracking ];
486 nunchuk_buttons = eButtonData;
487 nunchuk_motion = [ eData3, eData4, eData5, eData6/3 ];
488 nunchuk_stick = [ eData1, eData2 ];
491 // classic_buttons.do{ |it,i| classic_buttons[i] = eButtonData.bitTest( i ).asInteger };
492 classic_buttons = eButtonData;
493 classic_stick1 = [eData1, eData2];
494 classic_stick2 = [eData3, eData4];
495 classic_analog = [eData5, eData6];
499 spec.keysValuesDo{ |key,val,i|
500 actionSpec.at( key ).value( val.value );
501 if ( dumpEvents, { (key + val.value.round(0.00001)).postln; });
507 "WiiMote read error".warn;
512 "WiiMote connected".postln;
517 "WiiMote disconnected!".warn;
518 disconnectAction.value;