src/joystick/iphoneos/SDL_sysjoystick.m
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Wed, 15 Apr 2015 21:29:55 +0200
changeset 9561 d8ad01792399
parent 9536 3c87b8f9dc58
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Fixed typo in internal joystick documentation comments.
slouken@2765
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@2765
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@2765
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@2765
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@2765
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@2765
    22
philipp@8138
    23
/* This is the iOS implementation of the SDL joystick API */
slouken@2765
    24
slouken@2765
    25
#include "SDL_joystick.h"
slime73@9489
    26
#include "SDL_hints.h"
slouken@8921
    27
#include "SDL_stdinc.h"
slouken@2765
    28
#include "../SDL_sysjoystick.h"
slouken@2765
    29
#include "../SDL_joystick_c.h"
slouken@2765
    30
slouken@8921
    31
#import <CoreMotion/CoreMotion.h>
slouken@8921
    32
slouken@8921
    33
/* needed for SDL_IPHONE_MAX_GFORCE macro */
slouken@8921
    34
#import "SDL_config_iphoneos.h"
slouken@8921
    35
slime73@9489
    36
const char *accelerometerName = "iOS Accelerometer";
slouken@8921
    37
slouken@8921
    38
static CMMotionManager *motionManager = nil;
slime73@9489
    39
static int numjoysticks = 0;
slouken@2765
    40
slouken@2765
    41
/* Function to scan the system for joysticks.
philipp@9311
    42
 * Joystick 0 should be the system default joystick.
slouken@2765
    43
 * It should return 0, or -1 on an unrecoverable fatal error.
slouken@2765
    44
 */
slouken@2765
    45
int
slouken@2765
    46
SDL_SYS_JoystickInit(void)
slouken@2765
    47
{
slime73@9489
    48
    const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
slime73@9489
    49
    if (!hint || SDL_atoi(hint)) {
slime73@9489
    50
        /* Default behavior, accelerometer as joystick */
slime73@9490
    51
        numjoysticks = 1;
slime73@9489
    52
    }
slime73@9489
    53
slime73@9489
    54
    return numjoysticks;
slouken@2765
    55
}
slouken@2765
    56
slouken@6707
    57
int SDL_SYS_NumJoysticks()
slouken@6707
    58
{
slime73@9489
    59
    return numjoysticks;
slouken@6707
    60
}
slouken@6707
    61
slouken@6707
    62
void SDL_SYS_JoystickDetect()
slouken@6707
    63
{
slouken@6707
    64
}
slouken@6707
    65
slouken@2765
    66
/* Function to get the device-dependent name of a joystick */
slouken@2765
    67
const char *
slouken@6707
    68
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
slouken@2765
    69
{
slouken@6707
    70
    return accelerometerName;
slouken@6707
    71
}
slouken@6707
    72
slouken@6707
    73
/* Function to perform the mapping from device index to the instance id for this index */
slouken@6707
    74
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
slouken@6707
    75
{
slouken@6707
    76
    return device_index;
slouken@2765
    77
}
slouken@2765
    78
slouken@2765
    79
/* Function to open a joystick for use.
philipp@9380
    80
   The joystick to open is specified by the device index.
slouken@2765
    81
   This should fill the nbuttons and naxes fields of the joystick structure.
slouken@2765
    82
   It returns 0, or -1 if there is an error.
slouken@2765
    83
 */
slouken@2765
    84
int
slouken@6693
    85
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
slouken@2765
    86
{
slouken@6707
    87
    joystick->naxes = 3;
slouken@6707
    88
    joystick->nhats = 0;
slouken@6707
    89
    joystick->nballs = 0;
slouken@6707
    90
    joystick->nbuttons = 0;
slouken@8921
    91
slime73@9506
    92
    @autoreleasepool {
slime73@9506
    93
        if (motionManager == nil) {
slime73@9506
    94
            motionManager = [[CMMotionManager alloc] init];
slime73@9506
    95
        }
slime73@9506
    96
slime73@9506
    97
        /* Shorter times between updates can significantly increase CPU usage. */
slime73@9506
    98
        motionManager.accelerometerUpdateInterval = 0.1;
slime73@9506
    99
        [motionManager startAccelerometerUpdates];
slouken@8921
   100
    }
slouken@8921
   101
slouken@6707
   102
    return 0;
slouken@6707
   103
}
slouken@6707
   104
philipp@9561
   105
/* Function to determine if this joystick is attached to the system right now */
slouken@6707
   106
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
slouken@6707
   107
{
slouken@6707
   108
    return SDL_TRUE;
slouken@2765
   109
}
slouken@2765
   110
slouken@8921
   111
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
slouken@8921
   112
{
slouken@8921
   113
    const float maxgforce = SDL_IPHONE_MAX_GFORCE;
slouken@8921
   114
    const SInt16 maxsint16 = 0x7FFF;
slouken@8921
   115
    CMAcceleration accel;
slouken@8921
   116
slime73@9506
   117
    @autoreleasepool {
slime73@9506
   118
        if (!motionManager.accelerometerActive) {
slime73@9506
   119
            return;
slime73@9506
   120
        }
slime73@9506
   121
slime73@9506
   122
        accel = motionManager.accelerometerData.acceleration;
slouken@8921
   123
    }
slouken@8921
   124
slouken@8921
   125
    /*
slouken@8921
   126
     Convert accelerometer data from floating point to Sint16, which is what
slouken@8921
   127
     the joystick system expects.
slouken@8921
   128
slouken@8921
   129
     To do the conversion, the data is first clamped onto the interval
slouken@8921
   130
     [-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
slouken@8921
   131
     by MAX_SINT16 so that it is mapped to the full range of an Sint16.
slouken@8921
   132
slouken@8921
   133
     You can customize the clamped range of this function by modifying the
slouken@8921
   134
     SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
slouken@8921
   135
slouken@8921
   136
     Once converted to Sint16, the accelerometer data no longer has coherent
slouken@8921
   137
     units. You can convert the data back to units of g-force by multiplying
slouken@8921
   138
     it in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
slouken@8921
   139
     */
slouken@8921
   140
slouken@8921
   141
    /* clamp the data */
slouken@8921
   142
    accel.x = SDL_min(SDL_max(accel.x, -maxgforce), maxgforce);
slouken@8921
   143
    accel.y = SDL_min(SDL_max(accel.y, -maxgforce), maxgforce);
slouken@8921
   144
    accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
slouken@8921
   145
slouken@8921
   146
    /* pass in data mapped to range of SInt16 */
slouken@8921
   147
    SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
slouken@8921
   148
    SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
slouken@8921
   149
    SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
slouken@8921
   150
}
slouken@8921
   151
slouken@2765
   152
/* Function to update the state of a joystick - called as a device poll.
slouken@2765
   153
 * This function shouldn't update the joystick structure directly,
slouken@2765
   154
 * but instead should call SDL_PrivateJoystick*() to deliver events
slouken@2765
   155
 * and update joystick device state.
slouken@2765
   156
 */
slouken@2765
   157
void
slouken@2765
   158
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
slouken@2765
   159
{
slouken@8921
   160
    SDL_SYS_AccelerometerUpdate(joystick);
slouken@2765
   161
}
slouken@2765
   162
slouken@2765
   163
/* Function to close a joystick after use */
slouken@2765
   164
void
slouken@2765
   165
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
slouken@2765
   166
{
slime73@9506
   167
    @autoreleasepool {
slime73@9506
   168
        [motionManager stopAccelerometerUpdates];
slime73@9506
   169
    }
slouken@2765
   170
}
slouken@2765
   171
slouken@2765
   172
/* Function to perform any system-specific joystick related cleanup */
slouken@2765
   173
void
slouken@2765
   174
SDL_SYS_JoystickQuit(void)
slouken@2765
   175
{
slime73@9506
   176
    @autoreleasepool {
slouken@8921
   177
        motionManager = nil;
slouken@8921
   178
    }
slime73@9489
   179
slime73@9489
   180
    numjoysticks = 0;
slouken@2765
   181
}
slouken@6693
   182
slouken@6744
   183
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
slouken@6693
   184
{
slouken@6744
   185
    SDL_JoystickGUID guid;
slouken@7191
   186
    /* the GUID is just the first 16 chars of the name for now */
slouken@6707
   187
    const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
slouken@6693
   188
    SDL_zero( guid );
slouken@6693
   189
    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
slouken@6693
   190
    return guid;
slouken@6693
   191
}
slouken@6693
   192
slouken@6744
   193
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
slouken@6693
   194
{
slouken@6744
   195
    SDL_JoystickGUID guid;
slouken@7191
   196
    /* the GUID is just the first 16 chars of the name for now */
slouken@6693
   197
    const char *name = joystick->name;
slouken@6693
   198
    SDL_zero( guid );
slouken@6693
   199
    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
slouken@6693
   200
    return guid;
slouken@6693
   201
}
slouken@6693
   202
slouken@2765
   203
/* vi: set ts=4 sw=4 expandtab: */