test/testhaptic.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 26 Apr 2014 12:29:40 -0700
changeset 8741 d5b21f813734
parent 8149 681eb46b8ac4
child 9070 8973a237f360
permissions -rw-r--r--
Fixed the inertia effect in the test program
     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 <stdlib.h>
    18 #include <string.h>             /* strstr */
    19 #include <ctype.h>              /* isdigit */
    20 
    21 #include "SDL.h"
    22 
    23 #ifndef SDL_HAPTIC_DISABLED
    24 
    25 #include "SDL_haptic.h"
    26 
    27 static SDL_Haptic *haptic;
    28 
    29 
    30 /*
    31  * prototypes
    32  */
    33 static void abort_execution(void);
    34 static void HapticPrintSupported(SDL_Haptic * haptic);
    35 
    36 
    37 /**
    38  * @brief The entry point of this force feedback demo.
    39  * @param[in] argc Number of arguments.
    40  * @param[in] argv Array of argc arguments.
    41  */
    42 int
    43 main(int argc, char **argv)
    44 {
    45     int i;
    46     char *name;
    47     int index;
    48     SDL_HapticEffect efx[5];
    49     int id[5];
    50     int nefx;
    51     unsigned int supported;
    52 
    53     /* Enable standard application logging */
    54     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
    55 
    56     name = NULL;
    57     index = -1;
    58     if (argc > 1) {
    59         name = argv[1];
    60         if ((strcmp(name, "--help") == 0) || (strcmp(name, "-h") == 0)) {
    61             SDL_Log("USAGE: %s [device]\n"
    62                    "If device is a two-digit number it'll use it as an index, otherwise\n"
    63                    "it'll use it as if it were part of the device's name.\n",
    64                    argv[0]);
    65             return 0;
    66         }
    67 
    68         i = strlen(name);
    69         if ((i < 3) && isdigit(name[0]) && ((i == 1) || isdigit(name[1]))) {
    70             index = atoi(name);
    71             name = NULL;
    72         }
    73     }
    74 
    75     /* Initialize the force feedbackness */
    76     SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK |
    77              SDL_INIT_HAPTIC);
    78     SDL_Log("%d Haptic devices detected.\n", SDL_NumHaptics());
    79     if (SDL_NumHaptics() > 0) {
    80         /* We'll just use index or the first force feedback device found */
    81         if (name == NULL) {
    82             i = (index != -1) ? index : 0;
    83         }
    84         /* Try to find matching device */
    85         else {
    86             for (i = 0; i < SDL_NumHaptics(); i++) {
    87                 if (strstr(SDL_HapticName(i), name) != NULL)
    88                     break;
    89             }
    90 
    91             if (i >= SDL_NumHaptics()) {
    92                 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to find device matching '%s', aborting.\n",
    93                        name);
    94                 return 1;
    95             }
    96         }
    97 
    98         haptic = SDL_HapticOpen(i);
    99         if (haptic == NULL) {
   100             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s\n",
   101                    SDL_GetError());
   102             return 1;
   103         }
   104         SDL_Log("Device: %s\n", SDL_HapticName(i));
   105         HapticPrintSupported(haptic);
   106     } else {
   107         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No Haptic devices found!\n");
   108         return 1;
   109     }
   110 
   111     /* We only want force feedback errors. */
   112     SDL_ClearError();
   113 
   114     /* Create effects. */
   115     memset(&efx, 0, sizeof(efx));
   116     nefx = 0;
   117     supported = SDL_HapticQuery(haptic);
   118 
   119     SDL_Log("\nUploading effects\n");
   120     /* First we'll try a SINE effect. */
   121     if (supported & SDL_HAPTIC_SINE) {
   122         SDL_Log("   effect %d: Sine Wave\n", nefx);
   123         efx[nefx].type = SDL_HAPTIC_SINE;
   124         efx[nefx].periodic.period = 1000;
   125         efx[nefx].periodic.magnitude = 0x4000;
   126         efx[nefx].periodic.length = 5000;
   127         efx[nefx].periodic.attack_length = 1000;
   128         efx[nefx].periodic.fade_length = 1000;
   129         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   130         if (id[nefx] < 0) {
   131             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   132             abort_execution();
   133         }
   134         nefx++;
   135     }
   136     /* Now we'll try a SAWTOOTHUP */
   137     if (supported & SDL_HAPTIC_SAWTOOTHUP) {
   138         SDL_Log("   effect %d: Sawtooth Up\n", nefx);
   139         efx[nefx].type = SDL_HAPTIC_SAWTOOTHUP;
   140         efx[nefx].periodic.period = 500;
   141         efx[nefx].periodic.magnitude = 0x5000;
   142         efx[nefx].periodic.length = 5000;
   143         efx[nefx].periodic.attack_length = 1000;
   144         efx[nefx].periodic.fade_length = 1000;
   145         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   146         if (id[nefx] < 0) {
   147             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   148             abort_execution();
   149         }
   150         nefx++;
   151     }
   152     /* Now the classical constant effect. */
   153     if (supported & SDL_HAPTIC_CONSTANT) {
   154         SDL_Log("   effect %d: Constant Force\n", nefx);
   155         efx[nefx].type = SDL_HAPTIC_CONSTANT;
   156         efx[nefx].constant.direction.type = SDL_HAPTIC_POLAR;
   157         efx[nefx].constant.direction.dir[0] = 20000;    /* Force comes from the south-west. */
   158         efx[nefx].constant.length = 5000;
   159         efx[nefx].constant.level = 0x6000;
   160         efx[nefx].constant.attack_length = 1000;
   161         efx[nefx].constant.fade_length = 1000;
   162         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   163         if (id[nefx] < 0) {
   164             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   165             abort_execution();
   166         }
   167         nefx++;
   168     }
   169     /* The cute spring effect. */
   170     if (supported & SDL_HAPTIC_SPRING) {
   171         SDL_Log("   effect %d: Condition Spring\n", nefx);
   172         efx[nefx].type = SDL_HAPTIC_SPRING;
   173         efx[nefx].condition.length = 5000;
   174         for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
   175             efx[nefx].condition.right_sat[i] = 0x7FFF;
   176             efx[nefx].condition.left_sat[i] = 0x7FFF;
   177             efx[nefx].condition.right_coeff[i] = 0x2000;
   178             efx[nefx].condition.left_coeff[i] = 0x2000;
   179             efx[nefx].condition.center[i] = 0x1000;     /* Displace the center for it to move. */
   180         }
   181         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   182         if (id[nefx] < 0) {
   183             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   184             abort_execution();
   185         }
   186         nefx++;
   187     }
   188     /* The pretty awesome inertia effect. */
   189     if (supported & SDL_HAPTIC_INERTIA) {
   190         SDL_Log("   effect %d: Condition Inertia\n", nefx);
   191         efx[nefx].type = SDL_HAPTIC_INERTIA;
   192         efx[nefx].condition.length = 5000;
   193         for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
   194             efx[nefx].condition.right_sat[i] = 0x7FFF;
   195             efx[nefx].condition.left_sat[i] = 0x7FFF;
   196             efx[nefx].condition.right_coeff[i] = 0x2000;
   197             efx[nefx].condition.left_coeff[i] = 0x2000;
   198         }
   199         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   200         if (id[nefx] < 0) {
   201             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   202             abort_execution();
   203         }
   204         nefx++;
   205     }
   206 
   207     /* Finally we'll try a left/right effect. */
   208     if (supported & SDL_HAPTIC_LEFTRIGHT) {
   209         SDL_Log("   effect %d: Left/Right\n", nefx);
   210         efx[nefx].type = SDL_HAPTIC_LEFTRIGHT;
   211         efx[nefx].leftright.length = 5000;
   212         efx[nefx].leftright.large_magnitude = 0x3000;
   213         efx[nefx].leftright.small_magnitude = 0xFFFF;
   214         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   215         if (id[nefx] < 0) {
   216             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   217             abort_execution();
   218         }
   219         nefx++;
   220     }
   221 
   222 
   223     SDL_Log
   224         ("\nNow playing effects for 5 seconds each with 1 second delay between\n");
   225     for (i = 0; i < nefx; i++) {
   226         SDL_Log("   Playing effect %d\n", i);
   227         SDL_HapticRunEffect(haptic, id[i], 1);
   228         SDL_Delay(6000);        /* Effects only have length 5000 */
   229     }
   230 
   231     /* Quit */
   232     if (haptic != NULL)
   233         SDL_HapticClose(haptic);
   234     SDL_Quit();
   235 
   236     return 0;
   237 }
   238 
   239 
   240 /*
   241  * Cleans up a bit.
   242  */
   243 static void
   244 abort_execution(void)
   245 {
   246     SDL_Log("\nAborting program execution.\n");
   247 
   248     SDL_HapticClose(haptic);
   249     SDL_Quit();
   250 
   251     exit(1);
   252 }
   253 
   254 
   255 /*
   256  * Displays information about the haptic device.
   257  */
   258 static void
   259 HapticPrintSupported(SDL_Haptic * haptic)
   260 {
   261     unsigned int supported;
   262 
   263     supported = SDL_HapticQuery(haptic);
   264     SDL_Log("   Supported effects [%d effects, %d playing]:\n",
   265            SDL_HapticNumEffects(haptic), SDL_HapticNumEffectsPlaying(haptic));
   266     if (supported & SDL_HAPTIC_CONSTANT)
   267         SDL_Log("      constant\n");
   268     if (supported & SDL_HAPTIC_SINE)
   269         SDL_Log("      sine\n");
   270     /* !!! FIXME: put this back when we have more bits in 2.1 */
   271     /* if (supported & SDL_HAPTIC_SQUARE)
   272         SDL_Log("      square\n"); */
   273     if (supported & SDL_HAPTIC_TRIANGLE)
   274         SDL_Log("      triangle\n");
   275     if (supported & SDL_HAPTIC_SAWTOOTHUP)
   276         SDL_Log("      sawtoothup\n");
   277     if (supported & SDL_HAPTIC_SAWTOOTHDOWN)
   278         SDL_Log("      sawtoothdown\n");
   279     if (supported & SDL_HAPTIC_RAMP)
   280         SDL_Log("      ramp\n");
   281     if (supported & SDL_HAPTIC_FRICTION)
   282         SDL_Log("      friction\n");
   283     if (supported & SDL_HAPTIC_SPRING)
   284         SDL_Log("      spring\n");
   285     if (supported & SDL_HAPTIC_DAMPER)
   286         SDL_Log("      damper\n");
   287     if (supported & SDL_HAPTIC_INERTIA)
   288         SDL_Log("      inertia\n");
   289     if (supported & SDL_HAPTIC_CUSTOM)
   290         SDL_Log("      custom\n");
   291     if (supported & SDL_HAPTIC_LEFTRIGHT)
   292         SDL_Log("      left/right\n");
   293     SDL_Log("   Supported capabilities:\n");
   294     if (supported & SDL_HAPTIC_GAIN)
   295         SDL_Log("      gain\n");
   296     if (supported & SDL_HAPTIC_AUTOCENTER)
   297         SDL_Log("      autocenter\n");
   298     if (supported & SDL_HAPTIC_STATUS)
   299         SDL_Log("      status\n");
   300 }
   301 
   302 #else
   303 
   304 int
   305 main(int argc, char *argv[])
   306 {
   307     SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Haptic support.\n");
   308     exit(1);
   309 }
   310 
   311 #endif