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