test/testhaptic.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 25 Aug 2008 09:55:03 +0000
changeset 2713 0906692aa6a4
child 2748 5668c3dfe7bc
permissions -rw-r--r--
Final merge of Google Summer of Code 2008 work...

Force Feedback for SDL
by Edgar Simo, mentored by Ryan C. Gordon
     1 /*
     2 Copyright (c) 2008, Edgar Simo Serra
     3 All rights reserved.
     4 
     5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
     6 
     7     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
     8     * 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.
     9     * Neither the name of the Simple Directmedia Layer (SDL) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
    10 
    11 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.
    12 */
    13 
    14 /*
    15  * includes
    16  */
    17 #include "SDL.h"
    18 #include "SDL_haptic.h"
    19 
    20 #include <stdio.h>              /* printf */
    21 #include <string.h>             /* strstr */
    22 
    23 
    24 
    25 static SDL_Haptic *haptic;
    26 
    27 
    28 /*
    29  * prototypes
    30  */
    31 static void abort_execution(void);
    32 static void HapticPrintSupported(SDL_Haptic * haptic);
    33 
    34 
    35 /**
    36  * @brief The entry point of this force feedback demo.
    37  * @param[in] argc Number of arguments.
    38  * @param[in] argv Array of argc arguments.
    39  */
    40 int
    41 main(int argc, char **argv)
    42 {
    43     int i;
    44     char *name;
    45     SDL_HapticEffect efx[5];
    46     int id[5];
    47     int nefx;
    48     unsigned int supported;
    49 
    50     name = NULL;
    51     if (argc > 1) {
    52         name = argv[1];
    53         if ((strcmp(name, "--help") == 0) || (strcmp(name, "-h") == 0)) {
    54             printf("USAGE: %s [device name]\n"
    55                    "If device name is specified, it will try to find a device whose name\n"
    56                    "contains device name for testing.\n", argv[0]);
    57             return 0;
    58         }
    59     }
    60 
    61     /* Initialize the force feedbackness */
    62     SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK |
    63              SDL_INIT_HAPTIC);
    64     printf("%d Haptic devices detected.\n", SDL_NumHaptics());
    65     if (SDL_NumHaptics() > 0) {
    66         /* We'll just use the first force feedback device found */
    67         if (name == NULL) {
    68             i = 0;
    69         }
    70         /* Try to find matching device */
    71         else {
    72             for (i = 0; i < SDL_NumHaptics(); i++) {
    73                 if (strstr(SDL_HapticName(i), name) != NULL)
    74                     break;
    75             }
    76 
    77             if (i >= SDL_NumHaptics()) {
    78                 printf("Unable to find device matching '%s', aborting.\n",
    79                        name);
    80                 return 1;
    81             }
    82         }
    83 
    84         haptic = SDL_HapticOpen(i);
    85         if (haptic == NULL) {
    86             perror("Unable to create the haptic device");
    87             return 1;
    88         }
    89         printf("Device: %s\n", SDL_HapticName(i));
    90         HapticPrintSupported(haptic);
    91     } else {
    92         printf("No Haptic devices found!\n");
    93         return 1;
    94     }
    95 
    96     /* We only want force feedback errors. */
    97     SDL_ClearError();
    98 
    99     /* Create effects. */
   100     memset(&efx, 0, sizeof(efx));
   101     nefx = 0;
   102     supported = SDL_HapticQuery(haptic);
   103 
   104     printf("\nUploading effects\n");
   105     /* First we'll try a SINE effect. */
   106     if (supported & SDL_HAPTIC_SINE) {
   107         printf("   effect %d: Sine Wave\n", nefx);
   108         efx[nefx].type = SDL_HAPTIC_SINE;
   109         efx[nefx].periodic.period = 1000;
   110         efx[nefx].periodic.magnitude = 0x4000;
   111         efx[nefx].periodic.length = 5000;
   112         efx[nefx].periodic.attack_length = 1000;
   113         efx[nefx].periodic.fade_length = 1000;
   114         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   115         if (id[nefx] < 0) {
   116             printf("UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   117             abort_execution();
   118         }
   119         nefx++;
   120     }
   121     /* Now we'll try a SAWTOOTHUP */
   122     if (supported & SDL_HAPTIC_SAWTOOTHUP) {
   123         printf("   effect %d: Sawtooth Up\n", nefx);
   124         efx[nefx].type = SDL_HAPTIC_SQUARE;
   125         efx[nefx].periodic.period = 500;
   126         efx[nefx].periodic.magnitude = 0x5000;
   127         efx[nefx].periodic.length = 5000;
   128         efx[nefx].periodic.attack_length = 1000;
   129         efx[nefx].periodic.fade_length = 1000;
   130         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   131         if (id[nefx] < 0) {
   132             printf("UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   133             abort_execution();
   134         }
   135         nefx++;
   136     }
   137     /* Now the classical constant effect. */
   138     if (supported & SDL_HAPTIC_CONSTANT) {
   139         printf("   effect %d: Constant Force\n", nefx);
   140         efx[nefx].type = SDL_HAPTIC_CONSTANT;
   141         efx[nefx].constant.direction.type = SDL_HAPTIC_POLAR;
   142         efx[nefx].constant.direction.dir[0] = 20000;    /* Force comes from the south-west. */
   143         efx[nefx].constant.length = 5000;
   144         efx[nefx].constant.level = 0x6000;
   145         efx[nefx].constant.attack_length = 1000;
   146         efx[nefx].constant.fade_length = 1000;
   147         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   148         if (id[nefx] < 0) {
   149             printf("UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   150             abort_execution();
   151         }
   152         nefx++;
   153     }
   154     /* The cute spring effect. */
   155     if (supported & SDL_HAPTIC_SPRING) {
   156         printf("   effect %d: Condition Spring\n", nefx);
   157         efx[nefx].type = SDL_HAPTIC_SPRING;
   158         efx[nefx].condition.length = 5000;
   159         for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
   160             efx[nefx].condition.right_sat[i] = 0x7FFF;
   161             efx[nefx].condition.left_sat[i] = 0x7FFF;
   162             efx[nefx].condition.right_coeff[i] = 0x2000;
   163             efx[nefx].condition.left_coeff[i] = 0x2000;
   164             efx[nefx].condition.center[i] = 0x1000;     /* Displace the center for it to move. */
   165         }
   166         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   167         if (id[nefx] < 0) {
   168             printf("UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   169             abort_execution();
   170         }
   171         nefx++;
   172     }
   173     /* The pretty awesome inertia effect. */
   174     if (supported & SDL_HAPTIC_INERTIA) {
   175         printf("   effect %d: Condition Inertia\n", nefx);
   176         efx[nefx].type = SDL_HAPTIC_SPRING;
   177         efx[nefx].condition.length = 5000;
   178         for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
   179             efx[nefx].condition.right_sat[i] = 0x7FFF;
   180             efx[nefx].condition.left_sat[i] = 0x7FFF;
   181             efx[nefx].condition.right_coeff[i] = 0x2000;
   182             efx[nefx].condition.left_coeff[i] = 0x2000;
   183         }
   184         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   185         if (id[nefx] < 0) {
   186             printf("UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   187             abort_execution();
   188         }
   189         nefx++;
   190     }
   191 
   192     printf
   193         ("\nNow playing effects for 5 seconds each with 1 second delay between\n");
   194     for (i = 0; i < nefx; i++) {
   195         printf("   Playing effect %d\n", i);
   196         SDL_HapticRunEffect(haptic, id[i], 1);
   197         SDL_Delay(6000);        /* Effects only have length 5000 */
   198     }
   199 
   200     /* Quit */
   201     if (haptic != NULL)
   202         SDL_HapticClose(haptic);
   203     SDL_Quit();
   204 
   205     return 0;
   206 }
   207 
   208 
   209 /*
   210  * Cleans up a bit.
   211  */
   212 static void
   213 abort_execution(void)
   214 {
   215     printf("\nAborting program execution.\n");
   216 
   217     SDL_HapticClose(haptic);
   218     SDL_Quit();
   219 
   220     exit(1);
   221 }
   222 
   223 
   224 /*
   225  * Displays information about the haptic device.
   226  */
   227 static void
   228 HapticPrintSupported(SDL_Haptic * haptic)
   229 {
   230     unsigned int supported;
   231 
   232     supported = SDL_HapticQuery(haptic);
   233     printf("   Supported effects [%d effects, %d playing]:\n",
   234            SDL_HapticNumEffects(haptic), SDL_HapticNumEffectsPlaying(haptic));
   235     if (supported & SDL_HAPTIC_CONSTANT)
   236         printf("      constant\n");
   237     if (supported & SDL_HAPTIC_SINE)
   238         printf("      sine\n");
   239     if (supported & SDL_HAPTIC_SQUARE)
   240         printf("      square\n");
   241     if (supported & SDL_HAPTIC_TRIANGLE)
   242         printf("      triangle\n");
   243     if (supported & SDL_HAPTIC_SAWTOOTHUP)
   244         printf("      sawtoothup\n");
   245     if (supported & SDL_HAPTIC_SAWTOOTHDOWN)
   246         printf("      sawtoothdown\n");
   247     if (supported & SDL_HAPTIC_RAMP)
   248         printf("      ramp\n");
   249     if (supported & SDL_HAPTIC_FRICTION)
   250         printf("      friction\n");
   251     if (supported & SDL_HAPTIC_SPRING)
   252         printf("      spring\n");
   253     if (supported & SDL_HAPTIC_DAMPER)
   254         printf("      damper\n");
   255     if (supported & SDL_HAPTIC_INERTIA)
   256         printf("      intertia\n");
   257     if (supported & SDL_HAPTIC_CUSTOM)
   258         printf("      custom\n");
   259     printf("   Supported capabilities:\n");
   260     if (supported & SDL_HAPTIC_GAIN)
   261         printf("      gain\n");
   262     if (supported & SDL_HAPTIC_AUTOCENTER)
   263         printf("      autocenter\n");
   264     if (supported & SDL_HAPTIC_STATUS)
   265         printf("      status\n");
   266 }