Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / SCClassLibrary / Common / Control / WII.sc
blobfa929d0524e07a159c4ac7b203c5b34cf20a0f92
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
8 WiiCalibrationInfo {
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;
13         printOn { | stream |
14                 stream
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
34                 << $)
35         }
38 WiiMoteIRObject{
39         var <>id, <>valid, <>posx, <>posy, <>size;
40         var <>action;
43 WiiMote {
44         var dataPtr, <spec, <actionSpec; // <slots
45         var <>id;
46         var <battery;
47         var <ext_type;
48         var <>closeAction, <>connectAction, <>disconnectAction;
49         var <calibration;
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;
54         classvar all;
55         classvar < eventLoopIsRunning = false;
56 //      classvar < updateDataTask, <updateTask;
58         *initClass {
59                 all = [];
60         }
62         *devicesMap{
63                 ^(
64                         wii_mote: [
65                                 \ax, \ay, \az, \ao,
66                                 \bA, \bB, \bOne, \bTwo,
67                                 \bMinus, \bHome, \bPlus, \bUp, \bDown, \bLeft, \bRight,
68                                 \led1, \led2, \led3, \led4,
69                                 \battery
70                         ],
71                         wii_nunchuk: [
72                                 \nax, \nay, \naz, \nao, \nsx, \nsy, \nbZ, \nbC
73                         ],
74                         wii_classic: [
75                                 \cbX, \cbY, \cbA, \cbB, \cbL, \cbR,
76                                 \cbZL, \cbZR,
77                                 \cbUp, \cbDown, \cbLeft, \cbRight,
78                                 \cbMinus, \cbHome, \cbPlus,
79                                 \csx1, \csy1, \csx2, \csy2,
80                                 \caleft, \caright
81                         ]
82                 )
83         }
85         deviceSpec {
86                 ^(
87                         battery: { battery },
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] }
150                 )
151         }
153         *all {
154                 ^all.copy
155         }
156         *closeAll {
157                 all.copy.do({ | dev | dev.close });
158         }
159         *new { |id|
160                 ^super.new.id_(id).prInit();
161         }
162         isOpen {
163                 ^dataPtr.notNil
164         }
165         reconnect{
166                 this.disconnect;
167                 this.connect;
168         }
169         connect{
170                 ^this.prConnect;
171         }
172         disconnect{
173                 ^this.prDisconnect;
174         }
175         address{
176                 ^this.prAddress;
177         }
178         /*
179         setAddress{ |address|
180                 ^this.prSetAddress( address );
181                 }*/
182         close {
183                 if (this.isOpen) {
184                         this.prClose;
185                         //      all.remove(this);
186                 };
187                 try { all.remove( this ) };
188         }
189         setAction{ |key,keyAction|
190                 actionSpec.put( key, keyAction );
191         }
192         removeAction{ |key|
193                 actionSpec.removeAt( key );
194         }
195         at { | controlName |
196                 ^this.spec.atFail(controlName, {
197                         Error("invalid control name").throw
198                 });
199         }
200         /*
201         getLEDState { |id|
202                 this.prWiiGetLED( remote_led );
203                 ^remote_led[id]
204                 }*/
205         setLEDState { |id,state|
206                 var r;
207                 remote_led[id] = state;
208                 actionSpec.at( (\led ++ (id+1) ).asSymbol ).value( state );
209                 r = this.prWiiSetLED( remote_led );
210                 //              this.update;
211                 ^r;
212         }
213         /*
214         getExpansion{
215                 ^this.prGetExpansion;
216                 }*/
218         enable{ |onoff|
219                 this.prEnable( onoff );
220                 //              this.update;
221         }
222         enableExpansion{ |onoff|
223                 this.prEnableExpansion( onoff );
224                 //              this.update;
225         }
226         enableButtons{ |onoff|
227                 this.prEnableButtons( onoff );
228                 //              this.update;
229         }
230         enableMotionSensor{ |onoff|
231                 this.prEnableMotionSensor( onoff );
232                 //              this.update;
233         }
234         enableIRSensor{ |onoff|
235                 this.prEnableIRSensor( onoff );
236                 //              this.update;
237         }
238         rumble{ |onoff|
239                 this.prSetVibration( onoff );
240                 //              this.update;
241         }
242         /*
243         playSample{ |play,freq,vol,sample=0|
244                 this.prPlaySpeaker( play, freq, vol, sample );
245                 //              this.update;
246         }
247         mute{ |onoff|
248                 this.prMuteSpeaker( onoff );
249                 //              this.update;
250         }
251         enableSpeaker{ |onoff|
252                 this.prEnableSpeaker( onoff );
253                 //              this.update;
254         }
255         initSpeaker{ |format=0|
256                 this.prInitSpeaker( format );
257                 //              this.update;
258                 }*/
260         *start{ |updtime=50|
261                 ShutDown.add {
262                         this.closeAll;
263                         this.prStop;
264                 };
265                 this.prStart( updtime );
266                 eventLoopIsRunning = true;
267         }
269         *discover{
270                 var newid, newwii, newall;
271                 if ( eventLoopIsRunning.not, { this.start; } );
272                 newid = all.size;
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.
278                         all = newall;
279                         ^newwii;
280                 };
281                 ^nil;
282         }
284         *stop{
285                 this.prStop;
286                 eventLoopIsRunning = false;
287         }
289         // PRIVATE
290         prInit {
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 );
302                 battery = 0;
304                 this.prOpen;
306                 closeAction = {};
307                 connectAction = {};
308                 disconnectAction = {};
310                 //              //              this.prWiiGetLED( remote_led );
311                 //              calibration = this.prCalibration(WiiCalibrationInfo.new);
313                 spec = this.deviceSpec;
314                 actionSpec = IdentityDictionary.new;
315         }
316         *prStart { |updtime=0.05|
317                 _Wii_Start;
318                 ^this.primitiveFailed
319         }
320         *prStop {
321                 _Wii_Stop;
322                 ^this.primitiveFailed
323         }
324         *prDiscover { |newid,alldevices|
325                 _Wii_Discover
326                 ^this.primitiveFailed
327         }
328         prOpen {
329                 _Wii_Open;
330                 ^this.primitiveFailed
331         }
332         prClose {
333                 _Wii_Close;
334                 ^this.primitiveFailed
335         }
336         prAddress { |address|
337                 _Wii_Address;
338                 ^this.primitiveFailed
339         }
340         /*
341         prSetAddress { |address|
342                 _Wii_SetAddress;
343                 ^this.primitiveFailed
344                 }*/
345         prConnect {
346                 _Wii_Connect;
347                 ^this.primitiveFailed
348         }
349         prDisconnect {
350                 _Wii_Disconnect;
351                 ^this.primitiveFailed
352         }
353         prCalibration { |calib|
354                 _Wii_Calibration;
355                 ^this.primitiveFailed
356         }
357         /*      prGetExpansion {
358                 _Wii_GetExpansion;
359                 ^this.primitiveFailed
360         }
361         prGetBattery {
362                 _Wii_GetBattery;
363                 ^this.primitiveFailed
364                 }*/
365         prEnable { |onoff|
366                 _Wii_Enable;
367                 ^this.primitiveFailed
368         }
369         prEnableExpansion { |onoff|
370                 _Wii_EnableExpansion;
371                 ^this.primitiveFailed
372         }
373         prEnableIRSensor { |onoff|
374                 _Wii_EnableIRSensor;
375                 ^this.primitiveFailed
376         }
377         prEnableMotionSensor { |onoff|
378                 _Wii_EnableMotionSensor;
379                 ^this.primitiveFailed
380         }
381         prEnableButtons { |onoff|
382                 _Wii_EnableButtons;
383                 ^this.primitiveFailed
384         }
385         prSetVibration { |onoff|
386                 _Wii_SetVibration;
387                 ^this.primitiveFailed
388         }
389         /*
390         prPlaySpeaker { |play, freq, vol, sample |
391                 _Wii_PlaySpeaker;
392                 ^this.primitiveFailed
393         }
394         prMuteSpeaker { |onoff |
395                 _Wii_MuteSpeaker;
396                 ^this.primitiveFailed
397         }
398         prInitSpeaker { |format|
399                 _Wii_InitSpeaker;
400                 ^this.primitiveFailed
401         }
402         prEnableSpeaker { |onoff |
403                 _Wii_EnableSpeaker;
404                 ^this.primitiveFailed
405         }
406         */
407         /*      prWiiGetLED { | states |
408                 _Wii_GetLED;
409                 ^this.primitiveFailed
410                 }*/
411         prWiiSetLED { |states|
412                 _Wii_SetLED;
413                 ^this.primitiveFailed
414         }
416         prHandleBatteryEvent{ |batlevel|
417                 battery = batlevel;
418                 actionSpec.at( \battery ).value( spec.at( \battery ).value );
419                 // battery action
420         }
422         prHandleExtensionEvent{ |exttype|
423                 ext_type = exttype;
424         }
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; });
434                 }
435         }
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; });
447                 }
448         }
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; });
461                 }
462         }
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;
467         }
469         prHandleAccEvent{ |accX,accY,accZ|
470                 remote_motion = [ accX, accY, accZ, 0 ];
471                 // actions:
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; });
475                 }
476         }
478         prHandleEvent {
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 ];
484                 ext_type = extType;
485                 if ( extType == 1, {
486                         nunchuk_buttons = eButtonData;
487                         nunchuk_motion = [ eData3, eData4, eData5, eData6/3 ];
488                         nunchuk_stick = [ eData1, eData2 ];
489                 });
490                 if ( extType == 2, {
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];
496                 });
498                 // event callback
499                 spec.keysValuesDo{ |key,val,i|
500                         actionSpec.at( key ).value( val.value );
501                         if ( dumpEvents, { (key + val.value.round(0.00001)).postln; });
502                 }
503         }
505         prReadError{
506                 this.close;
507                 "WiiMote read error".warn;
508                 closeAction.value;
509         }
511         prConnectAction{
512                 "WiiMote connected".postln;
513                 connectAction.value;
514         }
516         prDisconnectAction{
517                 "WiiMote disconnected!".warn;
518                 disconnectAction.value;
519         }
522 // EOF