Update of /cvsroot/pure-data/externals/io/wiiremote
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30283/io/wiiremote
Added Files:
COPYRIGHT.txt Makefile aka.wiiremote.c wiiremote.c wiiremote.h
Log Message:
first stab at porting the Max aka.wiiremote object. it builds now, but I don't think it works
--- NEW FILE: COPYRIGHT.txt ---
Max porting by Masayuki Akamatsu
Copyright (c) 2006, Masayuki Akamatsu
Based on "DarwiinRemote" by Hiroaki Kimura
Copyright (c) 2006, Hiroaki Kimura
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of this project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- NEW FILE: wiiremote.c ---
// wiiremote.c
// Copyright by Masayuki Akamatsu
// Based on "DarwiinRemote" by Hiroaki Kimura
#include "wiiremote.h"
// this type is used a lot (data array):
typedef unsigned char darr[];
#define kTrial 10
static WiiRemoteRec gWiiRemote;
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
WiiRemoteRef wiiremote_init(void)
{
gWiiRemote.inquiry = nil;
gWiiRemote.device = nil;
gWiiRemote.ichan = nil;
gWiiRemote.cchan = nil;
gWiiRemote.accX = 0x10;
gWiiRemote.accY = 0x10;
gWiiRemote.accZ = 0x10;
gWiiRemote.buttonData = 0;
gWiiRemote.leftPoint = -1;
gWiiRemote.tracking = false;
gWiiRemote.batteryLevel = 0;
gWiiRemote.isIRSensorEnabled = false;
gWiiRemote.isMotionSensorEnabled = false;
gWiiRemote.isVibrationEnabled = false;
gWiiRemote.isExpansionPortUsed = false;
gWiiRemote.isLED1Illuminated = false;
gWiiRemote.isLED2Illuminated = false;
gWiiRemote.isLED3Illuminated = false;
gWiiRemote.isLED4Illuminated = false;
return &gWiiRemote;
}
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
void checkDevice(IOBluetoothDeviceRef device)
{
CFStringRef myString;
myString = IOBluetoothDeviceGetName(device);
if (CFStringCompare(myString, CFSTR("Nintendo RVL-CNT-01"), 0) == kCFCompareEqualTo)
{
gWiiRemote.device = IOBluetoothObjectRetain(device);
}
}
IOBluetoothDeviceInquiryDeviceFoundCallback myFoundFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device)
{
checkDevice(device);
}
IOBluetoothDeviceInquiryDeviceNameUpdatedCallback myUpdatedFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOBluetoothDeviceRef device, uint32_t devicesRemaining)
{
checkDevice(device);
}
IOBluetoothDeviceInquiryCompleteCallback myCompleteFunc(void *refCon, IOBluetoothDeviceInquiryRef inquiry, IOReturn error, Boolean aborted)
{
IOReturn result;
if (aborted) return; // called by stop ;)
if (error != kIOReturnSuccess)
{
wiiremote_stopsearch();
return;
}
}
//--------------------------------------------------------------------------------------------
Boolean wiiremote_search(void)
{
IOReturn ret;
if (gWiiRemote.inquiry != nil)
return true;
gWiiRemote.inquiry = IOBluetoothDeviceInquiryCreateWithCallbackRefCon(nil);
IOBluetoothDeviceInquirySetDeviceFoundCallback(gWiiRemote.inquiry, myFoundFunc);
IOBluetoothDeviceInquirySetDeviceNameUpdatedCallback(gWiiRemote.inquiry, myUpdatedFunc);
IOBluetoothDeviceInquirySetCompleteCallback(gWiiRemote.inquiry, myCompleteFunc);
ret = IOBluetoothDeviceInquiryStart(gWiiRemote.inquiry);
if (ret != kIOReturnSuccess)
{
IOBluetoothDeviceInquiryDelete(gWiiRemote.inquiry);
gWiiRemote.inquiry = nil;
return false;
}
return true;
}
Boolean wiiremote_stopsearch(void)
{
IOReturn ret;
if (gWiiRemote.inquiry == nil)
{
return true; // already stopped
}
ret = IOBluetoothDeviceInquiryStop(gWiiRemote.inquiry);
if (ret != kIOReturnSuccess && ret != kIOReturnNotPermitted)
{
// kIOReturnNotPermitted is if it's already stopped
}
IOBluetoothDeviceInquiryDelete(gWiiRemote.inquiry);
gWiiRemote.inquiry = nil;
return (ret==kIOReturnSuccess);
}
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
IOBluetoothL2CAPChannelIncomingDataListener myDataListener(IOBluetoothL2CAPChannelRef channel, void *data, UInt16 length, void *refCon)
{
unsigned char *dp = (unsigned char*)data;
if (dp[1] == 0x20 && length >= 8)
{
gWiiRemote.batteryLevel = (double)dp[7];
gWiiRemote.batteryLevel /= (double)0xC0;
gWiiRemote.isExpansionPortUsed = (dp[4] & 0x02) != 0;
gWiiRemote.isLED1Illuminated = (dp[4] & 0x10) != 0;
gWiiRemote.isLED2Illuminated = (dp[4] & 0x20) != 0;
gWiiRemote.isLED3Illuminated = (dp[4] & 0x40) != 0;
gWiiRemote.isLED4Illuminated = (dp[4] & 0x80) != 0;
//have to reset settings (vibration, motion, IR and so on...)
wiiremote_irsensor(gWiiRemote.isIRSensorEnabled);
}
if ((dp[1]&0xF0) == 0x30)
{
gWiiRemote.buttonData = ((short)dp[2] << 8) + dp[3];
if (dp[1] & 0x01)
{
gWiiRemote.accX = dp[4];
gWiiRemote.accY = dp[5];
gWiiRemote.accZ = dp[6];
gWiiRemote.lowZ = gWiiRemote.lowZ * .9 + gWiiRemote.accZ * .1;
gWiiRemote.lowX = gWiiRemote.lowX * .9 + gWiiRemote.accX * .1;
float absx = abs(gWiiRemote.lowX - 128);
float absz = abs(gWiiRemote.lowZ - 128);
if (gWiiRemote.orientation == 0 || gWiiRemote.orientation == 2) absx -= 5;
if (gWiiRemote.orientation == 1 || gWiiRemote.orientation == 3) absz -= 5;
if (absz >= absx)
{
if (absz > 5)
gWiiRemote.orientation = (gWiiRemote.lowZ > 128) ? 0 : 2;
}
else
{
if (absx > 5)
gWiiRemote.orientation = (gWiiRemote.lowX > 128) ? 3 : 1;
}
//printf("orientation: %d\n", orientation);
}
if (dp[1] & 0x02)
{
int i;
for(i=0 ; i<4 ; i++)
{
gWiiRemote.irData[i].x = dp[7 + 3*i];
gWiiRemote.irData[i].y = dp[8 + 3*i];
gWiiRemote.irData[i].s = dp[9 + 3*i];
gWiiRemote.irData[i].x += (gWiiRemote.irData[i].s & 0x30) << 4;
gWiiRemote.irData[i].y += (gWiiRemote.irData[i].s & 0xC0) << 2;
gWiiRemote.irData[i].s &= 0x0F;
}
}
}
float ox, oy;
if (gWiiRemote.irData[0].s < 0x0F && gWiiRemote.irData[1].s < 0x0F)
{
int l = gWiiRemote.leftPoint, r;
if (gWiiRemote.leftPoint == -1)
{
// printf("Tracking.\n");
switch (gWiiRemote.orientation)
{
case 0: l = (gWiiRemote.irData[0].x < gWiiRemote.irData[1].x) ? 0 : 1; break;
case 1: l = (gWiiRemote.irData[0].y > gWiiRemote.irData[1].y) ? 0 : 1; break;
case 2: l = (gWiiRemote.irData[0].x > gWiiRemote.irData[1].x) ? 0 : 1; break;
case 3: l = (gWiiRemote.irData[0].y < gWiiRemote.irData[1].y) ? 0 : 1; break;
}
gWiiRemote.leftPoint = l;
}
r = 1-l;
float dx = gWiiRemote.irData[r].x - gWiiRemote.irData[l].x;
float dy = gWiiRemote.irData[r].y - gWiiRemote.irData[l].y;
float d = sqrt(dx*dx+dy*dy);
dx /= d;
dy /= d;
float cx = (gWiiRemote.irData[l].x+gWiiRemote.irData[r].x)/1024.0 - 1;
float cy = (gWiiRemote.irData[l].y+gWiiRemote.irData[r].y)/1024.0 - .75;
gWiiRemote.angle = atan2(dy, dx);
ox = -dy*cy-dx*cx;
oy = -dx*cy+dy*cx;
//printf("x:%5.2f; y: %5.2f; angle: %5.1f\n", ox, oy, angle*180/M_PI);
gWiiRemote.tracking = true;
}
else
{
// printf("Not tracking.\n");
ox = oy = -100;
gWiiRemote.leftPoint = -1;
gWiiRemote.tracking = false;
}
gWiiRemote.posX = ox;
gWiiRemote.posY = oy;
}
IOBluetoothL2CAPChannelIncomingEventListener myEventListener(IOBluetoothL2CAPChannelRef channel, void *refCon, IOBluetoothL2CAPChannelEvent *event)
{
switch (event->eventType)
{
case kIOBluetoothL2CAPChannelEventTypeData:
// In thise case:
// event->u.newData.dataPtr is a pointer to the block of data received.
// event->u.newData.dataSize is the size of the block of data.
myDataListener(channel, event->u.data.dataPtr, event->u.data.dataSize, refCon);
break;
case kIOBluetoothL2CAPChannelEventTypeClosed:
// In this case:
// event->u.terminatedChannel is the channel that was terminated. It can be converted in an IOBluetoothL2CAPChannel
// object with [IOBluetoothL2CAPChannel withL2CAPChannelRef:]. (see below).
break;
}
}
IOBluetoothUserNotificationCallback myDisconnectedFunc(void * refCon, IOBluetoothUserNotificationRef inRef, IOBluetoothObjectRef objectRef)
{
wiiremote_disconnect();
}
//--------------------------------------------------------------------------------------------
Boolean wiiremote_connect(void)
{
IOReturn result;
short i;
if (gWiiRemote.device == nil)
return false;
// connect the device
for (i=0; i<kTrial; i++)
{
if (IOBluetoothDeviceOpenConnection(gWiiRemote.device, nil, nil) == kIOReturnSuccess)
break;
usleep(10000); // wait 10ms
}
if (i==kTrial) return false;
gWiiRemote.disconnectNotification = IOBluetoothDeviceRegisterForDisconnectNotification(gWiiRemote.device, myDisconnectedFunc, 0);
// performs an SDP query
for (i=0; i<kTrial; i++)
{
if (IOBluetoothDevicePerformSDPQuery(gWiiRemote.device, nil, nil) == kIOReturnSuccess)
break;
usleep(10000); // wait 10ms
}
if (i==kTrial) return false;
// open L2CAPChannel : BluetoothL2CAPPSM = 17
for (i=0; i<kTrial; i++)
{
if (IOBluetoothDeviceOpenL2CAPChannelSync(gWiiRemote.device, &(gWiiRemote.cchan), 17, myEventListener, nil) == kIOReturnSuccess)
break;
usleep(10000); // wait 10ms
}
if (i==kTrial)
{
gWiiRemote.cchan = nil;
IOBluetoothDeviceCloseConnection(gWiiRemote.device);
return false;
}
// open L2CAPChannel : BluetoothL2CAPPSM = 19
for (i=0; i<kTrial; i++)
{
if (IOBluetoothDeviceOpenL2CAPChannelSync(gWiiRemote.device, &(gWiiRemote.ichan), 19, myEventListener, nil) == kIOReturnSuccess)
break;
usleep(10000); // wait 10ms
}
if (i==kTrial)
{
gWiiRemote.ichan = nil;
IOBluetoothL2CAPChannelCloseChannel(gWiiRemote.cchan);
IOBluetoothDeviceCloseConnection(gWiiRemote.device);
return false;
}
wiiremote_motionsensor(true);
wiiremote_irsensor(false);
wiiremote_vibration(false);
wiiremote_led(false, false, false, false);
return true;
}
Boolean wiiremote_disconnect(void)
{
short i;
if (gWiiRemote.disconnectNotification != nil)
{
IOBluetoothUserNotificationUnregister(gWiiRemote.disconnectNotification);
gWiiRemote.disconnectNotification = nil;
}
if (gWiiRemote.cchan && IOBluetoothDeviceIsConnected(gWiiRemote.device))
{
for (i=0; i<kTrial; i++)
{
if (IOBluetoothL2CAPChannelCloseChannel(gWiiRemote.cchan) == kIOReturnSuccess)
{
gWiiRemote.cchan = nil;
break;
}
}
if (i==kTrial) return false;
}
if (gWiiRemote.ichan && IOBluetoothDeviceIsConnected(gWiiRemote.device))
{
for (i=0; i<kTrial; i++)
{
if (IOBluetoothL2CAPChannelCloseChannel(gWiiRemote.ichan) == kIOReturnSuccess)
{
gWiiRemote.ichan = nil;
break;
}
}
if (i==kTrial) return false;
}
if (gWiiRemote.device && IOBluetoothDeviceIsConnected(gWiiRemote.device))
{
for (i=0; i<kTrial; i++)
{
if (IOBluetoothDeviceCloseConnection(gWiiRemote.device) == kIOReturnSuccess)
{
gWiiRemote.device = nil;
break;
}
}
if (i==kTrial) return false;
}
return true;
}
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
Boolean sendCommand(unsigned char *data, size_t length)
{
unsigned char buf[40];
IOReturn ret;
int i;
memset(buf,0,40);
buf[0] = 0x52;
memcpy(buf+1, data, length);
if (buf[1] == 0x16)
length=23;
else
length++;
for (i = 0; i<kTrial; i++)
{
ret = IOBluetoothL2CAPChannelWriteSync(gWiiRemote.cchan, buf, length);
if (ret == kIOReturnSuccess)
break;
usleep(10000);
}
return (ret==kIOReturnSuccess);
}
Boolean writeData(const unsigned char *data, unsigned long address, size_t length)
{
unsigned char cmd[22];
int i;
for(i=0 ; i<length ; i++) cmd[i+6] = data[i];
for(;i<16 ; i++) cmd[i+6]= 0;
cmd[0] = 0x16;
cmd[1] = (address>>24) & 0xFF;
cmd[2] = (address>>16) & 0xFF;
cmd[3] = (address>> 8) & 0xFF;
cmd[4] = (address>> 0) & 0xFF;
cmd[5] = length;
// and of course the vibration flag, as usual
if (gWiiRemote.isVibrationEnabled) cmd[1] |= 0x01;
data = cmd;
return sendCommand(cmd, 22);
}
//--------------------------------------------------------------------------------------------
Boolean wiiremote_motionsensor(Boolean enabled)
{
gWiiRemote.isMotionSensorEnabled = enabled;
unsigned char cmd[] = {0x12, 0x00, 0x30};
if (gWiiRemote.isVibrationEnabled) cmd[1] |= 0x01;
if (gWiiRemote.isMotionSensorEnabled) cmd[2] |= 0x01;
if (gWiiRemote.isIRSensorEnabled) cmd[2] |= 0x02;
return sendCommand(cmd, 3);
}
Boolean wiiremote_irsensor(Boolean enabled)
{
IOReturn ret;
gWiiRemote.isIRSensorEnabled = enabled;
// set register 0x12 (report type)
if (ret = wiiremote_motionsensor(gWiiRemote.isMotionSensorEnabled)) return ret;
// set register 0x13 (ir enable/vibe)
if (ret = wiiremote_vibration(gWiiRemote.isVibrationEnabled)) return ret;
// set register 0x1a (ir enable 2)
unsigned char cmd[] = {0x1a, 0x00};
if (enabled) cmd[1] |= 0x04;
if (ret = sendCommand(cmd, 2)) return ret;
if(enabled){
// based on marcan's method, found on wiili wiki:
// tweaked to include some aspects of cliff's setup procedure in the hopes
// of it actually turning on 100% of the time (was seeing 30-40% failure rate before)
// the sleeps help it it seems
usleep(10000);
if (ret = writeData((darr){0x01}, 0x04B00030, 1)) return ret;
usleep(10000);
if (ret = writeData((darr){0x08}, 0x04B00030, 1)) return ret;
usleep(10000);
if (ret = writeData((darr){0x90}, 0x04B00006, 1)) return ret;
usleep(10000);
if (ret = writeData((darr){0xC0}, 0x04B00008, 1)) return ret;
usleep(10000);
if (ret = writeData((darr){0x40}, 0x04B0001A, 1)) return ret;
usleep(10000);
if (ret = writeData((darr){0x33}, 0x04B00033, 1)) return ret;
usleep(10000);
if (ret = writeData((darr){0x08}, 0x04B00030, 1)) return ret;
}else{
// probably should do some writes to power down the camera, save battery
// but don't know how yet.
//bug fix #1614587
wiiremote_motionsensor(gWiiRemote.isMotionSensorEnabled);
wiiremote_vibration(gWiiRemote.isVibrationEnabled);
}
return true;
}
Boolean wiiremote_vibration(Boolean enabled)
{
gWiiRemote.isVibrationEnabled = enabled;
unsigned char cmd[] = {0x13, 0x00};
if (gWiiRemote.isVibrationEnabled) cmd[1] |= 0x01;
if (gWiiRemote.isIRSensorEnabled) cmd[1] |= 0x04;
return sendCommand(cmd, 2);;
}
Boolean wiiremote_led(Boolean enabled1, Boolean enabled2, Boolean enabled3, Boolean enabled4)
{
unsigned char cmd[] = {0x11, 0x00};
if (gWiiRemote.isVibrationEnabled) cmd[1] |= 0x01;
if (enabled1) cmd[1] |= 0x10;
if (enabled2) cmd[1] |= 0x20;
if (enabled3) cmd[1] |= 0x40;
if (enabled4) cmd[1] |= 0x80;
gWiiRemote.isLED1Illuminated = enabled1;
gWiiRemote.isLED2Illuminated = enabled2;
gWiiRemote.isLED3Illuminated = enabled3;
gWiiRemote.isLED4Illuminated = enabled4;
return sendCommand(cmd, 2);
}
void wiiremote_getstatus(void)
{
unsigned char cmd[] = {0x15, 0x00};
sendCommand(cmd, 2);
}
--- NEW FILE: wiiremote.h ---
// wiiremote.h
// Copyright by Masayuki Akamatsu
// Based on "DarwiinRemote" by Hiroaki Kimura
#include <CoreFoundation/CoreFoundation.h>
#include <IOBluetooth/Bluetooth.h>
#include <IOBluetooth/IOBluetoothUserLib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
int x, y, s;
} IRData;
typedef struct _WiiRemoteRec
{
IOBluetoothDeviceInquiryRef inquiry;
IOBluetoothDeviceRef device;
IOBluetoothL2CAPChannelRef ichan;
IOBluetoothL2CAPChannelRef cchan;
unsigned char accX;
unsigned char accY;
unsigned char accZ;
unsigned short buttonData;
float lowZ;
float lowX;
int orientation;
int leftPoint; // is point 0 or 1 on the left. -1 when not tracking.
float posX;
float posY;
float angle;
Boolean tracking;
IRData irData[4];
double batteryLevel;
Boolean isIRSensorEnabled;
Boolean isMotionSensorEnabled;
Boolean isVibrationEnabled;
Boolean isExpansionPortUsed;
Boolean isLED1Illuminated;
Boolean isLED2Illuminated;
Boolean isLED3Illuminated;
Boolean isLED4Illuminated;
IOBluetoothUserNotificationCallback *disconnectNotification;
} WiiRemoteRec, *WiiRemoteRef;
WiiRemoteRef wiiremote_init(void);
Boolean wiiremote_search(void);
Boolean wiiremote_stopsearch(void);
Boolean wiiremote_connect(void);
Boolean wiiremote_disconnect(void);
Boolean wiiremote_motionsensor(Boolean enabled);
Boolean wiiremote_irsensor(Boolean enabled);
Boolean wiiremote_vibration(Boolean enabled);
Boolean wiiremote_led(Boolean enabled1, Boolean enabled2, Boolean enabled3, Boolean enabled4);
void wiiremote_getstatus(void);
--- NEW FILE: Makefile ---
TARGET := $(shell pwd | sed 's|.*/\(.*\)$$|\1|')
EXTERNALS_ROOT := $(shell pwd | sed 's|^\(/.*externals\).*|\1|')
default:
make -C $(EXTERNALS_ROOT) $(TARGET)
install:
make -C $(EXTERNALS_ROOT) $(TARGET)_install
clean:
make -C $(EXTERNALS_ROOT) $(TARGET)_clean
test_locations:
make -C $(EXTERNALS_ROOT) test_locations
# for emacs
etags:
etags ../../../pd/src/*.h *.[ch] linux/input.h
make etags_`uname -s`
etags_Darwin:
etags -a HID\ Utilities\ Source/*.[ch] \
/System/Library/Frameworks/ForceFeedback.framework/Headers/*.h \
/System/Library/Frameworks/Carbon.framework/Headers/*.h \
/System/Library/Frameworks/IOKit.framework/Headers/hid*/*.[ch]
etags_Linux:
etags -a /usr/include/*.h linux/input.h /usr/include/sys/*.h
etags_MINGW:
etags -a /usr/include/*.h /usr/include/sys/*.h \
/usr/local/include/*.h /usr/local/include/sys/*.h
--- NEW FILE: aka.wiiremote.c ---
// aka.wiiremote.c
// Copyright by Masayuki Akamatsu
// port to Pd by Hans-Christoph Steiner <hans(a)at.or.at>
#ifdef PD
#include "m_pd.h"
#define SETLONG SETFLOAT
static t_class *wiiremote_class;
#else /* Max */
#include "ext.h"
#endif
#include "wiiremote.h"
#define kInterval 100
#define kMaxTrial 100
typedef struct _akawiiremote
{
#ifdef PD
t_object x_obj;
#else /* Max */
struct object obj;
#endif
WiiRemoteRef wiiremote;
void *clock;
long interval;
long trial;
void *statusOut;
void *buttonsOut;
void *irOut;
void *accOut;
} t_akawiiremote;
void *akawiiremote_class; // the number of instance of this object
short akawiiremote_count;
void akawiiremote_bang(t_akawiiremote *x);
void akawiiremote_connect(t_akawiiremote *x);
void akawiiremote_disconnect(t_akawiiremote *x);
void akawiiremote_motionsensor(t_akawiiremote *x, long enable);
void akawiiremote_irsensor(t_akawiiremote *x, long enable);
void akawiiremote_vibration(t_akawiiremote *x, long enable);
void akawiiremote_led(t_akawiiremote *x, long enable1, long enable2, long enable3, long enable4);
void akawiiremote_getbatterylevel(t_akawiiremote *x);
void akawiiremote_getexpansionstatus(t_akawiiremote *x);
void akawiiremote_getledstatus(t_akawiiremote *x);
void akawiiremote_assist(t_akawiiremote *x, void *b, long m, long a, char *s);
void akawiiremote_clock(t_akawiiremote *x);
void *akawiiremote_new(t_symbol *s, short ac, t_atom *av);
void akawiiremote_free(t_akawiiremote *x);
#ifdef PD
void wiiremote_setup()
{
wiiremote_class = class_new(gensym("wiiremote"),
(t_newmethod)akawiiremote_new,
(t_method)akawiiremote_free,
sizeof(t_akawiiremote),
CLASS_DEFAULT,
A_GIMME,0);
class_addbang(wiiremote_class,(t_method)akawiiremote_bang);
class_addmethod(wiiremote_class,(t_method)akawiiremote_connect,gensym("connect"),0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_disconnect,gensym("disconnect"),0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_motionsensor,gensym("motionsensor"), A_DEFFLOAT, 0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_irsensor,gensym("irsensor"), A_DEFFLOAT, 0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_vibration,gensym("vibration"), A_DEFFLOAT, 0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_led,gensym("led"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_getbatterylevel,gensym("getbatterylevel"),0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_getexpansionstatus,gensym("getexpansionstatus"),0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_getledstatus,gensym("getledstatus"),0);
class_addmethod(wiiremote_class,(t_method)akawiiremote_assist,gensym("assist"),A_CANT,0);
post("aka.wiiremote 1.0B2-UB by Masayuki Akamatsu");
post("\tPd port by Hans-Christoph Steiner");
akawiiremote_count = 0;
}
#else /* Max */
void main()
{
setup((t_messlist **)&akawiiremote_class, (method)akawiiremote_new, (method)akawiiremote_free, (short)sizeof(t_akawiiremote), 0L, A_GIMME, 0);
addbang((method)akawiiremote_bang);
addmess((method)akawiiremote_connect,"connect",0);
addmess((method)akawiiremote_disconnect,"disconnect",0);
addmess((method)akawiiremote_motionsensor,"motionsensor", A_DEFLONG, 0);
addmess((method)akawiiremote_irsensor,"irsensor", A_DEFLONG, 0);
addmess((method)akawiiremote_vibration,"vibration", A_DEFLONG, 0);
addmess((method)akawiiremote_led,"led", A_DEFLONG, A_DEFLONG, A_DEFLONG, A_DEFLONG, 0);
addmess((method)akawiiremote_getbatterylevel,"getbatterylevel",0);
addmess((method)akawiiremote_getexpansionstatus,"getexpansionstatus",0);
addmess((method)akawiiremote_getledstatus,"getledstatus",0);
addmess((method)akawiiremote_assist,"assist",A_CANT,0);
post("aka.wiiremote 1.0B2-UB by Masayuki Akamatsu");
akawiiremote_count = 0;
}
#endif /* PD */
//--------------------------------------------------------------------------------------------
void akawiiremote_bang(t_akawiiremote *x)
{
t_atom list[4];
if (x->wiiremote->device == nil)
return; // do nothing
#ifdef PD
outlet_float(x->buttonsOut, (t_float) x->wiiremote->buttonData);
if (x->wiiremote->isIRSensorEnabled)
{
SETFLOAT(list, x->wiiremote->posX);
SETFLOAT(list + 1, x->wiiremote->posY);
SETFLOAT(list + 2, x->wiiremote->angle);
SETFLOAT (list + 3, x->wiiremote->tracking);
outlet_list(x->irOut, &s_list, 4, list);
}
if (x->wiiremote->isMotionSensorEnabled)
{
SETFLOAT(list, x->wiiremote->accX);
SETFLOAT(list + 1, x->wiiremote->accY);
SETFLOAT(list + 2, x->wiiremote->accZ);
SETFLOAT(list + 3, x->wiiremote->orientation);
outlet_list(x->accOut, &s_list, 4, list);
}
#else /* Max */
outlet_int(x->buttonsOut, x->wiiremote->buttonData);
if (x->wiiremote->isIRSensorEnabled)
{
SETFLOAT(list, x->wiiremote->posX);
SETFLOAT(list + 1, x->wiiremote->posY);
SETFLOAT(list + 2, x->wiiremote->angle);
SETLONG (list + 3, x->wiiremote->tracking);
outlet_list(x->irOut, 0L, 4, &list);
}
if (x->wiiremote->isMotionSensorEnabled)
{
SETLONG(list, x->wiiremote->accX);
SETLONG(list + 1, x->wiiremote->accY);
SETLONG(list + 2, x->wiiremote->accZ);
SETLONG(list + 3, x->wiiremote->orientation);
outlet_list(x->accOut, 0L, 4, &list);
}
#endif /* PD */
wiiremote_getstatus();
}
void akawiiremote_connect(t_akawiiremote *x)
{
if (x->wiiremote->device == nil) // if not connected
{
if (x->wiiremote->inquiry == nil) // if not seatching
{
Boolean result;
result = wiiremote_search(); // start searching the device
x->trial = 0;
clock_delay(x->clock, 0); // start clock to check the device found
}
}
else // if already connected
{
t_atom status;
SETLONG(&status, 1);
outlet_anything(x->statusOut, gensym("connect"), 1, &status);
}
}
void akawiiremote_disconnect(t_akawiiremote *x)
{
Boolean result;
t_atom status;
result = wiiremote_disconnect();
SETLONG(&status, result);
outlet_anything(x->statusOut, gensym("disconnect"), 1, &status);
}
void akawiiremote_motionsensor(t_akawiiremote *x, long enable)
{
wiiremote_motionsensor(enable);
}
void akawiiremote_irsensor(t_akawiiremote *x, long enable)
{
wiiremote_irsensor(enable);
}
void akawiiremote_vibration(t_akawiiremote *x, long enable)
{
wiiremote_vibration(enable);
}
void akawiiremote_led(t_akawiiremote *x, long enable1, long enable2, long enable3, long enable4)
{
wiiremote_led(enable1, enable2, enable3, enable4);
}
//--------------------------------------------------------------------------------------------
void akawiiremote_getbatterylevel(t_akawiiremote *x)
{
t_atom status;
SETFLOAT(&status, x->wiiremote->batteryLevel);
outlet_anything(x->statusOut, gensym("batterylevel"), 1, &status);
}
void akawiiremote_getexpansionstatus(t_akawiiremote *x)
{
t_atom status;
SETLONG(&status, x->wiiremote->isExpansionPortUsed);
outlet_anything(x->statusOut, gensym("expansionstatus"), 1, &status);
}
void akawiiremote_getledstatus(t_akawiiremote *x)
{
t_atom list[4];
SETLONG(list, x->wiiremote->isLED1Illuminated);
SETLONG(list + 1, x->wiiremote->isLED2Illuminated);
SETLONG(list + 2, x->wiiremote->isLED3Illuminated);
SETLONG(list + 3, x->wiiremote->isLED4Illuminated);
#ifdef PD
outlet_anything(x->statusOut, gensym("ledstatus"), 4, list);
#else /* Max */
outlet_anything(x->statusOut, gensym("ledstatus"), 4, &list);
#endif
}
//--------------------------------------------------------------------------------------------
void akawiiremote_clock(t_akawiiremote *x)
{
Boolean result;
t_atom status;
if (x->wiiremote->device != nil) // if the device is found...
{
clock_unset(x->clock); // stop clock
wiiremote_stopsearch();
result = wiiremote_connect(); // connect to it
SETLONG(&status, result);
outlet_anything(x->statusOut, gensym("connect"), 1, &status);
}
else // if the device is not found...
{
x->trial++;
//SETLONG(&status, x->trial);
//outlet_anything(x->statusOut, gensym("searching"), 1, &status);
if (x->trial >= kMaxTrial) // if trial is over
{
clock_unset(x->clock); // stop clock
wiiremote_stopsearch();
SETLONG(&status, 0);
outlet_anything(x->statusOut, gensym("connect"), 1, &status);
}
else
{
//post("trial %d",x->trial);
clock_delay(x->clock, x->interval); // restart clock
}
}
}
//--------------------------------------------------------------------------------------------
void akawiiremote_assist(t_akawiiremote *x, void *b, long m, long a, char *s)
{
#ifndef PD /* Max */
if (m==ASSIST_INLET)
{
sprintf(s,"connect, bang, disconnect....");
}
else
#endif /* NOT PD */
{
switch(a)
{
case 0: sprintf(s,"list(acc-x acc-y acc-z orientation)"); break;
case 1: sprintf(s,"list(pos-x pos-y angle tracking)"); break;
case 2: sprintf(s,"int(buttons)"); break;
case 3: sprintf(s,"message(status)"); break;
}
}
}
//--------------------------------------------------------------------------------------------
void *akawiiremote_new(t_symbol *s, short ac, t_atom *av)
{
#ifdef PD
t_akawiiremote *x = (t_akawiiremote *)pd_new(wiiremote_class);
x->clock = clock_new(x, (t_method)akawiiremote_clock);
/* create anything outlet used for HID data */
x->statusOut = outlet_new(&x->x_obj, 0);
x->buttonsOut = outlet_new(&x->x_obj, &s_float);
x->irOut = outlet_new(&x->x_obj, &s_list);
x->accOut = outlet_new(&x->x_obj, &s_list);
#else /* Max */
t_akawiiremote *x;
x = (t_akawiiremote *)newobject(akawiiremote_class);
x->wiiremote = wiiremote_init();
x->clock = clock_new(x, (method)akawiiremote_clock);
x->statusOut = outlet_new(x, 0);
x->buttonsOut = intout(x);
x->irOut = listout(x);
x->accOut = listout(x);
#endif /* PD */
x->trial = 0;
x->interval = kInterval;
akawiiremote_count++;
return x;
}
void akawiiremote_free(t_akawiiremote *x)
{
akawiiremote_count--;
if (akawiiremote_count == 0)
wiiremote_disconnect();
#ifdef PD
if (x->clock)
clock_unset(x->clock);
clock_free(x->clock);
#else /* Max */
freeobject(x->clock);
#endif
}