src/haptic/darwin/SDL_syshaptic.c
branchgsoc2008_force_feedback
changeset 2527 924a32719b6f
parent 2522 0877146be013
child 2528 50414589501e
equal deleted inserted replaced
2526:2d88b82ce781 2527:924a32719b6f
   129 /*
   129 /*
   130  * Gets supported features.
   130  * Gets supported features.
   131  */
   131  */
   132 static unsigned int
   132 static unsigned int
   133 GetSupportedFeatures(FFDeviceObjectReference device,
   133 GetSupportedFeatures(FFDeviceObjectReference device,
   134                      int *neffects, int *nplaying)
   134                      int *neffects, int *nplaying, int *naxes)
   135 {
   135 {
   136    HRESULT ret;
   136    HRESULT ret;
   137    FFCAPABILITIES features;
   137    FFCAPABILITIES features;
   138    unsigned int supported;
   138    unsigned int supported;
   139    Uint32 val;
   139    Uint32 val;
   180    else if (ret != FFERR_UNSUPPORTED) {
   180    else if (ret != FFERR_UNSUPPORTED) {
   181       SDL_SetError("Haptic: Unable to get if device supports autocenter.");
   181       SDL_SetError("Haptic: Unable to get if device supports autocenter.");
   182       return 0;
   182       return 0;
   183    }
   183    }
   184 
   184 
       
   185    /* Check for axes, we have an artificial limit on axes */
       
   186    *axes = ((features.numFfAxes) > 3) ?
       
   187          3 : features.numFfAxes;
       
   188 
   185    /* Always supported features. */
   189    /* Always supported features. */
   186    supported |= SDL_HAPTIC_STATUS;
   190    supported |= SDL_HAPTIC_STATUS;
   187    return supported;
   191    return supported;
   188 }
   192 }
   189 
   193 
   209       goto creat_err;
   213       goto creat_err;
   210    }
   214    }
   211 
   215 
   212    /* Get supported features. */
   216    /* Get supported features. */
   213    haptic->supported = GetSupportedFeatures(haptic->hwdata->device,
   217    haptic->supported = GetSupportedFeatures(haptic->hwdata->device,
   214                                             &haptic->neffects, &haptic->nplaying);
   218                                             &haptic->neffects, &haptic->nplaying,
       
   219                                             &haptic->naxes);
   215    if (haptic->supported == 0) { /* Error since device supports nothing. */
   220    if (haptic->supported == 0) { /* Error since device supports nothing. */
   216       goto open_err;
   221       goto open_err;
   217    }
   222    }
   218    haptic->effects = (struct haptic_effect *)
   223    haptic->effects = (struct haptic_effect *)
   219          SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
   224          SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
   340  */
   345  */
   341 static int
   346 static int
   342 SDL_SYS_SetDirection( FFEFFECT * effect, SDL_HapticDirection *dir, int axes )
   347 SDL_SYS_SetDirection( FFEFFECT * effect, SDL_HapticDirection *dir, int axes )
   343 {
   348 {
   344    LONG *rglDir;
   349    LONG *rglDir;
   345    dir = SDL_malloc( sizeof(LONG) * axes );
   350 
   346    if (dir == NULL) {
   351    /* Handle no axes a part. */
       
   352    if (dest->cAxes == 0) {
       
   353       effect->rglDirection = NULL;
       
   354       return 0;
       
   355    }
       
   356 
       
   357    /* Has axes. */
       
   358    rglDir = SDL_malloc( sizeof(LONG) * axes );
       
   359    if (rglDir == NULL) {
   347       SDL_OutOfMemory();
   360       SDL_OutOfMemory();
   348       return -1;
   361       return -1;
   349    }
   362    }
   350    SDL_memset( dir, 0, sizeof(LONG) * axes );
   363    SDL_memset( rglDir, 0, sizeof(LONG) * axes );
   351    effect->rglDirection = rglDir;
   364    effect->rglDirection = rglDir;
   352 
   365 
   353    switch (dir->type) {
   366    switch (dir->type) {
   354       case SDL_HAPTIC_POLAR:
   367       case SDL_HAPTIC_POLAR:
   355          effect->dwFlags |= FFEFF_POLAR;
   368          effect->dwFlags |= FFEFF_POLAR;
   374    }
   387    }
   375 }
   388 }
   376 
   389 
   377 #define CONVERT(x)   (((x)*10000) / 0xFFFF )
   390 #define CONVERT(x)   (((x)*10000) / 0xFFFF )
   378 /*
   391 /*
   379  * Creates the FFStruct
   392  * Creates the FFEFFECT from a SDL_HapticEffect.
   380  */
   393  */
   381 static int
   394 static int
   382 SDL_SYS_ToFFEFFECT( FFEFFECT * dest, SDL_HapticEffect * src )
   395 SDL_SYS_ToFFEFFECT( SDL_Haptic * haptic, FFEFFECT * dest, SDL_HapticEffect * src )
   383 {
   396 {
   384    FFCONSTANTFORCE *constant;
   397    FFCONSTANTFORCE *constant;
   385    FFPERIODIC *periodic;
   398    FFPERIODIC *periodic;
   386    FFCONDITION *condition;
   399    FFCONDITION *condition;
   387    FFRAMPFORCE *ramp;
   400    FFRAMPFORCE *ramp;
   389    FFENVELOPE *envelope;
   402    FFENVELOPE *envelope;
   390    SDL_HapticConstant *hap_constant;
   403    SDL_HapticConstant *hap_constant;
   391    SDL_HapticPeriodic *hap_periodic;
   404    SDL_HapticPeriodic *hap_periodic;
   392    SDL_HapticCondition *hap_condition;
   405    SDL_HapticCondition *hap_condition;
   393    SDL_HapticRamp *hap_ramp;
   406    SDL_HapticRamp *hap_ramp;
       
   407    DWORD *axes;
   394 
   408 
   395    /* Set global stuff. */
   409    /* Set global stuff. */
   396    SDL_memset(dest, 0, sizeof(FFEFFECT));
   410    SDL_memset(dest, 0, sizeof(FFEFFECT));
   397    dest->dwSize = sizeof(FFEFFECT); /* Set the structure size. */
   411    dest->dwSize = sizeof(FFEFFECT); /* Set the structure size. */
   398    dest->dwSamplePeriod = 0; /* Not used by us. */
   412    dest->dwSamplePeriod = 0; /* Not used by us. */
   406    }
   420    }
   407    SDL_memset(envelope, 0, sizeof(FFENVELOPE));
   421    SDL_memset(envelope, 0, sizeof(FFENVELOPE));
   408    dest->lpEnvelope = envelope;
   422    dest->lpEnvelope = envelope;
   409    envelope->dwSize = sizeof(FFENVELOPE); /* Always should be this. */
   423    envelope->dwSize = sizeof(FFENVELOPE); /* Always should be this. */
   410 
   424 
       
   425    /* Axes. */
       
   426    dest->cAxes = haptic->naxes;
       
   427    if (dest->cAxes > 0) {
       
   428       axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
       
   429       if (axes == NULL) {
       
   430          SDL_OutOfMemory();
       
   431          return -1;
       
   432       }
       
   433       axes[0] = FFJOFS_X; /* Always at least one axis. */
       
   434       if (dest->cAxes > 1) {
       
   435          axes[1] = FFJOFS_Y;
       
   436       }
       
   437       if (dest->cAxes > 2) {
       
   438          axes[2] = FFJOFS_Z;
       
   439       }
       
   440       dest->rgdwAxes = axes;
       
   441    }
       
   442 
       
   443 
   411    switch (src->type) {
   444    switch (src->type) {
   412       case SDL_HAPTIC_CONSTANT:
   445       case SDL_HAPTIC_CONSTANT:
   413          hap_constant = &src->constant;
   446          hap_constant = &src->constant;
   414          constant = SDL_malloc( sizeof(FFCONSTANTFORCE) );
   447          constant = SDL_malloc( sizeof(FFCONSTANTFORCE) );
       
   448          if (constant == NULL) {
       
   449             SDL_OutOfMemory();
       
   450             return -1;
       
   451          }
   415 
   452 
   416          /* Specifics */
   453          /* Specifics */
   417          constant->lMagnitude = CONVERT(hap_constant->level);
   454          constant->lMagnitude = CONVERT(hap_constant->level);
   418          dest->cbTypeSpecificParams = sizeof(FFCONSTANTFORCE); 
   455          dest->cbTypeSpecificParams = sizeof(FFCONSTANTFORCE); 
   419          dest->lpvTypeSpecificParams = constant;
   456          dest->lpvTypeSpecificParams = constant;
   421          /* Generics */
   458          /* Generics */
   422          dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
   459          dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
   423          dest->dwTriggerButton = FFJOFS_BUTTON(hap_constant->button);
   460          dest->dwTriggerButton = FFJOFS_BUTTON(hap_constant->button);
   424          dest->dwTriggerRepeatInterval = hap_constant->interval;
   461          dest->dwTriggerRepeatInterval = hap_constant->interval;
   425          dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */
   462          dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */
   426 
       
   427          /* Axes */
       
   428          dest->cAxes = 2; /* TODO handle */
       
   429          dest->rgdwAxes = 0;
       
   430 
   463 
   431          /* Direction. */
   464          /* Direction. */
   432          if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) < 0) {
   465          if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) < 0) {
   433             return -1;
   466             return -1;
   434          }
   467          }
   439          envelope->dwFadeLevel = CONVERT(hap_constant->fade_level);
   472          envelope->dwFadeLevel = CONVERT(hap_constant->fade_level);
   440          envelope->dwFadeTime = hap_constant->fade_length * 1000;
   473          envelope->dwFadeTime = hap_constant->fade_length * 1000;
   441 
   474 
   442          break;
   475          break;
   443 
   476 
   444          /* TODO finish */
       
   445 
       
   446       case SDL_HAPTIC_SINE:
   477       case SDL_HAPTIC_SINE:
   447       case SDL_HAPTIC_SQUARE:
   478       case SDL_HAPTIC_SQUARE:
   448       case SDL_HAPTIC_TRIANGLE:
   479       case SDL_HAPTIC_TRIANGLE:
   449       case SDL_HAPTIC_SAWTOOTHUP:
   480       case SDL_HAPTIC_SAWTOOTHUP:
   450       case SDL_HAPTIC_SAWTOOTHDOWN:
   481       case SDL_HAPTIC_SAWTOOTHDOWN:
   451          hap_periodic = &src->periodic;
   482          hap_periodic = &src->periodic;
       
   483          periodic = SDL_malloc(sizeof(FFPERIODIC));
       
   484          if (periodic == NULL) {
       
   485             SDL_OutOfMemory();
       
   486             return -1;
       
   487          }
       
   488 
       
   489          /* Specifics */
       
   490          periodic->dwMagnitude = CONVERT(hap_periodic->magnitude);
       
   491          periodic->lOffset = CONVERT(hap_periodic->offset);
       
   492          periodic->dwPhase = hap_periodic->phase;
       
   493          periodic->dwPeriod = hap_periodic->period * 1000;
       
   494          dest->cbTypeSpecificParams = sizeof(FFPERIODIC);
       
   495          dest->lpvTypeSpecificParams = periodic;
       
   496 
       
   497          /* Generics */
       
   498          dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */
       
   499          dest->dwTriggerButton = FFJOFS_BUTTON(hap_periodic->button);
       
   500          dest->dwTriggerRepeatInterval = hap_periodic->interval;
       
   501          dest->dwStartDelay = hap_periodic->delay * 1000; /* In microseconds. */
       
   502          
       
   503          /* Direction. */
       
   504          if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes) < 0) {
       
   505             return -1;
       
   506          }
       
   507          
       
   508          /* Envelope */
       
   509          envelope->dwAttackLevel = CONVERT(hap_periodic->attack_level);
       
   510          envelope->dwAttackTime = hap_periodic->attack_length * 1000;
       
   511          envelope->dwFadeLevel = CONVERT(hap_periodic->fade_level);
       
   512          envelope->dwFadeTime = hap_periodic->fade_length * 1000;
   452 
   513 
   453          break;
   514          break;
   454 
   515 
   455       case SDL_HAPTIC_SPRING:
   516       case SDL_HAPTIC_SPRING:
   456       case SDL_HAPTIC_DAMPER:
   517       case SDL_HAPTIC_DAMPER:
   474    return 0;
   535    return 0;
   475 }
   536 }
   476 
   537 
   477 
   538 
   478 /*
   539 /*
       
   540  * Frees an FFEFFECT allocated by SDL_SYS_ToFFEFFECT.
       
   541  */
       
   542 void SDL_SYS_HapticFreeFFEFFECT( FFEFFECT * effect )
       
   543 {
       
   544    if (effect->lpEnvelope != NULL) {
       
   545       SDL_free(effect->lpEnvelope);
       
   546       effect->lpEnvelope = NULL;
       
   547    }
       
   548    if (effect->rgdwAxes != NULL) {
       
   549       SDL_free(effect->rgdwAxes);
       
   550       effect->rgdwAxes = NULL;
       
   551    }
       
   552    if (effect->lpvTypeSpecificParams != NULL) {
       
   553       SDL_free(effect->lpvTypeSpecificParams);
       
   554       effect->lpvTypeSpecificParams = NULL;
       
   555    }
       
   556    if (effect->rglDirection != NULL) {
       
   557       SDL_free(effect->rglDirection);
       
   558       effect->rglDirection = NULL;
       
   559    }
       
   560 }
       
   561 
       
   562 
       
   563 /*
   479  * Gets the effect type from the generic SDL haptic effect wrapper.
   564  * Gets the effect type from the generic SDL haptic effect wrapper.
   480  */
   565  */
   481 CFUUIDRef SDL_SYS_HapticEffectType(struct haptic_effect * effect)
   566 CFUUIDRef SDL_SYS_HapticEffectType(struct haptic_effect * effect)
   482 {
   567 {
   483    switch (effect->effect.type) {
   568    switch (effect->effect.type) {
   537    /* Alloc the effect. */
   622    /* Alloc the effect. */
   538    effect->hweffect = (struct haptic_hweffect *)
   623    effect->hweffect = (struct haptic_hweffect *)
   539          SDL_malloc(sizeof(struct haptic_hweffect));
   624          SDL_malloc(sizeof(struct haptic_hweffect));
   540    if (effect->hweffect == NULL) {
   625    if (effect->hweffect == NULL) {
   541       SDL_OutOfMemory();
   626       SDL_OutOfMemory();
   542       return -1;
   627       goto err_hweffect;
   543    }
   628    }
   544 
   629 
   545    /* Get the type. */
   630    /* Get the type. */
   546    type = SDL_SYS_HapticEffectType(effect);
   631    type = SDL_SYS_HapticEffectType(effect);
   547    if (type == NULL) {
   632    if (type == NULL) {
       
   633       goto err_hweffect;
       
   634    }
       
   635 
       
   636    /* Get the effect. */
       
   637    if (SDL_SYS_ToFFEFFECT(haptic, &effect->hweffect->effect, &effect->effect ) < 0) {
       
   638       goto err_effectdone;
       
   639    }
       
   640 
       
   641    /* Create the actual effect. */
       
   642    ret = FFDeviceCreateEffect( haptic->hwdata->device, type,
       
   643          &effect->hweffect->effect, &effect->hweffect->ref );
       
   644 
       
   645    if (ret != FF_OK) {
       
   646       SDL_SetError("Haptic: Unable to create effect.");
       
   647       goto err_effectdone;
       
   648    }
       
   649 
       
   650    return 0;
       
   651 
       
   652 err_effectdone:
       
   653    SDL_SYS_HapticFreeFFEFFECT(&effect->hweffect->effect);
       
   654 err_hweffect:
       
   655    if (effect->hweffect != NULL) {
   548       SDL_free(effect->hweffect);
   656       SDL_free(effect->hweffect);
   549       effect->hweffect = NULL;
   657       effect->hweffect = NULL;
   550       return -1;
   658    }
   551    }
   659    return -1;
   552 
       
   553    /* Get the effect. */
       
   554    if (SDL_SYS_ToFFEFFECT( &effect->hweffect->effect, &effect->effect ) < 0) {
       
   555       /* TODO cleanup alloced stuff. */
       
   556       return -1;
       
   557    }
       
   558 
       
   559    ret = FFDeviceCreateEffect( haptic->hwdata->device, type,
       
   560          &effect->hweffect->effect, &effect->hweffect->ref );
       
   561 }
   660 }
   562 
   661 
   563 
   662 
   564 /*
   663 /*
   565  * Updates an effect.
   664  * Updates an effect.