#ifdef _WIN32 # define MSW // linker->befehlsausgabe: zusätzliche flags: "/export:wiimote_setup" #endif // TODO: // use RefreshState(): copy internal state to actual instance #ifdef _MSC_VER # pragma warning(disable: 4091) # define WIIEXTERN __declspec(dllexport) extern #else # define WIIEXTERN extern #endif #include #include "wiimote.h" #include // class and struct declarations for wiimote pd external: class wiimote4pd : public wiimote { public: private: t_object*m_obj; t_outlet *m_dataOut; t_outlet *m_statusOut; t_clock *m_clock; bool m_changed; typedef std::pair > datavec; std::vector < datavec> m_data; bool m_reportAccel, m_reportIR, m_reportNunchuk, m_reportClassic, m_reportBalance, m_reportMPlus, m_reportExt; bool m_connected; CRITICAL_SECTION DataLock; public: wiimote4pd(t_object*obj, t_outlet*dOut, t_outlet*sOut) : wiimote(), m_obj(obj), m_dataOut(dOut), m_statusOut(sOut), m_clock(NULL), m_changed(NO_CHANGE), m_reportAccel(false), m_reportIR(false), m_reportNunchuk(false), m_reportClassic(false), m_reportBalance(false), m_reportMPlus(false), m_reportExt(false), m_connected(false) { InitializeCriticalSection(&DataLock); m_clock = clock_new(this, (t_method)wiimote_tickCallback); } virtual ~wiimote4pd(void) { clock_free(m_clock); DeleteCriticalSection(&DataLock); } static void wiimote_tickCallback(wiimote4pd*x) { x->tick(); } void error(std::string s) { if(m_obj) pd_error(m_obj, "%s", s.c_str()); else ::error("[wiimote] %s", s.c_str()); } void state(void) { t_atom atom; SETFLOAT(&atom, m_connected); outlet_anything(m_statusOut, gensym("open"), 1, &atom); }; void state(bool connected) { m_connected=connected; state(); }; void data(const std::string&id, std::vector&d) { const unsigned int len=d.size(); t_atom*atoms=new t_atom[len]; unsigned int i=0; for(i=0; iv; // Wiimote specific) { if(changed & CONNECTION_LOST) { v.push_back(0); ADDvMSG(m_data, "state"); } if(changed & CONNECTED) { v.push_back(1); ADDvMSG(m_data, "state"); } if(changed & BATTERY_CHANGED || changed & BATTERY_DRAINED) { v.push_back(new_state.BatteryPercent * 0.01f); ADDvMSG(m_data, "battery"); } if(changed & BUTTONS_CHANGED) { unsigned char but1 = (new_state.Button.Bits & 0xFF00)>>8; unsigned char but2 = (new_state.Button.Bits & 0x00FF); v.push_back(but2); v.push_back(but1); ADDvMSG(m_data, "button"); } if(changed & ACCEL_CHANGED) { v.push_back(new_state.Acceleration.X); v.push_back(new_state.Acceleration.Y); v.push_back(new_state.Acceleration.Z); ADDvMSG(m_data, "acceleration"); #if 0 } if(changed & ORIENTATION_CHANGED) { // this is a cooked version of ACCEL } if(changed & LEDS_CHANGED) { // they won't change on their own, would they? #endif } if(changed & IR_CHANGED) { unsigned int i; for(i=0; i<4; i++) { const wiimote_state::ir::dot &dot = new_state.IR.Dot[i]; if(dot.bVisible) { v.push_back(i); v.push_back(dot.RawX); v.push_back(dot.RawY); v.push_back(dot.Size); ADDvMSG(m_data, "ir"); } } // - Extensions - // Nunchuk #if 0 } if(changed & NUNCHUK_CONNECTED) { } if(changed & NUNCHUK_BUTTONS_CHANGED) { } if(changed & NUNCHUK_ACCEL_CHANGED) { } if(changed & NUNCHUK_ORIENTATION_CHANGED) { } if(changed & NUNCHUK_JOYSTICK_CHANGED) { // Classic Controller (inc. Guitars etc) } if(changed & CLASSIC_CONNECTED) { } if(changed & CLASSIC_BUTTONS_CHANGED) { } if(changed & CLASSIC_JOYSTICK_L_CHANGED) { } if(changed & CLASSIC_JOYSTICK_R_CHANGED) { } if(changed & CLASSIC_TRIGGERS_CHANGED) { // Balance Board } if(changed & BALANCE_CONNECTED) { } if(changed & BALANCE_WEIGHT_CHANGED) { // Motion Plus } if(changed & MOTIONPLUS_DETECTED) { } if(changed & MOTIONPLUS_ENABLED) { } if(changed & MOTIONPLUS_SPEED_CHANGED) { } if(changed & MOTIONPLUS_EXTENSION_CONNECTED) { } if(changed & MOTIONPLUS_EXTENSION_DISCONNECTED) { #endif } unlock(); if(pristine) { sys_lock(); clock_delay(m_clock, 0); sys_unlock(); } } void tick(void) { lock(); m_changed=false; unsigned int i; for(i=0; i(32768.*vec[i].w_float); samples[i]=s; } bool res=Convert16bitMonoSamples (samples, true, length, freq, result); delete[]samples; return res; } wiimote_sample m_sample; void play(const std::string&arrayname) { bool res=array2sample(arrayname, m_sample); res=PlaySample(m_sample); } }; static t_class *wiimote_class; typedef struct _wiimote { t_object x_obj; // standard pd object (must be first in struct) wiimote4pd*x_wiimote; t_outlet*x_dataOut,*x_statusOut; } t_wiimote; static void wiimote_ctor(t_wiimote*x){ if(!x->x_wiimote) { try { x->x_wiimote=new wiimote4pd(&x->x_obj, x->x_dataOut, x->x_statusOut); } catch (int fourtytwo) { error("ouch! wiimote allocation failed fatally"); } } } static void wiimote_dtor(t_wiimote*x){ if(x->x_wiimote) { delete x->x_wiimote; } } static void wiimote_report(t_wiimote*x, t_symbol*s, t_float f) { if(!x->x_wiimote)return; x->x_wiimote->report(s->s_name, f>=0.5); #if 0 int flag=-1; if(gensym("status")==s) flag=CWIID_RPT_STATUS; else if(gensym("button")==s) flag=CWIID_RPT_BTN; else if(gensym("acceleration")==s) flag=CWIID_RPT_ACC; else if(gensym("ir")==s) flag=CWIID_RPT_IR; else if(gensym("nunchuk")==s) flag=CWIID_RPT_NUNCHUK; else if(gensym("classic")==s) flag=CWIID_RPT_CLASSIC; else if(gensym("balance")==s) flag=CWIID_RPT_BALANCE; else if(gensym("motionplus")==s) flag=CWIID_RPT_MOTIONPLUS; else if(gensym("ext")==s) flag=CWIID_RPT_EXT; else { pd_error(x, "unknown report mode '%s'", s->s_name); } if(flag!=-1) { if(onoff) { x->reportMode |= flag; } else { x->reportMode &= ~flag; } } wiimote_resetReportMode(x); #endif } static void wiimote_reportAcceleration(t_wiimote *x, t_floatarg f) { if(!x->x_wiimote)return; x->x_wiimote->report("acceleration", f>=0.5); } static void wiimote_reportIR(t_wiimote *x, t_floatarg f) { if(!x->x_wiimote)return; x->x_wiimote->report("ir", f>=0.5); } static void wiimote_reportNunchuk(t_wiimote *x, t_floatarg f) { if(!x->x_wiimote)return; x->x_wiimote->report("nunchuk", f>=0.5); } static void wiimote_reportMotionplus(t_wiimote *x, t_floatarg f) { if(!x->x_wiimote)return; x->x_wiimote->report("motionplus", f>=0.5); } static void wiimote_setReportMode(t_wiimote*x, t_floatarg r) { if(!x->x_wiimote)return; x->x_wiimote->error("setReportMode not implemented"); } static void wiimote_setLED(t_wiimote *x, t_floatarg f) { if(!x->x_wiimote)return; x->x_wiimote->SetLEDs(static_cast(f)); } static void wiimote_setRumble(t_wiimote *x, t_floatarg f) { if(!x->x_wiimote)return; x->x_wiimote->SetRumble(f > 0.5f); } // ============================================================== // The following function attempts to discover a wiimote. It requires // that the user puts the wiimote into 'discoverable' mode before being // called. This is done by pressing the red button under the battery // cover, or by pressing buttons 1 and 2 simultaneously. // TODO: Without pressing the buttons, I get a segmentation error. So far, I don't know why. static void wiimote_discover(t_wiimote *x) { wiimote_ctor(x); x->x_wiimote->Connect(); } static void wiimote_disconnect(t_wiimote *x) { if(!x->x_wiimote)return; x->x_wiimote->Disconnect(); delete x->x_wiimote;x->x_wiimote=NULL; } static void wiimote_play(t_wiimote* x, t_symbol*s) { if(!x->x_wiimote)return; x->x_wiimote->play(s->s_name); } static void wiimote_bang(t_wiimote *x) { if(!x->x_wiimote)return; x->x_wiimote->tick(); } // ============================================================== // ============================================================== static void *wiimote_new(t_symbol*s, int argc, t_atom *argv) { t_wiimote *x = NULL; x=(t_wiimote *)pd_new(wiimote_class); x->x_wiimote = NULL; x->x_dataOut =outlet_new(&x->x_obj, 0); x->x_statusOut=outlet_new(&x->x_obj, 0); wiimote_ctor(x); return (x); } static void wiimote_free(t_wiimote* x) { delete x->x_wiimote; x->x_wiimote=NULL; outlet_free(x->x_dataOut ); x->x_dataOut = NULL; outlet_free(x->x_statusOut); x->x_statusOut= NULL; } extern "C" { WIIEXTERN void wiimote_setup(void) { wiimote_class = class_new(gensym("wiimote"), (t_newmethod)wiimote_new, (t_method)wiimote_free, sizeof(t_wiimote), CLASS_DEFAULT, A_GIMME, 0); #if 0 class_addmethod(wiimote_class, (t_method) wiimote_debug, gensym("debug"), 0); class_addmethod(wiimote_class, (t_method) wiimote_status, gensym("status"), 0); /* connection settings */ // class_addmethod(wiimote_class, (t_method) wiimote_doConnect, gensym("connect"), A_DEFSYMBOL, A_DEFSYMBOL, 0); /* query data */ //... #endif class_addbang(wiimote_class, (t_method) wiimote_bang); /* connection handling */ class_addmethod(wiimote_class, (t_method) wiimote_disconnect, gensym("disconnect"), A_NULL); class_addmethod(wiimote_class, (t_method) wiimote_discover, gensym("discover"), A_NULL); /* activate WiiMote stuff */ class_addmethod(wiimote_class, (t_method) wiimote_setLED, gensym("setLED"), A_FLOAT, 0); class_addmethod(wiimote_class, (t_method) wiimote_setRumble, gensym("setRumble"), A_FLOAT, 0); /* report modes */ class_addmethod(wiimote_class, (t_method) wiimote_report, gensym("report"), A_SYMBOL, A_FLOAT, 0); /* legacy report modes */ class_addmethod(wiimote_class, (t_method) wiimote_setReportMode, gensym("setReportMode"), A_FLOAT, 0); class_addmethod(wiimote_class, (t_method) wiimote_reportAcceleration, gensym("reportAcceleration"), A_FLOAT, 0); class_addmethod(wiimote_class, (t_method) wiimote_reportIR, gensym("reportIR"), A_FLOAT, 0); class_addmethod(wiimote_class, (t_method) wiimote_reportNunchuk, gensym("reportNunchuck"), A_FLOAT, 0); class_addmethod(wiimote_class, (t_method) wiimote_reportNunchuk, gensym("reportNunchuk"), A_FLOAT, 0); class_addmethod(wiimote_class, (t_method) wiimote_reportMotionplus, gensym("reportMotionplus"), A_FLOAT, 0); /* play a sample */ class_addmethod(wiimote_class, (t_method) wiimote_play, gensym("play"), A_SYMBOL, 0); post("[wiimote]: reading data from the Wii remote controller"); post(" (c) 2011 IOhannes m zmölnig"); #ifdef VERSION post(" version " VERSION " published under the GNU General Public License"); #else post(" published under the GNU General Public License"); #endif post("contains WiiYourself! wiimote code by gl.tter http://gl.tter.org"); } }