# HG changeset patch # User Edgar Simo # Date 1216368204 0 # Node ID 924a32719b6f281e265f3114585319f146df1a45 # Parent 2d88b82ce781b5e85e7ed3a1c1f890a6d4b701a9 Handle axes for darwin now. Support for periodic effect sort of. More cleaning up. diff -r 2d88b82ce781 -r 924a32719b6f src/haptic/darwin/SDL_syshaptic.c --- a/src/haptic/darwin/SDL_syshaptic.c Fri Jul 18 08:00:16 2008 +0000 +++ b/src/haptic/darwin/SDL_syshaptic.c Fri Jul 18 08:03:24 2008 +0000 @@ -131,7 +131,7 @@ */ static unsigned int GetSupportedFeatures(FFDeviceObjectReference device, - int *neffects, int *nplaying) + int *neffects, int *nplaying, int *naxes) { HRESULT ret; FFCAPABILITIES features; @@ -182,6 +182,10 @@ return 0; } + /* Check for axes, we have an artificial limit on axes */ + *axes = ((features.numFfAxes) > 3) ? + 3 : features.numFfAxes; + /* Always supported features. */ supported |= SDL_HAPTIC_STATUS; return supported; @@ -211,7 +215,8 @@ /* Get supported features. */ haptic->supported = GetSupportedFeatures(haptic->hwdata->device, - &haptic->neffects, &haptic->nplaying); + &haptic->neffects, &haptic->nplaying, + &haptic->naxes); if (haptic->supported == 0) { /* Error since device supports nothing. */ goto open_err; } @@ -342,12 +347,20 @@ SDL_SYS_SetDirection( FFEFFECT * effect, SDL_HapticDirection *dir, int axes ) { LONG *rglDir; - dir = SDL_malloc( sizeof(LONG) * axes ); - if (dir == NULL) { + + /* Handle no axes a part. */ + if (dest->cAxes == 0) { + effect->rglDirection = NULL; + return 0; + } + + /* Has axes. */ + rglDir = SDL_malloc( sizeof(LONG) * axes ); + if (rglDir == NULL) { SDL_OutOfMemory(); return -1; } - SDL_memset( dir, 0, sizeof(LONG) * axes ); + SDL_memset( rglDir, 0, sizeof(LONG) * axes ); effect->rglDirection = rglDir; switch (dir->type) { @@ -376,10 +389,10 @@ #define CONVERT(x) (((x)*10000) / 0xFFFF ) /* - * Creates the FFStruct + * Creates the FFEFFECT from a SDL_HapticEffect. */ static int -SDL_SYS_ToFFEFFECT( FFEFFECT * dest, SDL_HapticEffect * src ) +SDL_SYS_ToFFEFFECT( SDL_Haptic * haptic, FFEFFECT * dest, SDL_HapticEffect * src ) { FFCONSTANTFORCE *constant; FFPERIODIC *periodic; @@ -391,6 +404,7 @@ SDL_HapticPeriodic *hap_periodic; SDL_HapticCondition *hap_condition; SDL_HapticRamp *hap_ramp; + DWORD *axes; /* Set global stuff. */ SDL_memset(dest, 0, sizeof(FFEFFECT)); @@ -408,10 +422,33 @@ dest->lpEnvelope = envelope; envelope->dwSize = sizeof(FFENVELOPE); /* Always should be this. */ + /* Axes. */ + dest->cAxes = haptic->naxes; + if (dest->cAxes > 0) { + axes = SDL_malloc(sizeof(DWORD) * dest->cAxes); + if (axes == NULL) { + SDL_OutOfMemory(); + return -1; + } + axes[0] = FFJOFS_X; /* Always at least one axis. */ + if (dest->cAxes > 1) { + axes[1] = FFJOFS_Y; + } + if (dest->cAxes > 2) { + axes[2] = FFJOFS_Z; + } + dest->rgdwAxes = axes; + } + + switch (src->type) { case SDL_HAPTIC_CONSTANT: hap_constant = &src->constant; constant = SDL_malloc( sizeof(FFCONSTANTFORCE) ); + if (constant == NULL) { + SDL_OutOfMemory(); + return -1; + } /* Specifics */ constant->lMagnitude = CONVERT(hap_constant->level); @@ -424,10 +461,6 @@ dest->dwTriggerRepeatInterval = hap_constant->interval; dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */ - /* Axes */ - dest->cAxes = 2; /* TODO handle */ - dest->rgdwAxes = 0; - /* Direction. */ if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) < 0) { return -1; @@ -441,14 +474,42 @@ break; - /* TODO finish */ - case SDL_HAPTIC_SINE: case SDL_HAPTIC_SQUARE: case SDL_HAPTIC_TRIANGLE: case SDL_HAPTIC_SAWTOOTHUP: case SDL_HAPTIC_SAWTOOTHDOWN: hap_periodic = &src->periodic; + periodic = SDL_malloc(sizeof(FFPERIODIC)); + if (periodic == NULL) { + SDL_OutOfMemory(); + return -1; + } + + /* Specifics */ + periodic->dwMagnitude = CONVERT(hap_periodic->magnitude); + periodic->lOffset = CONVERT(hap_periodic->offset); + periodic->dwPhase = hap_periodic->phase; + periodic->dwPeriod = hap_periodic->period * 1000; + dest->cbTypeSpecificParams = sizeof(FFPERIODIC); + dest->lpvTypeSpecificParams = periodic; + + /* Generics */ + dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */ + dest->dwTriggerButton = FFJOFS_BUTTON(hap_periodic->button); + dest->dwTriggerRepeatInterval = hap_periodic->interval; + dest->dwStartDelay = hap_periodic->delay * 1000; /* In microseconds. */ + + /* Direction. */ + if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes) < 0) { + return -1; + } + + /* Envelope */ + envelope->dwAttackLevel = CONVERT(hap_periodic->attack_level); + envelope->dwAttackTime = hap_periodic->attack_length * 1000; + envelope->dwFadeLevel = CONVERT(hap_periodic->fade_level); + envelope->dwFadeTime = hap_periodic->fade_length * 1000; break; @@ -476,6 +537,30 @@ /* + * Frees an FFEFFECT allocated by SDL_SYS_ToFFEFFECT. + */ +void SDL_SYS_HapticFreeFFEFFECT( FFEFFECT * effect ) +{ + if (effect->lpEnvelope != NULL) { + SDL_free(effect->lpEnvelope); + effect->lpEnvelope = NULL; + } + if (effect->rgdwAxes != NULL) { + SDL_free(effect->rgdwAxes); + effect->rgdwAxes = NULL; + } + if (effect->lpvTypeSpecificParams != NULL) { + SDL_free(effect->lpvTypeSpecificParams); + effect->lpvTypeSpecificParams = NULL; + } + if (effect->rglDirection != NULL) { + SDL_free(effect->rglDirection); + effect->rglDirection = NULL; + } +} + + +/* * Gets the effect type from the generic SDL haptic effect wrapper. */ CFUUIDRef SDL_SYS_HapticEffectType(struct haptic_effect * effect) @@ -539,25 +624,39 @@ SDL_malloc(sizeof(struct haptic_hweffect)); if (effect->hweffect == NULL) { SDL_OutOfMemory(); - return -1; + goto err_hweffect; } /* Get the type. */ type = SDL_SYS_HapticEffectType(effect); if (type == NULL) { - SDL_free(effect->hweffect); - effect->hweffect = NULL; - return -1; + goto err_hweffect; } /* Get the effect. */ - if (SDL_SYS_ToFFEFFECT( &effect->hweffect->effect, &effect->effect ) < 0) { - /* TODO cleanup alloced stuff. */ - return -1; + if (SDL_SYS_ToFFEFFECT(haptic, &effect->hweffect->effect, &effect->effect ) < 0) { + goto err_effectdone; } + /* Create the actual effect. */ ret = FFDeviceCreateEffect( haptic->hwdata->device, type, &effect->hweffect->effect, &effect->hweffect->ref ); + + if (ret != FF_OK) { + SDL_SetError("Haptic: Unable to create effect."); + goto err_effectdone; + } + + return 0; + +err_effectdone: + SDL_SYS_HapticFreeFFEFFECT(&effect->hweffect->effect); +err_hweffect: + if (effect->hweffect != NULL) { + SDL_free(effect->hweffect); + effect->hweffect = NULL; + } + return -1; }