src/joystick/android/SDL_sysjoystick.c
changeset 8057 801d84e26f91
parent 8025 a867f1891d2a
child 8060 d1948d163145
     1.1 --- a/src/joystick/android/SDL_sysjoystick.c	Mon Dec 09 15:17:20 2013 -0500
     1.2 +++ b/src/joystick/android/SDL_sysjoystick.c	Tue Dec 10 16:24:11 2013 -0300
     1.3 @@ -23,15 +23,18 @@
     1.4  
     1.5  #ifdef SDL_JOYSTICK_ANDROID
     1.6  
     1.7 -/* This is the system specific header for the SDL joystick API */
     1.8  #include <stdio.h>              /* For the definition of NULL */
     1.9 -
    1.10  #include "SDL_error.h"
    1.11  #include "SDL_events.h"
    1.12 +
    1.13 +#if !SDL_EVENTS_DISABLED
    1.14 +#include "../../events/SDL_events_c.h"
    1.15 +#endif
    1.16 +
    1.17  #include "SDL_joystick.h"
    1.18  #include "SDL_hints.h"
    1.19  #include "SDL_assert.h"
    1.20 -#include "../SDL_sysjoystick.h"
    1.21 +#include "SDL_sysjoystick_c.h"
    1.22  #include "../SDL_joystick_c.h"
    1.23  #include "../../core/android/SDL_android.h"
    1.24  
    1.25 @@ -57,14 +60,17 @@
    1.26  #define AKEYCODE_BUTTON_16 203
    1.27  #endif
    1.28  
    1.29 -#define ANDROID_ACCELEROMETER_INDEX (SYS_numjoysticks - 1)
    1.30  #define ANDROID_ACCELEROMETER_NAME "Android Accelerometer"
    1.31 +#define ANDROID_ACCELEROMETER_DEVICE_ID INT_MIN
    1.32  #define ANDROID_MAX_NBUTTONS 36
    1.33  
    1.34 -static SDL_Joystick **SYS_Joysticks;
    1.35 -static char **SYS_JoystickNames;
    1.36 -static int SYS_numjoysticks;
    1.37 -static SDL_bool SYS_accelAsJoy;
    1.38 +static SDL_joylist_item * JoystickByDeviceId(int device_id);
    1.39 +
    1.40 +static SDL_joylist_item *SDL_joylist = NULL;
    1.41 +static SDL_joylist_item *SDL_joylist_tail = NULL;
    1.42 +static int numjoysticks = 0;
    1.43 +static int instance_counter = 0;
    1.44 +
    1.45  
    1.46  /* Function to convert Android keyCodes into SDL ones.
    1.47   * This code manipulation is done to get a sequential list of codes.
    1.48 @@ -139,78 +145,265 @@
    1.49      
    1.50  }
    1.51  
    1.52 -/* Function to scan the system for joysticks.
    1.53 - * This function should set SDL_numjoysticks to the number of available
    1.54 - * joysticks.  Joystick 0 should be the system default joystick.
    1.55 - * It should return 0, or -1 on an unrecoverable fatal error.
    1.56 - */
    1.57 +int
    1.58 +Android_OnPadDown(int device_id, int keycode)
    1.59 +{
    1.60 +    SDL_joylist_item *item;
    1.61 +    int button = keycode_to_SDL(keycode);
    1.62 +    if (button >= 0) {
    1.63 +        item = JoystickByDeviceId(device_id);
    1.64 +        if (item && item->joystick) {
    1.65 +            SDL_PrivateJoystickButton(item->joystick, button , SDL_PRESSED);
    1.66 +        }
    1.67 +        return 0;
    1.68 +    }
    1.69 +    
    1.70 +    return -1;
    1.71 +}
    1.72 +
    1.73 +int
    1.74 +Android_OnPadUp(int device_id, int keycode)
    1.75 +{
    1.76 +    SDL_joylist_item *item;
    1.77 +    int button = keycode_to_SDL(keycode);
    1.78 +    if (button >= 0) {
    1.79 +        item = JoystickByDeviceId(device_id);
    1.80 +        if (item && item->joystick) {
    1.81 +            SDL_PrivateJoystickButton(item->joystick, button, SDL_RELEASED);
    1.82 +        }
    1.83 +        return 0;
    1.84 +    }
    1.85 +    
    1.86 +    return -1;
    1.87 +}
    1.88 +
    1.89 +int
    1.90 +Android_OnJoy(int device_id, int axis, float value)
    1.91 +{
    1.92 +    /* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
    1.93 +    SDL_joylist_item *item = JoystickByDeviceId(device_id);
    1.94 +    if (item && item->joystick) {
    1.95 +        SDL_PrivateJoystickAxis(item->joystick, axis, (Sint16) (32767.*value) );
    1.96 +    }
    1.97 +    
    1.98 +    return 0;
    1.99 +}
   1.100 +
   1.101 +
   1.102 +int
   1.103 +Android_AddJoystick(int device_id, const char *name, SDL_bool is_accelerometer, int nbuttons, int naxes, int nhats, int nballs)
   1.104 +{
   1.105 +    SDL_JoystickGUID guid;
   1.106 +    SDL_joylist_item *item;
   1.107 +#if !SDL_EVENTS_DISABLED
   1.108 +    SDL_Event event;
   1.109 +#endif
   1.110 +    
   1.111 +    if(JoystickByDeviceId(device_id) != NULL || name == NULL) {
   1.112 +        return -1;
   1.113 +    }
   1.114 +    
   1.115 +    /* the GUID is just the first 16 chars of the name for now */
   1.116 +    SDL_zero( guid );
   1.117 +    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
   1.118 +
   1.119 +    item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
   1.120 +    if (item == NULL) {
   1.121 +        return -1;
   1.122 +    }
   1.123 +
   1.124 +    SDL_zerop(item);
   1.125 +    item->guid = guid;
   1.126 +    item->device_id = device_id;
   1.127 +    item->name = SDL_strdup(name);
   1.128 +    if ( item->name == NULL ) {
   1.129 +         SDL_free(item);
   1.130 +         return -1;
   1.131 +    }
   1.132 +    
   1.133 +    item->is_accelerometer = is_accelerometer;
   1.134 +    if (nbuttons > -1) {
   1.135 +        item->nbuttons = nbuttons;
   1.136 +    }
   1.137 +    else {
   1.138 +        item->nbuttons = ANDROID_MAX_NBUTTONS;
   1.139 +    }
   1.140 +    item->naxes = naxes;
   1.141 +    item->nhats = nhats;
   1.142 +    item->nballs = nballs;
   1.143 +    item->device_instance = instance_counter++;
   1.144 +    if (SDL_joylist_tail == NULL) {
   1.145 +        SDL_joylist = SDL_joylist_tail = item;
   1.146 +    } else {
   1.147 +        SDL_joylist_tail->next = item;
   1.148 +        SDL_joylist_tail = item;
   1.149 +    }
   1.150 +
   1.151 +    /* Need to increment the joystick count before we post the event */
   1.152 +    ++numjoysticks;
   1.153 +
   1.154 +#if !SDL_EVENTS_DISABLED
   1.155 +    event.type = SDL_JOYDEVICEADDED;
   1.156 +
   1.157 +    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   1.158 +        event.jdevice.which = (numjoysticks - 1);
   1.159 +        if ( (SDL_EventOK == NULL) ||
   1.160 +             (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
   1.161 +            SDL_PushEvent(&event);
   1.162 +        }
   1.163 +    }
   1.164 +#endif /* !SDL_EVENTS_DISABLED */
   1.165 +
   1.166 +    SDL_Log("Added joystick %s with device_id %d", name, device_id);
   1.167 +
   1.168 +    return numjoysticks;
   1.169 +}
   1.170 +
   1.171 +int 
   1.172 +Android_RemoveJoystick(int device_id)
   1.173 +{
   1.174 +    SDL_joylist_item *item = SDL_joylist;
   1.175 +    SDL_joylist_item *prev = NULL;
   1.176 +#if !SDL_EVENTS_DISABLED
   1.177 +    SDL_Event event;
   1.178 +#endif
   1.179 +    
   1.180 +    /* Don't call JoystickByDeviceId here or there'll be an infinite loop! */
   1.181 +    while (item != NULL) {
   1.182 +        if (item->device_id == device_id) {
   1.183 +            break;
   1.184 +        }
   1.185 +        prev = item;
   1.186 +        item = item->next;
   1.187 +    }
   1.188 +    
   1.189 +    if (item == NULL) {
   1.190 +        return -1;
   1.191 +    }
   1.192 +
   1.193 +    const int retval = item->device_instance;
   1.194 +    if (prev != NULL) {
   1.195 +        prev->next = item->next;
   1.196 +    } else {
   1.197 +        SDL_assert(SDL_joylist == item);
   1.198 +        SDL_joylist = item->next;
   1.199 +    }
   1.200 +    if (item == SDL_joylist_tail) {
   1.201 +        SDL_joylist_tail = prev;
   1.202 +    }
   1.203 +
   1.204 +    /* Need to decrement the joystick count before we post the event */
   1.205 +    --numjoysticks;
   1.206 +
   1.207 +#if !SDL_EVENTS_DISABLED
   1.208 +    event.type = SDL_JOYDEVICEREMOVED;
   1.209 +
   1.210 +    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   1.211 +        event.jdevice.which = item->device_instance;
   1.212 +        if ( (SDL_EventOK == NULL) ||
   1.213 +             (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
   1.214 +            SDL_PushEvent(&event);
   1.215 +        }
   1.216 +    }
   1.217 +#endif /* !SDL_EVENTS_DISABLED */
   1.218 +
   1.219 +    SDL_Log("Removed joystick with device_id %d", device_id);
   1.220 +    
   1.221 +    SDL_free(item->name);
   1.222 +    SDL_free(item);
   1.223 +    return retval;
   1.224 +}
   1.225 +
   1.226 +
   1.227  int
   1.228  SDL_SYS_JoystickInit(void)
   1.229  {
   1.230 -    int i = 0;
   1.231      const char *env;
   1.232 +    SDL_SYS_JoystickDetect();
   1.233      
   1.234      env = SDL_GetHint(SDL_HINT_ACCEL_AS_JOY);
   1.235 -    if (env && !SDL_atoi(env))
   1.236 -        SYS_accelAsJoy = SDL_FALSE;
   1.237 -    else
   1.238 -        SYS_accelAsJoy = SDL_TRUE; /* Default behavior */
   1.239 -    
   1.240 -    SYS_numjoysticks = Android_JNI_GetNumJoysticks();
   1.241 -    if (SYS_accelAsJoy) {
   1.242 -        SYS_numjoysticks++;
   1.243 -    }
   1.244 -    SYS_Joysticks = (SDL_Joystick **)SDL_calloc(1, SYS_numjoysticks*sizeof(SDL_Joystick *));
   1.245 -    if (SYS_Joysticks == NULL)
   1.246 -    {
   1.247 -        return SDL_OutOfMemory();
   1.248 -    }
   1.249 -    SYS_JoystickNames = (char **)SDL_calloc(1, SYS_numjoysticks*sizeof(char *));
   1.250 -    if (SYS_JoystickNames == NULL)
   1.251 -    {
   1.252 -        SDL_free(SYS_Joysticks);
   1.253 -        SYS_Joysticks = NULL;
   1.254 -        return SDL_OutOfMemory();
   1.255 -    }
   1.256 -    
   1.257 -    for (i = 0; i < SYS_numjoysticks; i++)
   1.258 -    {
   1.259 -        if ( SYS_accelAsJoy && i == ANDROID_ACCELEROMETER_INDEX ) {
   1.260 -            SYS_JoystickNames[i] = ANDROID_ACCELEROMETER_NAME;
   1.261 -        } else {
   1.262 -            SYS_JoystickNames[i] = Android_JNI_GetJoystickName(i);
   1.263 -        }
   1.264 +    if (!env || SDL_atoi(env)) {
   1.265 +        /* Default behavior, accelerometer as joystick */
   1.266 +        Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, SDL_TRUE, 0, 3, 0, 0);
   1.267      }
   1.268     
   1.269 -    return (SYS_numjoysticks);
   1.270 +    return (numjoysticks);
   1.271 +
   1.272  }
   1.273  
   1.274  int SDL_SYS_NumJoysticks()
   1.275  {
   1.276 -    return SYS_numjoysticks;
   1.277 +    return numjoysticks;
   1.278  }
   1.279  
   1.280  void SDL_SYS_JoystickDetect()
   1.281  {
   1.282 +    /* Support for device connect/disconnect is API >= 16 only,
   1.283 +     * so we have to poll ever few seconds.
   1.284 +     * Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html
   1.285 +     */
   1.286 +    Android_JNI_PollInputDevices();   
   1.287 +}
   1.288 +
   1.289 +SDL_bool SDL_SYS_JoystickNeedsPolling()
   1.290 +{
   1.291 +    return SDL_TRUE;
   1.292  }
   1.293  
   1.294 -/* TODO: Hotplugging support */
   1.295 -SDL_bool SDL_SYS_JoystickNeedsPolling()
   1.296 +static SDL_joylist_item *
   1.297 +JoystickByDevIndex(int device_index)
   1.298 +{
   1.299 +    SDL_joylist_item *item = SDL_joylist;
   1.300 +
   1.301 +    if ((device_index < 0) || (device_index >= numjoysticks)) {
   1.302 +        return NULL;
   1.303 +    }
   1.304 +
   1.305 +    while (device_index > 0) {
   1.306 +        SDL_assert(item != NULL);
   1.307 +        device_index--;
   1.308 +        item = item->next;
   1.309 +    }
   1.310 +
   1.311 +    return item;
   1.312 +}
   1.313 +
   1.314 +static SDL_joylist_item *
   1.315 +JoystickByDeviceId(int device_id)
   1.316  {
   1.317 -    return SDL_FALSE;
   1.318 +    SDL_joylist_item *item = SDL_joylist;
   1.319 +
   1.320 +    while (item != NULL) {
   1.321 +        if (item->device_id == device_id) {
   1.322 +            return item;
   1.323 +        }
   1.324 +        item = item->next;
   1.325 +    }
   1.326 +    
   1.327 +    /* Joystick not found, try adding it */
   1.328 +    SDL_SYS_JoystickDetect();
   1.329 +    
   1.330 +    while (item != NULL) {
   1.331 +        if (item->device_id == device_id) {
   1.332 +            return item;
   1.333 +        }
   1.334 +        item = item->next;
   1.335 +    }
   1.336 +
   1.337 +    return NULL;
   1.338  }
   1.339  
   1.340  /* Function to get the device-dependent name of a joystick */
   1.341  const char *
   1.342  SDL_SYS_JoystickNameForDeviceIndex(int device_index)
   1.343  {
   1.344 -    return SYS_JoystickNames[device_index];
   1.345 +    return JoystickByDevIndex(device_index)->name;
   1.346  }
   1.347  
   1.348  /* Function to perform the mapping from device index to the instance id for this index */
   1.349  SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
   1.350  {
   1.351 -    return device_index;
   1.352 +    return JoystickByDevIndex(device_index)->device_instance;
   1.353  }
   1.354  
   1.355  /* Function to open a joystick for use.
   1.356 @@ -221,49 +414,54 @@
   1.357  int
   1.358  SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
   1.359  {
   1.360 -    if (device_index < SYS_numjoysticks) {
   1.361 -        joystick->nhats = 0;
   1.362 -        joystick->nballs = 0;
   1.363 -        if (SYS_accelAsJoy && device_index == ANDROID_ACCELEROMETER_INDEX) {
   1.364 -            joystick->nbuttons = 0;
   1.365 -            joystick->naxes = 3;
   1.366 -        } else {
   1.367 -            /* FIXME: Get the real number of buttons in the device? */
   1.368 -            joystick->nbuttons = ANDROID_MAX_NBUTTONS;
   1.369 -            joystick->naxes = Android_JNI_GetJoystickAxes(device_index);
   1.370 -        }
   1.371 -        
   1.372 -        SYS_Joysticks[device_index] = joystick;
   1.373 -        return 0;
   1.374 -    } else {
   1.375 -        return SDL_SetError("No joystick available with that index");
   1.376 +    SDL_joylist_item *item = JoystickByDevIndex(device_index);
   1.377 +    char *fname = NULL;
   1.378 +
   1.379 +    if (item == NULL ) {
   1.380 +        return SDL_SetError("No such device");
   1.381 +    }
   1.382 +    
   1.383 +    if (item->joystick != NULL) {
   1.384 +        return SDL_SetError("Joystick already opened");
   1.385      }
   1.386 +
   1.387 +    joystick->instance_id = item->device_instance;
   1.388 +    joystick->hwdata = (struct joystick_hwdata *) item;
   1.389 +    item->joystick = joystick;
   1.390 +    joystick->nhats = item->nhats;
   1.391 +    joystick->nballs = item->nballs;
   1.392 +    joystick->nbuttons = item->nbuttons;
   1.393 +    joystick->naxes = item->naxes;
   1.394 +
   1.395 +    return (0);
   1.396  }
   1.397  
   1.398  /* Function to determine is this joystick is attached to the system right now */
   1.399  SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
   1.400  {
   1.401 -    return SDL_TRUE;
   1.402 +    return !joystick->closed && (joystick->hwdata != NULL);
   1.403  }
   1.404  
   1.405 -/* Function to update the state of a joystick - called as a device poll.
   1.406 - * This function shouldn't update the joystick structure directly,
   1.407 - * but instead should call SDL_PrivateJoystick*() to deliver events
   1.408 - * and update joystick device state.
   1.409 - */
   1.410  void
   1.411  SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
   1.412  {
   1.413      int i;
   1.414      Sint16 value;
   1.415      float values[3];
   1.416 +    SDL_joylist_item *item = SDL_joylist;
   1.417  
   1.418 -    if (SYS_accelAsJoy && Android_JNI_GetAccelerometerValues(values) &&
   1.419 -        joystick->instance_id == ANDROID_ACCELEROMETER_INDEX) {
   1.420 -        for ( i = 0; i < 3; i++ ) {
   1.421 -            value = (Sint16)(values[i] * 32767.0f);
   1.422 -            SDL_PrivateJoystickAxis(joystick, i, value);
   1.423 +    while (item) {
   1.424 +        if (item->is_accelerometer) {
   1.425 +            if (item->joystick) {
   1.426 +                Android_JNI_GetAccelerometerValues(values);
   1.427 +                for ( i = 0; i < 3; i++ ) {
   1.428 +                    value = (Sint16)(values[i] * 32767.0f);
   1.429 +                    SDL_PrivateJoystickAxis(item->joystick, i, value);
   1.430 +                }
   1.431 +            }
   1.432 +            break;
   1.433          }
   1.434 +        item = item->next;
   1.435      }
   1.436  }
   1.437  
   1.438 @@ -271,14 +469,10 @@
   1.439  void
   1.440  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   1.441  {
   1.442 -    int device_index;
   1.443 -    
   1.444 -    for (device_index = 0; device_index < SYS_numjoysticks; device_index++) {
   1.445 -        if ( SYS_Joysticks[device_index] == joystick ) {
   1.446 -            SYS_Joysticks[device_index] = NULL;
   1.447 -        }
   1.448 +    if (joystick->hwdata) {
   1.449 +        ((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
   1.450 +        joystick->hwdata = NULL;
   1.451      }
   1.452 -    
   1.453      joystick->closed = 1;
   1.454  }
   1.455  
   1.456 @@ -286,70 +480,29 @@
   1.457  void
   1.458  SDL_SYS_JoystickQuit(void)
   1.459  {
   1.460 -    SDL_free(SYS_JoystickNames);
   1.461 -    SDL_free(SYS_Joysticks);
   1.462 -    SYS_JoystickNames = NULL;
   1.463 -    SYS_Joysticks = NULL;
   1.464 +    SDL_joylist_item *item = NULL;
   1.465 +    SDL_joylist_item *next = NULL;
   1.466 +
   1.467 +    for (item = SDL_joylist; item; item = next) {
   1.468 +        next = item->next;
   1.469 +        SDL_free(item->name);
   1.470 +        SDL_free(item);
   1.471 +    }
   1.472 +
   1.473 +    SDL_joylist = SDL_joylist_tail = NULL;
   1.474 +
   1.475 +    numjoysticks = 0;
   1.476 +    instance_counter = 0;
   1.477  }
   1.478  
   1.479  SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
   1.480  {
   1.481 -    SDL_JoystickGUID guid;
   1.482 -    /* the GUID is just the first 16 chars of the name for now */
   1.483 -    const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
   1.484 -    SDL_zero( guid );
   1.485 -    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
   1.486 -    return guid;
   1.487 +    return JoystickByDevIndex(device_index)->guid;
   1.488  }
   1.489  
   1.490  SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
   1.491  {
   1.492 -    SDL_JoystickGUID guid;
   1.493 -    /* the GUID is just the first 16 chars of the name for now */
   1.494 -    const char *name = joystick->name;
   1.495 -    SDL_zero( guid );
   1.496 -    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
   1.497 -    return guid;
   1.498 -}
   1.499 -
   1.500 -int
   1.501 -Android_OnPadDown(int padId, int keycode)
   1.502 -{
   1.503 -    int button = keycode_to_SDL(keycode);
   1.504 -    if (button >= 0) {
   1.505 -        if (SYS_Joysticks[padId]) {
   1.506 -            SDL_PrivateJoystickButton(SYS_Joysticks[padId], button , SDL_PRESSED);
   1.507 -        }
   1.508 -        return 0;
   1.509 -    }
   1.510 -    
   1.511 -    return -1;
   1.512 -}
   1.513 -
   1.514 -int
   1.515 -Android_OnPadUp(int padId, int keycode)
   1.516 -{
   1.517 -    int button = keycode_to_SDL(keycode);
   1.518 -    if (button >= 0) {
   1.519 -        if (SYS_Joysticks[padId]) {
   1.520 -            SDL_PrivateJoystickButton(SYS_Joysticks[padId], button, SDL_RELEASED);
   1.521 -        }
   1.522 -        return 0;
   1.523 -    }
   1.524 -    
   1.525 -    return -1;
   1.526 -}
   1.527 -
   1.528 -int
   1.529 -Android_OnJoy(int joyId, int axis, float value)
   1.530 -{
   1.531 -    /* Android gives joy info normalized as [-1.0, 1.0] or [0.0, 1.0] */
   1.532 -    /* TODO: Are the reported values right? */
   1.533 -    if (SYS_Joysticks[joyId]) {
   1.534 -        SDL_PrivateJoystickAxis(SYS_Joysticks[joyId], axis, (Sint16) (32767.*value) );
   1.535 -    }
   1.536 -    
   1.537 -    return 0;
   1.538 +    return ((SDL_joylist_item*)joystick->hwdata)->guid;
   1.539  }
   1.540  
   1.541  #endif /* SDL_JOYSTICK_ANDROID */