2 #if defined(_WIN32) && defined(VRPN_USE_DIRECTINPUT) 16 const int STATUS_BROKEN = -1;
19 #define MAX_TIME_INTERVAL (2000000) // max time to try and reacquire 25 vrpn_DirectXFFJoystick::vrpn_DirectXFFJoystick (
const char * name,
vrpn_Connection * c,
26 double readRate,
double forceRate) :
31 _force_rate(forceRate),
40 _forcetime.tv_sec = 0;
41 _forcetime.tv_usec = 0;
44 _last_report.tv_sec = 0;
45 _last_report.tv_usec = 0;
52 _status = STATUS_BROKEN;
57 if (_numchannels < 12) {
58 fprintf(stderr,
"vrpn_DirectXFFJoystick::vrpn_DirectXFFJoystick(): Not enough analog channels!\n");
68 _hWnd = CreateWindow(
"STATIC",
"JoystickWindow", WS_ICONIC, 0,0, 10,10, NULL, NULL, NULL, NULL);
77 printf(
"vrpn_DirectXFFJoystick::vrpn_DirectXFFJoystick(): Window handle %ld\n", _hWnd);
79 if( FAILED( InitDirectJoystick() ) ) {
80 fprintf(stderr,
"vrpn_DirectXFFJoystick::vrpn_DirectXFFJoystick(): Failed to open direct joystick\n");
86 if (_force_rate > 0) {
88 send_normalized_force(0,0);
97 if (_force_rate > 0) {
100 fprintf(stderr,
"vrpn_DirectXFFJoystick:can't register plane handler\n");
105 fprintf(stderr,
"vrpn_DirectXFFJoystick:can't register force handler\n");
115 vrpn_DirectXFFJoystick::~vrpn_DirectXFFJoystick()
118 if ( _ForceEffect ) {
119 send_normalized_force(0,0);
120 _ForceEffect->Release();
127 _Joystick->Unacquire();
128 _Joystick->Release();
133 if ( _DirectInput ) {
134 _DirectInput->Release();
139 HRESULT vrpn_DirectXFFJoystick::InitDirectJoystick(
void )
147 IID_IDirectInput8, (VOID**)&_DirectInput, NULL ) ) ) {
148 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Cannot open DirectInput\n");
149 _status = STATUS_BROKEN;
155 long device_type = DIEDFL_ATTACHEDONLY;
156 if (_force_rate > 0) { device_type |= DIEDFL_FORCEFEEDBACK; }
157 if( FAILED( hr = _DirectInput->EnumDevices( DI8DEVCLASS_GAMECTRL,
158 EnumJoysticksCallback,
159 this, device_type ) ) ) {
160 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Cannot Enumerate devices\n");
161 _status = STATUS_BROKEN;
166 if( NULL == _Joystick ) {
167 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): No joystick found\n");
168 _status = STATUS_BROKEN;
177 if( FAILED( hr = _Joystick->SetDataFormat( &c_dfDIJoystick2 ) ) ) {
178 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Cannot set data format\n");
179 _status = STATUS_BROKEN;
188 long access_type = DISCL_EXCLUSIVE | DISCL_BACKGROUND;
189 if( FAILED( hr = _Joystick->SetCooperativeLevel( _hWnd, access_type) ) ) {
190 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Cannot set cooperative level\n");
191 _status = STATUS_BROKEN;
198 if( FAILED( hr = _Joystick->EnumObjects( EnumObjectsCallback,
this, DIDFT_ALL ) ) ) {
199 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Cannot enumerate objects\n");
200 _status = STATUS_BROKEN;
203 if (_force_rate > 0) {
204 if (_numforceaxes != 2) {
205 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Not two force axes, disabling forces\n");
209 printf(
"vrpn_DirectXFFJoystick::InitDirectJoystick(): found %d force axes\n", _numforceaxes);
214 dipdw.diph.dwSize =
sizeof(DIPROPDWORD);
215 dipdw.diph.dwHeaderSize =
sizeof(DIPROPHEADER);
216 dipdw.diph.dwObj = 0;
217 dipdw.diph.dwHow = DIPH_DEVICE;
218 dipdw.dwData = FALSE;
221 printf(
"vrpn_DirectXFFJoystick::InitDirectJoystick(): disabling autocenter\n");
223 if( FAILED( hr = _Joystick->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph ) ) ) {
224 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Can't disable autocenter, disabling forces\n");
228 DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };
229 LONG rglDirection[2] = { 0, 0 };
230 DICONSTANTFORCE cf = { 0 };
242 ZeroMemory( &eff,
sizeof(eff) );
243 eff.dwSize =
sizeof(DIEFFECT);
244 eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
246 eff.dwDuration = (DWORD)(0.02 * DI_SECONDS);
247 eff.dwSamplePeriod = 0;
248 eff.dwGain = DI_FFNOMINALMAX;
249 eff.dwTriggerButton = DIEB_NOTRIGGER;
250 eff.dwTriggerRepeatInterval = 0;
251 eff.cAxes = _numforceaxes;
252 eff.rgdwAxes = rgdwAxes;
253 eff.rglDirection = rglDirection;
256 eff.cbTypeSpecificParams =
sizeof(DICONSTANTFORCE);
257 eff.lpvTypeSpecificParams = &cf;
258 eff.dwStartDelay = 0;
261 if( FAILED( hr = _Joystick->CreateEffect( GUID_ConstantForce, &eff, &_ForceEffect, NULL ) ) ||
262 (_ForceEffect == NULL) ) {
263 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Can't create force effect, disabling forces\n");
271 if( FAILED( hr = _Joystick->Acquire() ) ) {
274 case DIERR_INVALIDPARAM:
275 reason =
"Invalid parameter";
277 case DIERR_NOTINITIALIZED:
278 reason =
"Not Initialized";
280 case DIERR_OTHERAPPHASPRIO:
281 reason =
"Another application has priority";
286 fprintf(stderr,
"vrpn_DirectXFFJoystick::InitDirectJoystick(): Cannot acquire joystick because %s\n", reason);
287 _status = STATUS_BROKEN;
298 BOOL CALLBACK vrpn_DirectXFFJoystick::EnumJoysticksCallback(
const DIDEVICEINSTANCE* pdidInstance,
301 vrpn_DirectXFFJoystick *me = (vrpn_DirectXFFJoystick*)(selfPtr);
305 printf(
"vrpn_DirectXFFJoystick::EnumJoysticksCallback(): Found joystick\n");
309 hr = me->_DirectInput->CreateDevice( pdidInstance->guidInstance, &me->_Joystick, NULL );
313 if( FAILED(hr) )
return DIENUM_CONTINUE;
325 BOOL CALLBACK vrpn_DirectXFFJoystick::EnumObjectsCallback(
const DIDEVICEOBJECTINSTANCE* pdidoi,
328 vrpn_DirectXFFJoystick *me = (vrpn_DirectXFFJoystick*)(selfPtr);
331 printf(
"vrpn_DirectXFFJoystick::EnumObjectsCallback(): Found type %d object\n", pdidoi->dwType);
335 if (pdidoi->dwType & DIDFT_AXIS) {
337 diprg.diph.dwSize =
sizeof(DIPROPRANGE);
338 diprg.diph.dwHeaderSize =
sizeof(DIPROPHEADER);
339 diprg.diph.dwHow = DIPH_BYID;
340 diprg.diph.dwObj = pdidoi->dwType;
345 if( FAILED( me->_Joystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
350 if (pdidoi->dwFlags & DIDOI_FFACTUATOR) {
354 return DIENUM_CONTINUE;
358 void vrpn_DirectXFFJoystick::clear_values(
void)
362 for (i = 0; i < _numbuttons; i++) {
365 for (i = 0; i < _numchannels; i++) {
375 int vrpn_DirectXFFJoystick::get_report(
void)
384 send_normalized_force(_fX, _fY);
390 struct timeval reporttime;
396 printf(
" now: %ld:%ld, last %ld:%ld\n", reporttime.tv_sec, reporttime.tv_usec,
397 _timestamp.tv_sec, static_cast<long>(_timestamp.tv_usec));
398 printf(
" DirectX joystick: Getting report\n");
403 hr = _Joystick->Poll();
409 hr = _Joystick->Acquire();
410 if ( hr == DIERR_INPUTLOST ) {
411 struct timeval resettime;
415 hr = _Joystick->Acquire();
417 if (hr == DIERR_INPUTLOST) {
418 fprintf(stderr,
"vrpn_DirectXFFJoystick::get_report::vrpn_DirectXFFJoystick::get_report(): Can't Acquire joystick\n");
419 _status = STATUS_BROKEN;
422 reporttime = resettime;
428 fprintf(stderr,
"Error other than INPUTLOST\n");
436 if( FAILED( hr = _Joystick->GetDeviceState(
sizeof(DIJOYSTATE2), &js ) ) ) {
437 fprintf(stderr,
"vrpn_DirectXFFJoystick::get_report(): Can't read joystick\n");
438 _status = STATUS_BROKEN;
441 channel[0] = js.lX / 1000.0;
442 channel[1] = js.lY / 1000.0;
443 channel[2] = js.lZ / 1000.0;
445 channel[3] = js.lRx / 1000.0;
446 channel[4] = js.lRy / 1000.0;
447 channel[5] = js.lRz / 1000.0;
449 channel[6] = js.rglSlider[0] / 1000.0;
450 channel[7] = js.rglSlider[1] / 1000.0;
452 channel[8] = (long)js.rgdwPOV[0] / 100.0;
453 channel[9] = (
long)js.rgdwPOV[1] / 100.0;
454 channel[10] = (long)js.rgdwPOV[2] / 100.0;
455 channel[11] = (
long)js.rgdwPOV[3] / 100.0;
459 buttons[i] = ( (js.rgbButtons[i] & 0x80) != 0);
463 _timestamp = reporttime;
468 void vrpn_DirectXFFJoystick::report_changes(vrpn_uint32 class_of_service)
477 void vrpn_DirectXFFJoystick::report(vrpn_uint32 class_of_service)
487 void vrpn_DirectXFFJoystick::send_normalized_force(
double fx,
double fy)
491 if ( (_force_rate <= 0) || (_ForceEffect == NULL) ) {
492 send_text_message(
"Asked to send force when no force enabled", _timestamp,
vrpn_TEXT_ERROR);
501 double len = sqrt(fx*fx + fy*fy);
510 double fx_avg = (fx + _fx_1 + _fx_2 )/3.0;
511 double fy_avg = (fy + _fy_1 + _fy_2 )/3.0;
518 INT xForce = (INT)(fx_avg * DI_FFNOMINALMAX);
519 INT yForce = (INT)(fy_avg * DI_FFNOMINALMAX);
521 _fx_2 = _fx_1; _fy_2 = _fy_1;
522 _fx_1 = fx; _fy_1 = fy;
524 LONG rglDirection[2];
527 rglDirection[0] = xForce;
528 rglDirection[1] = yForce;
529 cf.lMagnitude = (DWORD)(sqrt( (
double)xForce * (double)xForce +
530 (
double)yForce * (double)yForce ));
542 ZeroMemory( &eff,
sizeof(eff) );
543 eff.dwSize =
sizeof(DIEFFECT);
544 eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
545 eff.cAxes = _numforceaxes;
546 eff.rglDirection = rglDirection;
549 eff.cbTypeSpecificParams =
sizeof(DICONSTANTFORCE);
550 eff.lpvTypeSpecificParams = &cf;
551 eff.dwStartDelay = 0;
554 if ( FAILED ( _ForceEffect->SetParameters( &eff, DIEP_DIRECTION |
555 DIEP_TYPESPECIFICPARAMS |
566 void vrpn_DirectXFFJoystick::mainloop()
588 fprintf(stderr,
"vrpn_DirectXFFJoystick: Unknown mode (internal error)\n");
634 int vrpn_DirectXFFJoystick::handle_plane_change_message(
void *selfPtr,
637 vrpn_DirectXFFJoystick *me = (vrpn_DirectXFFJoystick *)selfPtr;
638 vrpn_float32 abcd[4];
639 vrpn_float32 kspring, kdamp, fricdynamic, fricstatic;
640 vrpn_int32 plane_index, plane_recovery_cycles;
641 double fscale = 0.25;
646 &kspring, &kdamp, &fricdynamic, &fricstatic,
647 &plane_index, &plane_recovery_cycles);
650 if ( (abcd[0] == 0) && (abcd[1] == 0) && (abcd[2] == 0) ) {
651 me->_fX = me->_fY = 0;
659 double len = sqrt(abcd[0]*abcd[0] + abcd[1]*abcd[1]);
660 me->_fX = abcd[0] / len;
661 me->_fY = abcd[1] / len;
669 me->_fX = fscale * abcd[0] / abcd[2];
670 me->_fY = fscale * abcd[1] / abcd[2];
676 int vrpn_DirectXFFJoystick::handle_forcefield_change_message(
void *selfPtr,
679 vrpn_DirectXFFJoystick *me = (vrpn_DirectXFFJoystick *)selfPtr;
681 vrpn_float32 center[3];
682 vrpn_float32 force[3];
683 vrpn_float32 jacobian[3][3];
696 int vrpn_DirectXFFJoystick::handle_last_connection_dropped(
void *selfPtr,
vrpn_HANDLERPARAM)
698 vrpn_DirectXFFJoystick *me = (vrpn_DirectXFFJoystick*)selfPtr;
699 if (me->_force_rate > 0) {
700 me->_fX = me->_fY = 0;
701 me->send_normalized_force(0,0);
virtual void report_changes(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report only if something has changed (for servers) Optionally, tell what time to stamp the val...
vrpn_float64 channel[vrpn_CHANNEL_MAX]
Generic connection class not specific to the transport mechanism.
virtual void report(vrpn_uint32 class_of_service=vrpn_CONNECTION_LOW_LATENCY, const struct timeval time=vrpn_ANALOG_NOW)
Send a report whether something has changed or not (for servers) Optionally, tell what time to stamp ...
const char * vrpn_dropped_last_connection
int register_autodeleted_handler(vrpn_int32 type, vrpn_MESSAGEHANDLER handler, void *userdata, vrpn_int32 sender=vrpn_ANY_SENDER)
Registers a handler with the connection, and remembers to delete at destruction.
vrpn_Connection * d_connection
Connection that this object talks to.
This structure is what is passed to a vrpn_Connection message callback.
#define MAX_TIME_INTERVAL
#define vrpn_gettimeofday
vrpn_int32 d_sender_id
Sender ID registered with the connection.
unsigned long vrpn_TimevalDuration(struct timeval endT, struct timeval startT)
Return number of microseconds between startT and endT.
virtual vrpn_int32 register_message_type(const char *name)
vrpn_float64 last[vrpn_CHANNEL_MAX]