SDL  2.0
SDL_sysjoystick.m File Reference
#include "../../SDL_internal.h"
#include "SDL_sysjoystick_c.h"
#include "SDL_config_iphoneos.h"
#include "SDL_assert.h"
#include "SDL_events.h"
#include "SDL_joystick.h"
#include "SDL_hints.h"
#include "SDL_stdinc.h"
#include "../SDL_sysjoystick.h"
#include "../SDL_joystick_c.h"
#include "../steam/SDL_steamcontroller.h"
#include "../../events/SDL_events_c.h"
#import <CoreMotion/CoreMotion.h>
+ Include dependency graph for SDL_sysjoystick.m:

Go to the source code of this file.

Functions

static SDL_JoystickDeviceItemGetDeviceForIndex (int device_index)
 
static void SDL_SYS_AddMFIJoystickDevice (SDL_JoystickDeviceItem *device, GCController *controller)
 
static void SDL_SYS_AddJoystickDevice (GCController *controller, SDL_bool accelerometer)
 
static SDL_JoystickDeviceItemSDL_SYS_RemoveJoystickDevice (SDL_JoystickDeviceItem *device)
 
static SDL_bool SteamControllerConnectedCallback (const char *name, SDL_JoystickGUID guid, int *device_instance)
 
static void SteamControllerDisconnectedCallback (int device_instance)
 
int SDL_SYS_JoystickInit (void)
 
int SDL_SYS_NumJoysticks (void)
 
void SDL_SYS_JoystickDetect (void)
 
const char * SDL_SYS_JoystickNameForDeviceIndex (int device_index)
 
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex (int device_index)
 
int SDL_SYS_JoystickOpen (SDL_Joystick *joystick, int device_index)
 
SDL_bool SDL_SYS_JoystickAttached (SDL_Joystick *joystick)
 
static void SDL_SYS_AccelerometerUpdate (SDL_Joystick *joystick)
 
static void SDL_SYS_MFIJoystickUpdate (SDL_Joystick *joystick)
 
void SDL_SYS_JoystickUpdate (SDL_Joystick *joystick)
 
void SDL_SYS_JoystickClose (SDL_Joystick *joystick)
 
void SDL_SYS_JoystickQuit (void)
 
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID (int device_index)
 
SDL_JoystickGUID SDL_SYS_JoystickGetGUID (SDL_Joystick *joystick)
 

Variables

static const char * accelerometerName = "iOS Accelerometer"
 
static CMMotionManager * motionManager = nil
 
static SDL_JoystickDeviceItemdeviceList = NULL
 
static int numjoysticks = 0
 
static SDL_JoystickID instancecounter = 0
 
int SDL_AppleTVRemoteOpenedAsJoystick = 0
 

Function Documentation

◆ GetDeviceForIndex()

static SDL_JoystickDeviceItem* GetDeviceForIndex ( int  device_index)
static

Definition at line 66 of file SDL_sysjoystick.m.

References device, deviceList, i, recDevice::next, and NULL.

Referenced by SDL_SYS_GetInstanceIdOfDeviceIndex(), SDL_SYS_JoystickGetDeviceGUID(), SDL_SYS_JoystickNameForDeviceIndex(), and SDL_SYS_JoystickOpen().

67 {
69  int i = 0;
70 
71  while (i < device_index) {
72  if (device == NULL) {
73  return NULL;
74  }
75  device = device->next;
76  i++;
77  }
78 
79  return device;
80 }
static SDL_JoystickDeviceItem * deviceList
struct joystick_hwdata * next
static SDL_AudioDeviceID device
Definition: loopwave.c:37
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:164

◆ SDL_SYS_AccelerometerUpdate()

static void SDL_SYS_AccelerometerUpdate ( SDL_Joystick *  joystick)
static

Definition at line 475 of file SDL_sysjoystick.m.

References motionManager, SDL_HAT_CENTERED, SDL_HAT_DOWN, SDL_HAT_LEFT, SDL_HAT_RIGHT, SDL_HAT_UP, SDL_IPHONE_MAX_GFORCE, SDL_max, SDL_min, and SDL_PrivateJoystickAxis().

Referenced by SDL_SYS_JoystickUpdate().

476 {
477 #if !TARGET_OS_TV
478  const float maxgforce = SDL_IPHONE_MAX_GFORCE;
479  const SInt16 maxsint16 = 0x7FFF;
480  CMAcceleration accel;
481 
482  @autoreleasepool {
483  if (!motionManager.isAccelerometerActive) {
484  return;
485  }
486 
487  accel = motionManager.accelerometerData.acceleration;
488  }
489 
490  /*
491  Convert accelerometer data from floating point to Sint16, which is what
492  the joystick system expects.
493 
494  To do the conversion, the data is first clamped onto the interval
495  [-SDL_IPHONE_MAX_G_FORCE, SDL_IPHONE_MAX_G_FORCE], then the data is multiplied
496  by MAX_SINT16 so that it is mapped to the full range of an Sint16.
497 
498  You can customize the clamped range of this function by modifying the
499  SDL_IPHONE_MAX_GFORCE macro in SDL_config_iphoneos.h.
500 
501  Once converted to Sint16, the accelerometer data no longer has coherent
502  units. You can convert the data back to units of g-force by multiplying
503  it in your application's code by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
504  */
505 
506  /* clamp the data */
507  accel.x = SDL_min(SDL_max(accel.x, -maxgforce), maxgforce);
508  accel.y = SDL_min(SDL_max(accel.y, -maxgforce), maxgforce);
509  accel.z = SDL_min(SDL_max(accel.z, -maxgforce), maxgforce);
510 
511  /* pass in data mapped to range of SInt16 */
512  SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
513  SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
514  SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
515 #endif /* !TARGET_OS_TV */
516 }
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:655
#define SDL_IPHONE_MAX_GFORCE
static CMMotionManager * motionManager

◆ SDL_SYS_AddJoystickDevice()

static void SDL_SYS_AddJoystickDevice ( GCController *  controller,
SDL_bool  accelerometer 
)
static

Definition at line 151 of file SDL_sysjoystick.m.

References recDevice::accelerometer, accelerometerName, recDevice::controller, SDL_JoystickGUID::data, device, deviceList, recDevice::guid, recDevice::instance_id, instancecounter, recDevice::name, recDevice::naxes, recDevice::nbuttons, recDevice::next, recDevice::nhats, NULL, numjoysticks, SDL_calloc, SDL_free, SDL_GetHintBoolean, SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_memcpy, SDL_min, SDL_PrivateJoystickAdded(), SDL_strdup, SDL_strlen, SDL_SYS_AddMFIJoystickDevice(), and SDL_TRUE.

Referenced by SDL_SYS_JoystickInit().

152 {
154 
155 #if TARGET_OS_TV
157  /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */
158  if (controller && !controller.extendedGamepad && !controller.gamepad && controller.microGamepad) {
159  return;
160  }
161  }
162 #endif
163 
164  while (device != NULL) {
165  if (device->controller == controller) {
166  return;
167  }
168  device = device->next;
169  }
170 
172  if (device == NULL) {
173  return;
174  }
175 
176  device->accelerometer = accelerometer;
177  device->instance_id = instancecounter++;
178 
179  if (accelerometer) {
180 #if TARGET_OS_TV
181  SDL_free(device);
182  return;
183 #else
184  device->name = SDL_strdup(accelerometerName);
185  device->naxes = 3; /* Device acceleration in the x, y, and z axes. */
186  device->nhats = 0;
187  device->nbuttons = 0;
188 
189  /* Use the accelerometer name as a GUID. */
190  SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name)));
191 #endif /* TARGET_OS_TV */
192  } else if (controller) {
193  SDL_SYS_AddMFIJoystickDevice(device, controller);
194  }
195 
196  if (deviceList == NULL) {
197  deviceList = device;
198  } else {
199  SDL_JoystickDeviceItem *lastdevice = deviceList;
200  while (lastdevice->next != NULL) {
201  lastdevice = lastdevice->next;
202  }
203  lastdevice->next = device;
204  }
205 
206  ++numjoysticks;
207 
209 }
#define SDL_HINT_TV_REMOTE_AS_JOYSTICK
A variable controlling whether the Android / tvOS remotes should be listed as joystick devices...
Definition: SDL_hints.h:399
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_JoystickGUID guid
static SDL_JoystickDeviceItem * deviceList
static const char * accelerometerName
struct joystick_hwdata * next
Uint8 data[16]
Definition: SDL_joystick.h:71
#define SDL_GetHintBoolean
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define SDL_memcpy
#define SDL_free
static void SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controller)
void SDL_PrivateJoystickAdded(int device_index)
Definition: SDL_joystick.c:595
#define NULL
Definition: begin_code.h:164
#define SDL_calloc
static SDL_JoystickID instancecounter
#define SDL_strlen
#define SDL_strdup
static int numjoysticks
GCController __unsafe_unretained * controller

◆ SDL_SYS_AddMFIJoystickDevice()

static void SDL_SYS_AddMFIJoystickDevice ( SDL_JoystickDeviceItem device,
GCController *  controller 
)
static

Definition at line 83 of file SDL_sysjoystick.m.

References recDevice::controller, SDL_JoystickGUID::data, recDevice::guid, recDevice::name, recDevice::naxes, recDevice::nbuttons, recDevice::nhats, NULL, recDevice::remote, SDL_FALSE, SDL_GetHintBoolean, SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_strdup, and SDL_TRUE.

Referenced by SDL_SYS_AddJoystickDevice().

84 {
85 #ifdef SDL_JOYSTICK_MFI
86  const char *name = NULL;
87  /* Explicitly retain the controller because SDL_JoystickDeviceItem is a
88  * struct, and ARC doesn't work with structs. */
89  device->controller = (__bridge GCController *) CFBridgingRetain(controller);
90 
91  if (controller.vendorName) {
92  name = controller.vendorName.UTF8String;
93  }
94 
95  if (!name) {
96  name = "MFi Gamepad";
97  }
98 
99  device->name = SDL_strdup(name);
100 
101  device->guid.data[0] = 'M';
102  device->guid.data[1] = 'F';
103  device->guid.data[2] = 'i';
104  device->guid.data[3] = 'G';
105  device->guid.data[4] = 'a';
106  device->guid.data[5] = 'm';
107  device->guid.data[6] = 'e';
108  device->guid.data[7] = 'p';
109  device->guid.data[8] = 'a';
110  device->guid.data[9] = 'd';
111 
112  if (controller.extendedGamepad) {
113  device->guid.data[10] = 1;
114  } else if (controller.gamepad) {
115  device->guid.data[10] = 2;
116  }
117 #if TARGET_OS_TV
118  else if (controller.microGamepad) {
119  device->guid.data[10] = 3;
120  device->remote = SDL_TRUE;
121  }
122 #endif /* TARGET_OS_TV */
123 
124  if (controller.extendedGamepad) {
125  device->naxes = 6; /* 2 thumbsticks and 2 triggers */
126  device->nhats = 1; /* d-pad */
127  device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
128  } else if (controller.gamepad) {
129  device->naxes = 0; /* no traditional analog inputs */
130  device->nhats = 1; /* d-pad */
131  device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
132  }
133 #if TARGET_OS_TV
134  else if (controller.microGamepad) {
135  device->naxes = 2; /* treat the touch surface as two axes */
136  device->nhats = 0; /* apparently the touch surface-as-dpad is buggy */
137  device->nbuttons = 3; /* AX, pause button */
138 
139  controller.microGamepad.allowsRotation = SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_FALSE);
140  }
141 #endif /* TARGET_OS_TV */
142 
143  /* This will be set when the first button press of the controller is
144  * detected. */
145  controller.playerIndex = -1;
146 
147 #endif /* SDL_JOYSTICK_MFI */
148 }
SDL_JoystickGUID guid
#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION
A variable controlling whether the Apple TV remote&#39;s joystick axes will automatically match the rotat...
Definition: SDL_hints.h:368
Uint8 data[16]
Definition: SDL_joystick.h:71
GLuint const GLchar * name
#define SDL_GetHintBoolean
#define NULL
Definition: begin_code.h:164
#define SDL_strdup
GCController __unsafe_unretained * controller

◆ SDL_SYS_GetInstanceIdOfDeviceIndex()

SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex ( int  device_index)

Definition at line 409 of file SDL_sysjoystick.m.

References device, GetDeviceForIndex(), and recDevice::instance_id.

Referenced by SDL_GameControllerOpen(), and SDL_JoystickGetDeviceInstanceID().

410 {
412  return device ? device->instance_id : 0;
413 }
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37

◆ SDL_SYS_JoystickAttached()

SDL_bool SDL_SYS_JoystickAttached ( SDL_Joystick *  joystick)

Definition at line 469 of file SDL_sysjoystick.m.

References NULL.

Referenced by SDL_JoystickGetAttached().

470 {
471  return joystick->hwdata != NULL;
472 }
#define NULL
Definition: begin_code.h:164

◆ SDL_SYS_JoystickClose()

void SDL_SYS_JoystickClose ( SDL_Joystick *  joystick)

Definition at line 704 of file SDL_sysjoystick.m.

References recDevice::accelerometer, recDevice::controller, device, recDevice::joystick, NULL, recDevice::remote, and SDL_AppleTVRemoteOpenedAsJoystick.

Referenced by SDL_JoystickClose().

705 {
706  SDL_JoystickDeviceItem *device = joystick->hwdata;
707 
708  if (device == NULL) {
709  return;
710  }
711 
712  device->joystick = NULL;
713 
714  @autoreleasepool {
715  if (device->accelerometer) {
716 #if !TARGET_OS_TV
717  [motionManager stopAccelerometerUpdates];
718 #endif /* !TARGET_OS_TV */
719  } else if (device->controller) {
720 #ifdef SDL_JOYSTICK_MFI
721  GCController *controller = device->controller;
722  controller.controllerPausedHandler = nil;
723  controller.playerIndex = -1;
724 #endif
725  }
726  }
727  if (device->remote) {
729  }
730 }
SDL_Joystick * joystick
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define NULL
Definition: begin_code.h:164
int SDL_AppleTVRemoteOpenedAsJoystick
GCController __unsafe_unretained * controller

◆ SDL_SYS_JoystickDetect()

void SDL_SYS_JoystickDetect ( void  )

Definition at line 395 of file SDL_sysjoystick.m.

References SDL_UpdateSteamControllers().

Referenced by SDL_JoystickUpdate().

396 {
398 }
void SDL_UpdateSteamControllers(void)

◆ SDL_SYS_JoystickGetDeviceGUID()

SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID ( int  device_index)

Definition at line 771 of file SDL_sysjoystick.m.

References device, GetDeviceForIndex(), recDevice::guid, and SDL_zero.

Referenced by SDL_JoystickGetDeviceGUID().

772 {
774  SDL_JoystickGUID guid;
775  if (device) {
776  guid = device->guid;
777  } else {
778  SDL_zero(guid);
779  }
780  return guid;
781 }
SDL_JoystickGUID guid
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define SDL_zero(x)
Definition: SDL_stdinc.h:416

◆ SDL_SYS_JoystickGetGUID()

SDL_JoystickGUID SDL_SYS_JoystickGetGUID ( SDL_Joystick *  joystick)

Definition at line 784 of file SDL_sysjoystick.m.

References recDevice::guid, and SDL_zero.

Referenced by SDL_JoystickGetGUID().

785 {
786  SDL_JoystickGUID guid;
787  if (joystick->hwdata) {
788  guid = joystick->hwdata->guid;
789  } else {
790  SDL_zero(guid);
791  }
792  return guid;
793 }
#define SDL_zero(x)
Definition: SDL_stdinc.h:416

◆ SDL_SYS_JoystickInit()

int SDL_SYS_JoystickInit ( void  )

Definition at line 330 of file SDL_sysjoystick.m.

References recDevice::controller, sort_controllers::controllers, NULL, numjoysticks, SDL_AddHintCallback, SDL_FALSE, SDL_GetHintBoolean, SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_InitSteamControllers(), SDL_SYS_AddJoystickDevice(), SDL_TRUE, SteamControllerConnectedCallback(), and SteamControllerDisconnectedCallback().

Referenced by SDL_JoystickInit().

331 {
332  @autoreleasepool {
333  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
334 
337 
338 #if !TARGET_OS_TV
340  /* Default behavior, accelerometer as joystick */
342  }
343 #endif /* !TARGET_OS_TV */
344 
345 #ifdef SDL_JOYSTICK_MFI
346  /* GameController.framework was added in iOS 7. */
347  if (![GCController class]) {
348  return numjoysticks;
349  }
350 
351  for (GCController *controller in [GCController controllers]) {
353  }
354 
355 #if TARGET_OS_TV
357  SDL_AppleTVRemoteRotationHintChanged, NULL);
358 #endif /* TARGET_OS_TV */
359 
360  connectObserver = [center addObserverForName:GCControllerDidConnectNotification
361  object:nil
362  queue:nil
363  usingBlock:^(NSNotification *note) {
364  GCController *controller = note.object;
365  SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
366  }];
367 
368  disconnectObserver = [center addObserverForName:GCControllerDidDisconnectNotification
369  object:nil
370  queue:nil
371  usingBlock:^(NSNotification *note) {
372  GCController *controller = note.object;
373  SDL_JoystickDeviceItem *device = deviceList;
374  while (device != NULL) {
375  if (device->controller == controller) {
376  SDL_SYS_RemoveJoystickDevice(device);
377  break;
378  }
379  device = device->next;
380  }
381  }];
382 #endif /* SDL_JOYSTICK_MFI */
383  }
384 
385  return numjoysticks;
386 }
void SDL_InitSteamControllers(SteamControllerConnectedCallback_t connectedCallback, SteamControllerDisconnectedCallback_t disconnectedCallback)
static void SteamControllerDisconnectedCallback(int device_instance)
#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION
A variable controlling whether the Apple TV remote&#39;s joystick axes will automatically match the rotat...
Definition: SDL_hints.h:368
#define SDL_GetHintBoolean
#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK
A variable controlling whether the Android / iOS built-in accelerometer should be listed as a joystic...
Definition: SDL_hints.h:389
static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
#define NULL
Definition: begin_code.h:164
#define SDL_AddHintCallback
static int numjoysticks
GLuint in
static void SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)

◆ SDL_SYS_JoystickNameForDeviceIndex()

const char* SDL_SYS_JoystickNameForDeviceIndex ( int  device_index)

Definition at line 402 of file SDL_sysjoystick.m.

References device, GetDeviceForIndex(), and recDevice::name.

Referenced by SDL_JoystickNameForIndex(), and SDL_JoystickOpen().

403 {
405  return device ? device->name : "Unknown";
406 }
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37

◆ SDL_SYS_JoystickOpen()

int SDL_SYS_JoystickOpen ( SDL_Joystick *  joystick,
int  device_index 
)

Definition at line 421 of file SDL_sysjoystick.m.

References recDevice::accelerometer, recDevice::controller, device, GetDeviceForIndex(), recDevice::instance_id, recDevice::joystick, motionManager, recDevice::naxes, recDevice::nbuttons, recDevice::nhats, NULL, recDevice::remote, SDL_AppleTVRemoteOpenedAsJoystick, and SDL_SetError.

Referenced by SDL_JoystickOpen().

422 {
424  if (device == NULL) {
425  return SDL_SetError("Could not open Joystick: no hardware device for the specified index");
426  }
427 
428  joystick->hwdata = device;
429  joystick->instance_id = device->instance_id;
430 
431  joystick->naxes = device->naxes;
432  joystick->nhats = device->nhats;
433  joystick->nbuttons = device->nbuttons;
434  joystick->nballs = 0;
435 
436  device->joystick = joystick;
437 
438  @autoreleasepool {
439  if (device->accelerometer) {
440 #if !TARGET_OS_TV
441  if (motionManager == nil) {
442  motionManager = [[CMMotionManager alloc] init];
443  }
444 
445  /* Shorter times between updates can significantly increase CPU usage. */
446  motionManager.accelerometerUpdateInterval = 0.1;
447  [motionManager startAccelerometerUpdates];
448 #endif /* !TARGET_OS_TV */
449  } else {
450 #ifdef SDL_JOYSTICK_MFI
451  GCController *controller = device->controller;
452  controller.controllerPausedHandler = ^(GCController *c) {
453  if (joystick->hwdata) {
454  ++joystick->hwdata->num_pause_presses;
455  }
456  };
457 #endif /* SDL_JOYSTICK_MFI */
458  }
459  }
460  if (device->remote) {
462  }
463 
464  return 0;
465 }
SDL_Joystick * joystick
static SDL_JoystickDeviceItem * GetDeviceForIndex(int device_index)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
const GLubyte * c
#define NULL
Definition: begin_code.h:164
#define SDL_SetError
int SDL_AppleTVRemoteOpenedAsJoystick
GCController __unsafe_unretained * controller
static CMMotionManager * motionManager

◆ SDL_SYS_JoystickQuit()

void SDL_SYS_JoystickQuit ( void  )

Definition at line 734 of file SDL_sysjoystick.m.

References motionManager, NULL, numjoysticks, SDL_DelHintCallback, SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_QuitSteamControllers(), and SDL_SYS_RemoveJoystickDevice().

Referenced by SDL_JoystickQuit().

735 {
736  @autoreleasepool {
737 #ifdef SDL_JOYSTICK_MFI
738  NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
739 
740  if (connectObserver) {
741  [center removeObserver:connectObserver name:GCControllerDidConnectNotification object:nil];
742  connectObserver = nil;
743  }
744 
745  if (disconnectObserver) {
746  [center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
747  disconnectObserver = nil;
748  }
749 
750 #if TARGET_OS_TV
752  SDL_AppleTVRemoteRotationHintChanged, NULL);
753 #endif /* TARGET_OS_TV */
754 #endif /* SDL_JOYSTICK_MFI */
755 
756  while (deviceList != NULL) {
758  }
759 
760 #if !TARGET_OS_TV
761  motionManager = nil;
762 #endif /* !TARGET_OS_TV */
763  }
764 
766 
767  numjoysticks = 0;
768 }
void SDL_QuitSteamControllers(void)
static SDL_JoystickDeviceItem * deviceList
#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION
A variable controlling whether the Apple TV remote&#39;s joystick axes will automatically match the rotat...
Definition: SDL_hints.h:368
#define NULL
Definition: begin_code.h:164
#define SDL_DelHintCallback
static SDL_JoystickDeviceItem * SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
static int numjoysticks
static CMMotionManager * motionManager

◆ SDL_SYS_JoystickUpdate()

void SDL_SYS_JoystickUpdate ( SDL_Joystick *  joystick)

Definition at line 682 of file SDL_sysjoystick.m.

References recDevice::accelerometer, recDevice::controller, device, recDevice::m_bSteamController, NULL, SDL_SYS_AccelerometerUpdate(), SDL_SYS_MFIJoystickUpdate(), and SDL_UpdateSteamController().

Referenced by SDL_JoystickOpen(), and SDL_JoystickUpdate().

683 {
684  SDL_JoystickDeviceItem *device = joystick->hwdata;
685 
686  if (device == NULL) {
687  return;
688  }
689 
690  if (device->m_bSteamController) {
691  SDL_UpdateSteamController(joystick);
692  return;
693  }
694 
695  if (device->accelerometer) {
696  SDL_SYS_AccelerometerUpdate(joystick);
697  } else if (device->controller) {
698  SDL_SYS_MFIJoystickUpdate(joystick);
699  }
700 }
static void SDL_SYS_MFIJoystickUpdate(SDL_Joystick *joystick)
static SDL_AudioDeviceID device
Definition: loopwave.c:37
#define NULL
Definition: begin_code.h:164
void SDL_UpdateSteamController(SDL_Joystick *joystick)
SDL_bool m_bSteamController
static void SDL_SYS_AccelerometerUpdate(SDL_Joystick *joystick)
GCController __unsafe_unretained * controller

◆ SDL_SYS_MFIJoystickUpdate()

static void SDL_SYS_MFIJoystickUpdate ( SDL_Joystick *  joystick)
static

Definition at line 545 of file SDL_sysjoystick.m.

References recDevice::axes, recDevice::buttons, recDevice::controller, sort_controllers::controllers, i, SDL_arraysize, SDL_HAT_CENTERED, SDL_PRESSED, SDL_PrivateJoystickAxis(), SDL_PrivateJoystickButton(), SDL_PrivateJoystickHat(), and SDL_RELEASED.

Referenced by SDL_SYS_JoystickUpdate().

546 {
547 #if SDL_JOYSTICK_MFI
548  @autoreleasepool {
549  GCController *controller = joystick->hwdata->controller;
550  Uint8 hatstate = SDL_HAT_CENTERED;
551  int i;
552  int updateplayerindex = 0;
553 
554  if (controller.extendedGamepad) {
555  GCExtendedGamepad *gamepad = controller.extendedGamepad;
556 
557  /* Axis order matches the XInput Windows mappings. */
558  Sint16 axes[] = {
559  (Sint16) (gamepad.leftThumbstick.xAxis.value * 32767),
560  (Sint16) (gamepad.leftThumbstick.yAxis.value * -32767),
561  (Sint16) ((gamepad.leftTrigger.value * 65535) - 32768),
562  (Sint16) (gamepad.rightThumbstick.xAxis.value * 32767),
563  (Sint16) (gamepad.rightThumbstick.yAxis.value * -32767),
564  (Sint16) ((gamepad.rightTrigger.value * 65535) - 32768),
565  };
566 
567  /* Button order matches the XInput Windows mappings. */
568  Uint8 buttons[] = {
569  gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
570  gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
571  gamepad.leftShoulder.isPressed,
572  gamepad.rightShoulder.isPressed,
573  };
574 
575  hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
576 
577  for (i = 0; i < SDL_arraysize(axes); i++) {
578  /* The triggers (axes 2 and 5) are resting at -32768 but SDL
579  * initializes its values to 0. We only want to make sure the
580  * player index is up to date if the user actually moves an axis. */
581  if ((i != 2 && i != 5) || axes[i] != -32768) {
582  updateplayerindex |= (joystick->axes[i].value != axes[i]);
583  }
584  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
585  }
586 
587  for (i = 0; i < SDL_arraysize(buttons); i++) {
588  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
589  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
590  }
591  } else if (controller.gamepad) {
592  GCGamepad *gamepad = controller.gamepad;
593 
594  /* Button order matches the XInput Windows mappings. */
595  Uint8 buttons[] = {
596  gamepad.buttonA.isPressed, gamepad.buttonB.isPressed,
597  gamepad.buttonX.isPressed, gamepad.buttonY.isPressed,
598  gamepad.leftShoulder.isPressed,
599  gamepad.rightShoulder.isPressed,
600  };
601 
602  hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad);
603 
604  for (i = 0; i < SDL_arraysize(buttons); i++) {
605  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
606  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
607  }
608  }
609 #if TARGET_OS_TV
610  else if (controller.microGamepad) {
611  GCMicroGamepad *gamepad = controller.microGamepad;
612 
613  Sint16 axes[] = {
614  (Sint16) (gamepad.dpad.xAxis.value * 32767),
615  (Sint16) (gamepad.dpad.yAxis.value * -32767),
616  };
617 
618  for (i = 0; i < SDL_arraysize(axes); i++) {
619  updateplayerindex |= (joystick->axes[i].value != axes[i]);
620  SDL_PrivateJoystickAxis(joystick, i, axes[i]);
621  }
622 
623  Uint8 buttons[] = {
624  gamepad.buttonA.isPressed,
625  gamepad.buttonX.isPressed,
626  };
627 
628  for (i = 0; i < SDL_arraysize(buttons); i++) {
629  updateplayerindex |= (joystick->buttons[i] != buttons[i]);
630  SDL_PrivateJoystickButton(joystick, i, buttons[i]);
631  }
632  }
633 #endif /* TARGET_OS_TV */
634 
635  if (joystick->nhats > 0) {
636  updateplayerindex |= (joystick->hats[0] != hatstate);
637  SDL_PrivateJoystickHat(joystick, 0, hatstate);
638  }
639 
640  for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
641  /* The pause button is always last. */
642  Uint8 pausebutton = joystick->nbuttons - 1;
643 
644  SDL_PrivateJoystickButton(joystick, pausebutton, SDL_PRESSED);
645  SDL_PrivateJoystickButton(joystick, pausebutton, SDL_RELEASED);
646 
647  updateplayerindex = YES;
648  }
649 
650  joystick->hwdata->num_pause_presses = 0;
651 
652  if (updateplayerindex && controller.playerIndex == -1) {
653  BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
654 
655  /* Find the player index of all other connected controllers. */
656  for (GCController *c in [GCController controllers]) {
657  if (c != controller && c.playerIndex >= 0) {
658  usedPlayerIndexSlots[c.playerIndex] = YES;
659  }
660  }
661 
662  /* Set this controller's player index to the first unused index.
663  * FIXME: This logic isn't great... but SDL doesn't expose this
664  * concept in its external API, so we don't have much to go on. */
665  for (i = 0; i < SDL_arraysize(usedPlayerIndexSlots); i++) {
666  if (!usedPlayerIndexSlots[i]) {
667  controller.playerIndex = i;
668  break;
669  }
670  }
671  }
672  }
673 #endif /* SDL_JOYSTICK_MFI */
674 }
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:712
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:788
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:655
uint8_t Uint8
Definition: SDL_stdinc.h:157
const GLubyte * c
GLsizei const GLfloat * value
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
#define SDL_PRESSED
Definition: SDL_events.h:50
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:316
#define SDL_RELEASED
Definition: SDL_events.h:49
GLuint in
int16_t Sint16
Definition: SDL_stdinc.h:163

◆ SDL_SYS_NumJoysticks()

int SDL_SYS_NumJoysticks ( void  )

Definition at line 389 of file SDL_sysjoystick.m.

References numjoysticks.

Referenced by SDL_NumJoysticks().

390 {
391  return numjoysticks;
392 }
static int numjoysticks

◆ SDL_SYS_RemoveJoystickDevice()

static SDL_JoystickDeviceItem* SDL_SYS_RemoveJoystickDevice ( SDL_JoystickDeviceItem device)
static

Definition at line 212 of file SDL_sysjoystick.m.

References recDevice::controller, sort_controllers::controllers, deviceList, recDevice::instance_id, recDevice::item, recDevice::joystick, recDevice::name, recDevice::next, NULL, numjoysticks, SDL_free, SDL_PrivateJoystickRemoved(), and SDLCALL.

Referenced by SDL_SYS_JoystickQuit(), and SteamControllerDisconnectedCallback().

213 {
217 
218  if (device == NULL) {
219  return NULL;
220  }
221 
222  next = device->next;
223 
224  while (item != NULL) {
225  if (item == device) {
226  break;
227  }
228  prev = item;
229  item = item->next;
230  }
231 
232  /* Unlink the device item from the device list. */
233  if (prev) {
234  prev->next = device->next;
235  } else if (device == deviceList) {
236  deviceList = device->next;
237  }
238 
239  if (device->joystick) {
240  device->joystick->hwdata = NULL;
241  }
242 
243 #ifdef SDL_JOYSTICK_MFI
244  @autoreleasepool {
245  if (device->controller) {
246  /* The controller was explicitly retained in the struct, so it
247  * should be explicitly released before freeing the struct. */
248  GCController *controller = CFBridgingRelease((__bridge CFTypeRef)(device->controller));
249  controller.controllerPausedHandler = nil;
250  device->controller = nil;
251  }
252  }
253 #endif /* SDL_JOYSTICK_MFI */
254 
255  --numjoysticks;
256 
258 
259  SDL_free(device->name);
260  SDL_free(device);
261 
262  return next;
263 }
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
Definition: SDL_joystick.c:638
static SDL_JoystickDeviceItem * deviceList
SDL_Joystick * joystick
struct joystick_hwdata * next
#define SDL_free
#define NULL
Definition: begin_code.h:164
static int numjoysticks
GCController __unsafe_unretained * controller

◆ SteamControllerConnectedCallback()

static SDL_bool SteamControllerConnectedCallback ( const char *  name,
SDL_JoystickGUID  guid,
int *  device_instance 
)
static

Definition at line 281 of file SDL_sysjoystick.m.

References device, deviceList, recDevice::guid, recDevice::instance_id, instancecounter, recDevice::m_bSteamController, recDevice::name, recDevice::naxes, recDevice::nbuttons, recDevice::next, recDevice::nhats, NULL, numjoysticks, SDL_calloc, SDL_FALSE, SDL_GetSteamControllerInputs(), SDL_PrivateJoystickAdded(), SDL_strdup, and SDL_TRUE.

Referenced by SDL_SYS_JoystickInit().

282 {
284  if (device == NULL) {
285  return SDL_FALSE;
286  }
287 
288  *device_instance = device->instance_id = instancecounter++;
289  device->name = SDL_strdup(name);
290  device->guid = guid;
292  &device->naxes,
293  &device->nhats);
294  device->m_bSteamController = SDL_TRUE;
295 
296  if (deviceList == NULL) {
297  deviceList = device;
298  } else {
299  SDL_JoystickDeviceItem *lastdevice = deviceList;
300  while (lastdevice->next != NULL) {
301  lastdevice = lastdevice->next;
302  }
303  lastdevice->next = device;
304  }
305 
306  ++numjoysticks;
307 
309 
310  return SDL_TRUE;
311 }
SDL_JoystickGUID guid
static SDL_JoystickDeviceItem * deviceList
struct joystick_hwdata * next
GLuint const GLchar * name
static SDL_AudioDeviceID device
Definition: loopwave.c:37
void SDL_PrivateJoystickAdded(int device_index)
Definition: SDL_joystick.c:595
#define NULL
Definition: begin_code.h:164
SDL_bool m_bSteamController
#define SDL_calloc
static SDL_JoystickID instancecounter
#define SDL_strdup
static int numjoysticks
void SDL_GetSteamControllerInputs(int *nbuttons, int *naxes, int *nhats)

◆ SteamControllerDisconnectedCallback()

static void SteamControllerDisconnectedCallback ( int  device_instance)
static

Definition at line 313 of file SDL_sysjoystick.m.

References recDevice::instance_id, recDevice::item, recDevice::next, and SDL_SYS_RemoveJoystickDevice().

Referenced by SDL_SYS_JoystickInit().

314 {
316 
317  for (item = deviceList; item; item = item->next) {
318  if (item->instance_id == device_instance) {
320  break;
321  }
322  }
323 }
static SDL_JoystickDeviceItem * deviceList
struct joystick_hwdata * next
static SDL_JoystickDeviceItem * SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)

Variable Documentation

◆ accelerometerName

const char* accelerometerName = "iOS Accelerometer"
static

Definition at line 55 of file SDL_sysjoystick.m.

Referenced by SDL_SYS_AddJoystickDevice().

◆ deviceList

◆ instancecounter

SDL_JoystickID instancecounter = 0
static

◆ motionManager

CMMotionManager* motionManager = nil
static

◆ numjoysticks

◆ SDL_AppleTVRemoteOpenedAsJoystick

int SDL_AppleTVRemoteOpenedAsJoystick = 0

Definition at line 63 of file SDL_sysjoystick.m.

Referenced by SDL_SYS_JoystickClose(), and SDL_SYS_JoystickOpen().