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