src/joystick/iphoneos/SDL_sysjoystick.m
author Alex Szpakowski <slime73@gmail.com>
Wed, 06 Aug 2014 03:24:16 -0300
branchiOS-improvements
changeset 9510 e19faa3b5d88
parent 9506 18e3f94bd860
child 9535 a66a7f7e8cd8
permissions -rw-r--r--
Updated the iOS backend code to use Objective-C's automatic reference counting (ARC).
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.
slouken@2765
    42
 * This function should set SDL_numjoysticks to the number of available
slouken@2765
    43
 * joysticks.  Joystick 0 should be the system default joystick.
slouken@2765
    44
 * It should return 0, or -1 on an unrecoverable fatal error.
slouken@2765
    45
 */
slouken@2765
    46
int
slouken@2765
    47
SDL_SYS_JoystickInit(void)
slouken@2765
    48
{
slime73@9489
    49
    const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
slime73@9489
    50
    if (!hint || SDL_atoi(hint)) {
slime73@9489
    51
        /* Default behavior, accelerometer as joystick */
slime73@9490
    52
        numjoysticks = 1;
slime73@9489
    53
    }
slime73@9489
    54
slime73@9489
    55
    return numjoysticks;
slouken@2765
    56
}
slouken@2765
    57
slouken@6707
    58
int SDL_SYS_NumJoysticks()
slouken@6707
    59
{
slime73@9489
    60
    return numjoysticks;
slouken@6707
    61
}
slouken@6707
    62
slouken@6707
    63
void SDL_SYS_JoystickDetect()
slouken@6707
    64
{
slouken@6707
    65
}
slouken@6707
    66
slouken@2765
    67
/* Function to get the device-dependent name of a joystick */
slouken@2765
    68
const char *
slouken@6707
    69
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
slouken@2765
    70
{
slouken@6707
    71
    return accelerometerName;
slouken@6707
    72
}
slouken@6707
    73
slouken@6707
    74
/* Function to perform the mapping from device index to the instance id for this index */
slouken@6707
    75
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
slouken@6707
    76
{
slouken@6707
    77
    return device_index;
slouken@2765
    78
}
slouken@2765
    79
slouken@2765
    80
/* Function to open a joystick for use.
slouken@2765
    81
   The joystick to open is specified by the index field of the joystick.
slouken@2765
    82
   This should fill the nbuttons and naxes fields of the joystick structure.
slouken@2765
    83
   It returns 0, or -1 if there is an error.
slouken@2765
    84
 */
slouken@2765
    85
int
slouken@6693
    86
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
slouken@2765
    87
{
slouken@6707
    88
    joystick->naxes = 3;
slouken@6707
    89
    joystick->nhats = 0;
slouken@6707
    90
    joystick->nballs = 0;
slouken@6707
    91
    joystick->nbuttons = 0;
slouken@8921
    92
slime73@9506
    93
    @autoreleasepool {
slime73@9506
    94
        if (motionManager == nil) {
slime73@9506
    95
            motionManager = [[CMMotionManager alloc] init];
slime73@9506
    96
        }
slime73@9506
    97
slime73@9506
    98
        /* Shorter times between updates can significantly increase CPU usage. */
slime73@9506
    99
        motionManager.accelerometerUpdateInterval = 0.1;
slime73@9506
   100
        [motionManager startAccelerometerUpdates];
slouken@8921
   101
    }
slouken@8921
   102
slouken@6707
   103
    return 0;
slouken@6707
   104
}
slouken@6707
   105
slouken@6707
   106
/* Function to determine is this joystick is attached to the system right now */
slouken@6707
   107
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
slouken@6707
   108
{
slouken@6707
   109
    return SDL_TRUE;
slouken@2765
   110
}
slouken@2765
   111
slouken@8921
   112
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
slouken@8921
   113
{
slouken@8921
   114
    const float maxgforce = SDL_IPHONE_MAX_GFORCE;
slouken@8921
   115
    const SInt16 maxsint16 = 0x7FFF;
slouken@8921
   116
    CMAcceleration accel;
slouken@8921
   117
slime73@9506
   118
    @autoreleasepool {
slime73@9506
   119
        if (!motionManager.accelerometerActive) {
slime73@9506
   120
            return;
slime73@9506
   121
        }
slime73@9506
   122
slime73@9506
   123
        accel = motionManager.accelerometerData.acceleration;
slouken@8921
   124
    }
slouken@8921
   125
slouken@8921
   126
    /*
slouken@8921
   127
     Convert accelerometer data from floating point to Sint16, which is what
slouken@8921
   128
     the joystick system expects.
slouken@8921
   129
slouken@8921
   130
     To do the conversion, the data is first clamped onto the interval
slouken@8921
   131
     [-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
slouken@8921
   132
     by MAX_SINT16 so that it is mapped to the full range of an Sint16.
slouken@8921
   133
slouken@8921
   134
     You can customize the clamped range of this function by modifying the
slouken@8921
   135
     SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
slouken@8921
   136
slouken@8921
   137
     Once converted to Sint16, the accelerometer data no longer has coherent
slouken@8921
   138
     units. You can convert the data back to units of g-force by multiplying
slouken@8921
   139
     it in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
slouken@8921
   140
     */
slouken@8921
   141
slouken@8921
   142
    /* clamp the data */
slouken@8921
   143
    accel.x = SDL_min(SDL_max(accel.x, -maxgforce), maxgforce);
slouken@8921
   144
    accel.y = SDL_min(SDL_max(accel.y, -maxgforce), maxgforce);
slouken@8921
   145
    accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
slouken@8921
   146
slouken@8921
   147
    /* pass in data mapped to range of SInt16 */
slouken@8921
   148
    SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
slouken@8921
   149
    SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
slouken@8921
   150
    SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
slouken@8921
   151
}
slouken@8921
   152
slouken@2765
   153
/* Function to update the state of a joystick - called as a device poll.
slouken@2765
   154
 * This function shouldn't update the joystick structure directly,
slouken@2765
   155
 * but instead should call SDL_PrivateJoystick*() to deliver events
slouken@2765
   156
 * and update joystick device state.
slouken@2765
   157
 */
slouken@2765
   158
void
slouken@2765
   159
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
slouken@2765
   160
{
slouken@8921
   161
    SDL_SYS_AccelerometerUpdate(joystick);
slouken@2765
   162
}
slouken@2765
   163
slouken@2765
   164
/* Function to close a joystick after use */
slouken@2765
   165
void
slouken@2765
   166
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
slouken@2765
   167
{
slime73@9506
   168
    @autoreleasepool {
slime73@9506
   169
        [motionManager stopAccelerometerUpdates];
slime73@9506
   170
    }
slouken@8921
   171
    joystick->closed = 1;
slouken@2765
   172
}
slouken@2765
   173
slouken@2765
   174
/* Function to perform any system-specific joystick related cleanup */
slouken@2765
   175
void
slouken@2765
   176
SDL_SYS_JoystickQuit(void)
slouken@2765
   177
{
slime73@9506
   178
    @autoreleasepool {
slime73@9510
   179
        motionManager = nil;
slouken@8921
   180
    }
slime73@9489
   181
slime73@9489
   182
    numjoysticks = 0;
slouken@2765
   183
}
slouken@6693
   184
slouken@6744
   185
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
slouken@6693
   186
{
slouken@6744
   187
    SDL_JoystickGUID guid;
slouken@7191
   188
    /* the GUID is just the first 16 chars of the name for now */
slouken@6707
   189
    const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
slouken@6693
   190
    SDL_zero( guid );
slouken@6693
   191
    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
slouken@6693
   192
    return guid;
slouken@6693
   193
}
slouken@6693
   194
slouken@6744
   195
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
slouken@6693
   196
{
slouken@6744
   197
    SDL_JoystickGUID guid;
slouken@7191
   198
    /* the GUID is just the first 16 chars of the name for now */
slouken@6693
   199
    const char *name = joystick->name;
slouken@6693
   200
    SDL_zero( guid );
slouken@6693
   201
    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
slouken@6693
   202
    return guid;
slouken@6693
   203
}
slouken@6693
   204
slouken@2765
   205
/* vi: set ts=4 sw=4 expandtab: */