test/testhaptic.c
author Ryan C. Gordon <icculus@icculus.org>
Sat, 16 Aug 2014 16:50:10 -0400
changeset 9072 0c1a46c018aa
parent 9070 8973a237f360
child 9147 6bf589c8d549
permissions -rw-r--r--
Haptic: Add some missing haptic types to test, and fix wrong array-sizes.

Thanks, Elias!

Fixes Bugzilla #2686.
(along with the last several commits.)
     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[9];
    49     int id[9];
    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     
   153     /* Now the classical constant effect. */
   154     if (supported & SDL_HAPTIC_CONSTANT) {
   155         SDL_Log("   effect %d: Constant Force\n", nefx);
   156         efx[nefx].type = SDL_HAPTIC_CONSTANT;
   157         efx[nefx].constant.direction.type = SDL_HAPTIC_POLAR;
   158         efx[nefx].constant.direction.dir[0] = 20000;    /* Force comes from the south-west. */
   159         efx[nefx].constant.length = 5000;
   160         efx[nefx].constant.level = 0x6000;
   161         efx[nefx].constant.attack_length = 1000;
   162         efx[nefx].constant.fade_length = 1000;
   163         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   164         if (id[nefx] < 0) {
   165             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   166             abort_execution();
   167         }
   168         nefx++;
   169     }
   170     
   171     /* The cute spring effect. */
   172     if (supported & SDL_HAPTIC_SPRING) {
   173         SDL_Log("   effect %d: Condition Spring\n", nefx);
   174         efx[nefx].type = SDL_HAPTIC_SPRING;
   175         efx[nefx].condition.length = 5000;
   176         for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
   177             efx[nefx].condition.right_sat[i] = 0xFFFF;
   178             efx[nefx].condition.left_sat[i] = 0xFFFF;
   179             efx[nefx].condition.right_coeff[i] = 0x2000;
   180             efx[nefx].condition.left_coeff[i] = 0x2000;
   181             efx[nefx].condition.center[i] = 0x1000;     /* Displace the center for it to move. */
   182         }
   183         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   184         if (id[nefx] < 0) {
   185             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   186             abort_execution();
   187         }
   188         nefx++;
   189     }
   190     /* The interesting damper effect. */
   191     if (supported & SDL_HAPTIC_DAMPER) {
   192         SDL_Log("   effect %d: Condition Damper\n", nefx);
   193         efx[nefx].type = SDL_HAPTIC_DAMPER;
   194         efx[nefx].condition.length = 5000;
   195         for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
   196             efx[nefx].condition.right_sat[i] = 0xFFFF;
   197             efx[nefx].condition.left_sat[i] = 0xFFFF;
   198             efx[nefx].condition.right_coeff[i] = 0x2000;
   199             efx[nefx].condition.left_coeff[i] = 0x2000;
   200         }
   201         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   202         if (id[nefx] < 0) {
   203             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   204             abort_execution();
   205         }
   206         nefx++;
   207     }
   208     /* The pretty awesome inertia effect. */
   209     if (supported & SDL_HAPTIC_INERTIA) {
   210         SDL_Log("   effect %d: Condition Inertia\n", nefx);
   211         efx[nefx].type = SDL_HAPTIC_INERTIA;
   212         efx[nefx].condition.length = 5000;
   213         for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
   214             efx[nefx].condition.right_sat[i] = 0xFFFF;
   215             efx[nefx].condition.left_sat[i] = 0xFFFF;
   216             efx[nefx].condition.right_coeff[i] = 0x2000;
   217             efx[nefx].condition.left_coeff[i] = 0x2000;
   218             efx[nefx].condition.deadband[i] = 0x1000;    /* 1/16th of axis-range around the center is 'dead'. */
   219         }
   220         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   221         if (id[nefx] < 0) {
   222             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   223             abort_execution();
   224         }
   225         nefx++;
   226     }
   227     /* The hot friction effect. */
   228     if (supported & SDL_HAPTIC_FRICTION) {
   229         SDL_Log("   effect %d: Condition Friction\n", nefx);
   230         efx[nefx].type = SDL_HAPTIC_FRICTION;
   231         efx[nefx].condition.length = 5000;
   232         for (i = 0; i < SDL_HapticNumAxes(haptic); i++) {
   233             efx[nefx].condition.right_sat[i] = 0xFFFF;
   234             efx[nefx].condition.left_sat[i] = 0xFFFF;
   235             efx[nefx].condition.right_coeff[i] = 0x2000;
   236             efx[nefx].condition.left_coeff[i] = 0x2000;
   237         }
   238         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   239         if (id[nefx] < 0) {
   240             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   241             abort_execution();
   242         }
   243         nefx++;
   244     }
   245     
   246     /* Now we'll try a ramp effect */
   247     if (supported & SDL_HAPTIC_RAMP) {
   248         SDL_Log("   effect %d: Ramp\n", nefx);
   249         efx[nefx].type = SDL_HAPTIC_RAMP;
   250         efx[nefx].ramp.direction.type = SDL_HAPTIC_CARTESIAN;
   251         efx[nefx].ramp.direction.dir[0] = 1;     /* Force comes from                 */
   252         efx[nefx].ramp.direction.dir[1] = -1;    /*                  the north-east. */
   253         efx[nefx].ramp.length = 5000;
   254         efx[nefx].ramp.start = 0x4000;
   255         efx[nefx].ramp.end = -0x4000;
   256         efx[nefx].ramp.attack_length = 1000;
   257         efx[nefx].ramp.fade_length = 1000;
   258         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   259         if (id[nefx] < 0) {
   260             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   261             abort_execution();
   262         }
   263         nefx++;
   264     }
   265 
   266     /* Finally we'll try a left/right effect. */
   267     if (supported & SDL_HAPTIC_LEFTRIGHT) {
   268         SDL_Log("   effect %d: Left/Right\n", nefx);
   269         efx[nefx].type = SDL_HAPTIC_LEFTRIGHT;
   270         efx[nefx].leftright.length = 5000;
   271         efx[nefx].leftright.large_magnitude = 0x3000;
   272         efx[nefx].leftright.small_magnitude = 0xFFFF;
   273         id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
   274         if (id[nefx] < 0) {
   275             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
   276             abort_execution();
   277         }
   278         nefx++;
   279     }
   280 
   281 
   282     SDL_Log
   283         ("\nNow playing effects for 5 seconds each with 1 second delay between\n");
   284     for (i = 0; i < nefx; i++) {
   285         SDL_Log("   Playing effect %d\n", i);
   286         SDL_HapticRunEffect(haptic, id[i], 1);
   287         SDL_Delay(6000);        /* Effects only have length 5000 */
   288     }
   289 
   290     /* Quit */
   291     if (haptic != NULL)
   292         SDL_HapticClose(haptic);
   293     SDL_Quit();
   294 
   295     return 0;
   296 }
   297 
   298 
   299 /*
   300  * Cleans up a bit.
   301  */
   302 static void
   303 abort_execution(void)
   304 {
   305     SDL_Log("\nAborting program execution.\n");
   306 
   307     SDL_HapticClose(haptic);
   308     SDL_Quit();
   309 
   310     exit(1);
   311 }
   312 
   313 
   314 /*
   315  * Displays information about the haptic device.
   316  */
   317 static void
   318 HapticPrintSupported(SDL_Haptic * haptic)
   319 {
   320     unsigned int supported;
   321 
   322     supported = SDL_HapticQuery(haptic);
   323     SDL_Log("   Supported effects [%d effects, %d playing]:\n",
   324            SDL_HapticNumEffects(haptic), SDL_HapticNumEffectsPlaying(haptic));
   325     if (supported & SDL_HAPTIC_CONSTANT)
   326         SDL_Log("      constant\n");
   327     if (supported & SDL_HAPTIC_SINE)
   328         SDL_Log("      sine\n");
   329     /* !!! FIXME: put this back when we have more bits in 2.1 */
   330     /* if (supported & SDL_HAPTIC_SQUARE)
   331         SDL_Log("      square\n"); */
   332     if (supported & SDL_HAPTIC_TRIANGLE)
   333         SDL_Log("      triangle\n");
   334     if (supported & SDL_HAPTIC_SAWTOOTHUP)
   335         SDL_Log("      sawtoothup\n");
   336     if (supported & SDL_HAPTIC_SAWTOOTHDOWN)
   337         SDL_Log("      sawtoothdown\n");
   338     if (supported & SDL_HAPTIC_RAMP)
   339         SDL_Log("      ramp\n");
   340     if (supported & SDL_HAPTIC_FRICTION)
   341         SDL_Log("      friction\n");
   342     if (supported & SDL_HAPTIC_SPRING)
   343         SDL_Log("      spring\n");
   344     if (supported & SDL_HAPTIC_DAMPER)
   345         SDL_Log("      damper\n");
   346     if (supported & SDL_HAPTIC_INERTIA)
   347         SDL_Log("      inertia\n");
   348     if (supported & SDL_HAPTIC_CUSTOM)
   349         SDL_Log("      custom\n");
   350     if (supported & SDL_HAPTIC_LEFTRIGHT)
   351         SDL_Log("      left/right\n");
   352     SDL_Log("   Supported capabilities:\n");
   353     if (supported & SDL_HAPTIC_GAIN)
   354         SDL_Log("      gain\n");
   355     if (supported & SDL_HAPTIC_AUTOCENTER)
   356         SDL_Log("      autocenter\n");
   357     if (supported & SDL_HAPTIC_STATUS)
   358         SDL_Log("      status\n");
   359 }
   360 
   361 #else
   362 
   363 int
   364 main(int argc, char *argv[])
   365 {
   366     SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL compiled without Haptic support.\n");
   367     exit(1);
   368 }
   369 
   370 #endif