1 /+
2 +            Copyright 2022 – 2024 Aya Partridge
3 +          Copyright 2018 - 2022 Michael D. Parker
4 + Distributed under the Boost Software License, Version 1.0.
5 +     (See accompanying file LICENSE_1_0.txt or copy at
6 +           http://www.boost.org/LICENSE_1_0.txt)
7 +/
8 module sdl.joystick;
9 
10 import bindbc.sdl.config;
11 import bindbc.sdl.codegen;
12 
13 import sdl.stdinc: SDL_bool;
14 import sdl.guid: SDL_GUID;
15 
16 version(SDL_ThreadSafetyAnalysis){
17 	import sdl.mutex: SDL_mutex;
18 	extern extern(C) SDL_mutex* SDL_joystick_lock;
19 }
20 
21 struct SDL_Joystick;
22 
23 alias SDL_JoystickGUID = SDL_GUID;
24 
25 alias SDL_JoystickID = int;
26 
27 enum: ubyte{
28 	SDL_HAT_CENTERED   = 0x00,
29 	SDL_HAT_UP         = 0x01,
30 	SDL_HAT_RIGHT      = 0x02,
31 	SDL_HAT_DOWN       = 0x04,
32 	SDL_HAT_LEFT       = 0x08,
33 	SDL_HAT_RIGHTUP    = (SDL_HAT_RIGHT | SDL_HAT_UP),
34 	SDL_HAT_RIGHTDOWN  = (SDL_HAT_RIGHT | SDL_HAT_DOWN),
35 	SDL_HAT_LEFTUP     = (SDL_HAT_LEFT  | SDL_HAT_UP),
36 	SDL_HAT_LEFTDOWN   = (SDL_HAT_LEFT  | SDL_HAT_DOWN),
37 }
38 
39 static if(sdlSupport >= SDLSupport.v2_0_4){
40 	alias SDL_JoystickPowerLevel = int;
41 	enum: SDL_JoystickPowerLevel{
42 		SDL_JOYSTICK_POWER_UNKNOWN = -1,
43 		SDL_JOYSTICK_POWER_EMPTY,
44 		SDL_JOYSTICK_POWER_LOW,
45 		SDL_JOYSTICK_POWER_MEDIUM,
46 		SDL_JOYSTICK_POWER_FULL,
47 		SDL_JOYSTICK_POWER_WIRED,
48 		SDL_JOYSTICK_POWER_MAX
49 	}
50 }
51 
52 static if(sdlSupport >= SDLSupport.v2_0_14){
53 	enum SDL_IPHONE_MAX_GFORCE = 5.0;
54 }
55 
56 static if(sdlSupport >= SDLSupport.v2_24){
57 	struct SDL_VirtualJoystickDesc{
58 		ushort version_; //NOTE: the original variable's name is `version`
59 		ushort type;
60 		ushort naxes;
61 		ushort nbuttons;
62 		ushort nhats;
63 		ushort vendor_id;
64 		ushort product_id;
65 		ushort padding;
66 		uint button_mask;
67 		uint axis_mask;
68 		const(char)* name;
69 
70 		void* userdata;
71 		void function(void* userData) Update;
72 		void function(void* userData, int playerIndex) SetPlayerIndex;
73 		int function(void* userData, ushort lowFrequencyRumble, ushort highFrequencyRumble) Rumble;
74 		int function(void* userData, ushort leftRumble, ushort rightRumble) RumbleTriggers;
75 		int function(void* userData, ubyte red, ubyte green, ubyte blue) SetLED;
76 		int function(void* userData, const(void)* data, int size) SendEffect;
77 	}
78 	
79 	enum ushort SDL_VIRTUAL_JOYSTICK_DESC_VERSION = 1;
80 }
81 
82 static if(sdlSupport >= SDLSupport.v2_0_6){
83 	alias SDL_JoystickType = ushort;
84 	enum: SDL_JoystickType{
85 		SDL_JOYSTICK_TYPE_UNKNOWN,
86 		SDL_JOYSTICK_TYPE_GAMECONTROLLER,
87 		SDL_JOYSTICK_TYPE_WHEEL,
88 		SDL_JOYSTICK_TYPE_ARCADE_STICK,
89 		SDL_JOYSTICK_TYPE_FLIGHT_STICK,
90 		SDL_JOYSTICK_TYPE_DANCE_PAD,
91 		SDL_JOYSTICK_TYPE_GUITAR,
92 		SDL_JOYSTICK_TYPE_DRUM_KIT,
93 		SDL_JOYSTICK_TYPE_ARCADE_PAD,
94 		SDL_JOYSTICK_TYPE_THROTTLE,
95 	}
96 	
97 	enum{
98 		SDL_JOYSTICK_AXIS_MAX = 32767,
99 		SDL_JOYSTICK_AXIS_MIN = -32768,
100 	}
101 }
102 
103 mixin(joinFnBinds((){
104 	FnBind[] ret = [
105 		{q{int}, q{SDL_NumJoysticks}, q{}},
106 		{q{const(char)*}, q{SDL_JoystickNameForIndex}, q{int deviceIndex}},
107 		{q{SDL_JoystickGUID}, q{SDL_JoystickGetDeviceGUID}, q{int deviceIndex}},
108 		{q{SDL_Joystick*}, q{SDL_JoystickOpen}, q{int device_index}},
109 		{q{const(char)*}, q{SDL_JoystickName}, q{SDL_Joystick* joystick}},
110 		{q{SDL_JoystickGUID}, q{SDL_JoystickGetGUID}, q{SDL_Joystick* joystick}},
111 		{q{void}, q{SDL_JoystickGetGUIDString}, q{SDL_JoystickGUID guid, char* pszGUID, int cbGUID}},
112 		{q{SDL_JoystickGUID}, q{SDL_JoystickGetGUIDFromString}, q{const(char)*}},
113 		{q{SDL_bool}, q{SDL_JoystickGetAttached}, q{SDL_Joystick* joystick}},
114 		{q{SDL_JoystickID}, q{SDL_JoystickInstanceID}, q{SDL_Joystick* joystick}},
115 		{q{int}, q{SDL_JoystickNumAxes}, q{SDL_Joystick* joystick}},
116 		{q{int}, q{SDL_JoystickNumBalls}, q{SDL_Joystick* joystick}},
117 		{q{int}, q{SDL_JoystickNumHats}, q{SDL_Joystick* joystick}},
118 		{q{int}, q{SDL_JoystickNumButtons}, q{SDL_Joystick* joystick}},
119 		{q{void}, q{SDL_JoystickUpdate}, q{}},
120 		{q{int}, q{SDL_JoystickEventState}, q{int state}},
121 		{q{short}, q{SDL_JoystickGetAxis}, q{SDL_Joystick* joystick, int axis}},
122 		{q{ubyte}, q{SDL_JoystickGetHat}, q{SDL_Joystick* joystick, int hat}},
123 		{q{int}, q{SDL_JoystickGetBall}, q{SDL_Joystick* joystick, int ball, int* dx, int* dy}},
124 		{q{ubyte}, q{SDL_JoystickGetButton}, q{SDL_Joystick* joystick, int button}},
125 		{q{void}, q{SDL_JoystickClose}, q{SDL_Joystick* joystick}},
126 	];
127 	if(sdlSupport >= SDLSupport.v2_0_4){
128 		FnBind[] add = [
129 			{q{SDL_JoystickPowerLevel}, q{SDL_JoystickCurrentPowerLevel}, q{SDL_Joystick* joystick}},
130 			{q{SDL_Joystick*}, q{SDL_JoystickFromInstanceID}, q{SDL_JoystickID instanceID}},
131 		];
132 		ret ~= add;
133 	}
134 	if(sdlSupport >= SDLSupport.v2_0_6){
135 		FnBind[] add = [
136 			{q{SDL_bool}, q{SDL_JoystickGetAxisInitialState}, q{SDL_Joystick* joystick, int axis, short* state}},
137 			{q{ushort}, q{SDL_JoystickGetDeviceProduct}, q{int deviceIndex}},
138 			{q{ushort}, q{SDL_JoystickGetDeviceProductVersion}, q{int deviceIndex}},
139 			{q{SDL_JoystickType}, q{SDL_JoystickGetDeviceType}, q{int deviceIndex}},
140 			{q{SDL_JoystickType}, q{SDL_JoystickGetDeviceInstanceID}, q{int deviceIndex}},
141 			{q{ushort}, q{SDL_JoystickGetDeviceVendor}, q{int device_index}},
142 			{q{ushort}, q{SDL_JoystickGetProduct}, q{SDL_Joystick* joystick}},
143 			{q{ushort}, q{SDL_JoystickGetProductVersion}, q{SDL_Joystick* joystick}},
144 			{q{SDL_JoystickType}, q{SDL_JoystickGetType}, q{SDL_Joystick* joystick}},
145 			{q{ushort}, q{SDL_JoystickGetVendor}, q{SDL_Joystick* joystick}},
146 		];
147 		ret ~= add;
148 	}
149 	if(sdlSupport >= SDLSupport.v2_0_7){
150 		FnBind[] add = [
151 			{q{void}, q{SDL_LockJoysticks}, q{}},
152 			{q{void}, q{SDL_UnlockJoysticks}, q{}},
153 		];
154 		ret ~= add;
155 	}
156 	if(sdlSupport >= SDLSupport.v2_0_9){
157 		FnBind[] add = [
158 			{q{int}, q{SDL_JoystickRumble}, q{SDL_Joystick* joystick, ushort lowFrequencyRumble, ushort highFrequencyRumble, uint durationMS}},
159 		];
160 		ret ~= add;
161 	}
162 	if(sdlSupport >= SDLSupport.v2_0_10){
163 		FnBind[] add = [
164 			{q{int}, q{SDL_JoystickGetDevicePlayerIndex}, q{int deviceIndex}},
165 			{q{int}, q{SDL_JoystickGetPlayerIndex}, q{SDL_Joystick* joystick}},
166 		];
167 		ret ~= add;
168 	}
169 	if(sdlSupport >= SDLSupport.v2_0_12){
170 		FnBind[] add = [
171 			{q{SDL_Joystick*}, q{SDL_JoystickFromPlayerIndex}, q{int}},
172 			{q{void}, q{SDL_JoystickSetPlayerIndex}, q{SDL_Joystick* joystick, int}},
173 		];
174 		ret ~= add;
175 	}
176 	if(sdlSupport >= SDLSupport.v2_0_14){
177 		FnBind[] add = [
178 			{q{int}, q{SDL_JoystickAttachVirtual}, q{SDL_JoystickType type, int naxes, int nButtons, int nHats}},
179 			{q{int}, q{SDL_JoystickDetachVirtual}, q{int deviceIndex}},
180 			{q{SDL_bool}, q{SDL_JoystickIsVirtual}, q{int deviceIndex}},
181 			{q{int}, q{SDL_JoystickSetVirtualAxis}, q{SDL_Joystick* joystick, int axis, short value}},
182 			{q{int}, q{SDL_JoystickSetVirtualButton}, q{SDL_Joystick* joystick, int button, ubyte value}},
183 			{q{int}, q{SDL_JoystickSetVirtualHat}, q{SDL_Joystick* joystick, int hat, ubyte value}},
184 			{q{const(char)*}, q{SDL_JoystickGetSerial}, q{SDL_Joystick* joystick}},
185 			{q{int}, q{SDL_JoystickRumbleTriggers}, q{SDL_Joystick* joystick, ushort leftRumble, ushort rightRumble, uint durationMS}},
186 			{q{SDL_bool}, q{SDL_JoystickHasLED}, q{SDL_Joystick* joystick}},
187 			{q{int}, q{SDL_JoystickSetLED}, q{SDL_Joystick* joystick, ubyte red, ubyte green, ubyte blue}},
188 		];
189 		ret ~= add;
190 	}
191 	if(sdlSupport >= SDLSupport.v2_0_16){
192 		FnBind[] add = [
193 			{q{int}, q{SDL_JoystickSendEffect}, q{SDL_Joystick* joystick, const(void)* data, int size}},
194 		];
195 		ret ~= add;
196 	}
197 	if(sdlSupport >= SDLSupport.v2_0_18){
198 		FnBind[] add = [
199 			{q{SDL_bool}, q{SDL_JoystickHasRumble}, q{SDL_Joystick* joystick}},
200 			{q{SDL_bool}, q{SDL_JoystickHasRumbleTriggers}, q{SDL_Joystick* joystick}},
201 		];
202 		ret ~= add;
203 	}
204 	if(sdlSupport >= SDLSupport.v2_24){
205 		FnBind[] add = [
206 			{q{const(char)*}, q{SDL_JoystickPathForIndex}, q{int deviceIndex}},
207 			{q{int}, q{SDL_JoystickAttachVirtualEx}, q{const(SDL_VirtualJoystickDesc)* desc}},
208 			{q{const(char)*}, q{SDL_JoystickPath}, q{SDL_Joystick* joystick}},
209 			{q{ushort}, q{SDL_JoystickGetFirmwareVersion}, q{SDL_Joystick* joystick}},
210 		];
211 		ret ~= add;
212 	}
213 	if(sdlSupport >= SDLSupport.v2_26){
214 		FnBind[] add = [
215 			{q{void}, q{SDL_GetJoystickGUIDInfo}, q{SDL_JoystickGUID guid, ushort* vendor, ushort* product, ushort* version_, ushort* crc16}},
216 		];
217 		ret ~= add;
218 	}
219 	return ret;
220 }()));