1 #include "allegro5/allegro.h"
2 #include "allegro5/internal/aintern.h"
3 #include "allegro5/internal/aintern_events.h"
4 #include "allegro5/internal/aintern_joystick.h"
5 #include "allegro5/internal/aintern_android.h"
6
7 ALLEGRO_DEBUG_CHANNEL("android")
8
9 typedef struct ALLEGRO_JOYSTICK_ANDROID {
10 ALLEGRO_JOYSTICK parent;
11 ALLEGRO_JOYSTICK_STATE joystate;
12 const char *name;
13 } ALLEGRO_JOYSTICK_ANDROID;
14
15 static _AL_VECTOR joysticks = _AL_VECTOR_INITIALIZER(ALLEGRO_JOYSTICK_ANDROID *);
16 static bool initialized;
17
android_init_joysticks(int num)18 static void android_init_joysticks(int num)
19 {
20 int i, j;
21
22 for (i = 0; i < num; i++) {
23 ALLEGRO_JOYSTICK_ANDROID *stick = al_calloc(1, sizeof(ALLEGRO_JOYSTICK_ANDROID));
24 ALLEGRO_JOYSTICK_ANDROID **ptr;
25 ALLEGRO_JOYSTICK *joy;
26
27 joy = (void *)stick;
28 stick->name = "Android Joystick";
29
30 /* Fill in the joystick information fields. */
31 joy->info.num_sticks = 2;
32 joy->info.num_buttons = 11;
33 joy->info.stick[0].name = "Stick 1";
34 joy->info.stick[0].num_axes = 2;
35 joy->info.stick[0].axis[0].name = "X";
36 joy->info.stick[0].axis[1].name = "Y";
37 joy->info.stick[0].flags = ALLEGRO_JOYFLAG_ANALOGUE;
38 joy->info.stick[1].name = "Stick 2";
39 joy->info.stick[1].num_axes = 2;
40 joy->info.stick[1].axis[0].name = "X";
41 joy->info.stick[1].axis[1].name = "Y";
42 joy->info.stick[1].flags = ALLEGRO_JOYFLAG_ANALOGUE;
43
44 for (j = 0; j < joy->info.num_buttons; j++) {
45 joy->info.button[j].name = "";
46 }
47
48 ptr = _al_vector_alloc_back(&joysticks);
49 *ptr = stick;
50 }
51 }
52
andjoy_init_joystick(void)53 static bool andjoy_init_joystick(void)
54 {
55 ALLEGRO_JOYSTICK_ANDROID *accel = al_calloc(1, sizeof(ALLEGRO_JOYSTICK_ANDROID));
56 ALLEGRO_JOYSTICK_ANDROID **ptr;
57 ALLEGRO_JOYSTICK *joy;
58 int num;
59
60 accel->name = "Accelerometer";
61
62 joy = (void *)accel;
63
64 /* Fill in the joystick information fields. */
65 joy->info.num_sticks = 1;
66 joy->info.num_buttons = 0;
67 joy->info.stick[0].name = "Accelerometer";
68 joy->info.stick[0].num_axes = 3;
69 joy->info.stick[0].axis[0].name = "X";
70 joy->info.stick[0].axis[1].name = "Y";
71 joy->info.stick[0].axis[2].name = "Z";
72 joy->info.stick[0].flags = ALLEGRO_JOYFLAG_ANALOGUE;
73
74 ptr = _al_vector_alloc_back(&joysticks);
75 *ptr = accel;
76
77 num = _jni_callIntMethodV(_al_android_get_jnienv(), _al_android_activity_object(), "getNumJoysticks", "()I");
78
79 android_init_joysticks(num);
80
81 initialized = true;
82
83 _jni_callVoidMethod(_al_android_get_jnienv(), _al_android_activity_object(), "setJoystickActive");
84
85 return true;
86 }
87
andjoy_exit_joystick(void)88 static void andjoy_exit_joystick(void)
89 {
90 initialized = false;
91 }
92
andjoy_reconfigure_joysticks(void)93 static bool andjoy_reconfigure_joysticks(void)
94 {
95 int i;
96 int sz;
97 int num;
98
99 sz = _al_vector_size(&joysticks);
100
101 for (i = 1; i < sz; i++) {
102 al_free(*((ALLEGRO_JOYSTICK_ANDROID **)_al_vector_ref(&joysticks, 1)));
103 _al_vector_delete_at(&joysticks, 1);
104 }
105
106 _jni_callVoidMethod(_al_android_get_jnienv(), _al_android_activity_object(), "reconfigureJoysticks");
107
108 num = _jni_callIntMethodV(_al_android_get_jnienv(), _al_android_activity_object(), "getNumJoysticks", "()I");
109
110 android_init_joysticks(num);
111
112 return true;
113 }
114
andjoy_num_joysticks(void)115 static int andjoy_num_joysticks(void)
116 {
117 return _al_vector_size(&joysticks);
118 }
119
andjoy_get_joystick(int num)120 static ALLEGRO_JOYSTICK *andjoy_get_joystick(int num)
121 {
122 ALLEGRO_JOYSTICK_ANDROID *andjoy;
123 ALLEGRO_JOYSTICK *joy;
124
125 if (num >= andjoy_num_joysticks())
126 return NULL;
127
128 andjoy = *((ALLEGRO_JOYSTICK_ANDROID **)_al_vector_ref(&joysticks, num));
129 joy = &andjoy->parent;
130
131 return joy;
132 }
133
andjoy_release_joystick(ALLEGRO_JOYSTICK * joy)134 static void andjoy_release_joystick(ALLEGRO_JOYSTICK *joy)
135 {
136 int i;
137 int sz;
138 (void)joy;
139
140 sz = _al_vector_size(&joysticks);
141
142 for (i = 0; i < sz; i++) {
143 al_free(*((ALLEGRO_JOYSTICK_ANDROID **)_al_vector_ref(&joysticks, 0)));
144 _al_vector_delete_at(&joysticks, 0);
145 }
146
147 _jni_callVoidMethod(_al_android_get_jnienv(), _al_android_activity_object(), "setJoystickInactive");
148
149 ALLEGRO_DEBUG("Joystick released.\n");
150 initialized = false;
151 }
152
andjoy_get_joystick_state(ALLEGRO_JOYSTICK * joy,ALLEGRO_JOYSTICK_STATE * ret_state)153 static void andjoy_get_joystick_state(ALLEGRO_JOYSTICK *joy, ALLEGRO_JOYSTICK_STATE *ret_state)
154 {
155 ALLEGRO_JOYSTICK_ANDROID *andjoy = (void *)joy;
156 ALLEGRO_EVENT_SOURCE *es = al_get_joystick_event_source();
157 int i;
158 bool found = false;
159
160 for (i = 0; i < (int)_al_vector_size(&joysticks); i++) {
161 ALLEGRO_JOYSTICK_ANDROID **ptr = _al_vector_ref(&joysticks, i);
162 ALLEGRO_JOYSTICK_ANDROID *thisjoy = *ptr;
163 if (andjoy == thisjoy) {
164 found = true;
165 break;
166 }
167 }
168
169 if (!found) {
170 memset(ret_state, 0, sizeof(*ret_state));
171 return;
172 }
173
174 _al_event_source_lock(es);
175 *ret_state = andjoy->joystate;
176 _al_event_source_unlock(es);
177 }
178
_al_android_generate_accelerometer_event(float x,float y,float z)179 void _al_android_generate_accelerometer_event(float x, float y, float z)
180 {
181 if (!initialized)
182 return;
183
184 /* Android reports accelerometer data in the approximate range
185 * -9.81 -> 9.81, but can be higher or lower. Allegro joysticks
186 * use -1 -> 1. Also, the axis' are all reversed on Android,
187 * hence the negative division.
188 */
189 x /= -9.81f;
190 if (x < -1) x = -1;
191 if (x > 1) x = 1;
192 y /= -9.81f;
193 if (y < -1) y = -1;
194 if (y > 1) y = 1;
195 z /= -9.81f;
196 if (z < -1) z = -1;
197 if (z > 1) z = 1;
198
199 ALLEGRO_JOYSTICK_ANDROID *accel = *((ALLEGRO_JOYSTICK_ANDROID **)_al_vector_ref(&joysticks, 0));
200 ALLEGRO_JOYSTICK *joy = &accel->parent;
201
202 ALLEGRO_EVENT_SOURCE *es = al_get_joystick_event_source();
203
204 ALLEGRO_EVENT event;
205
206 _al_event_source_lock(es);
207
208 if (_al_event_source_needs_to_generate_event(es)) {
209 float pos[] = {x, y, z};
210 int i;
211 for (i = 0; i < 3; i++) {
212 event.joystick.id = joy;
213 event.joystick.type = ALLEGRO_EVENT_JOYSTICK_AXIS;
214 event.joystick.timestamp = al_get_time();
215 event.joystick.stick = 0;
216 event.joystick.axis = i;
217 event.joystick.pos = pos[i];
218 event.joystick.button = 0;
219
220 accel->joystate.stick[0].axis[i] = pos[i];
221
222 _al_event_source_emit_event(es, &event);
223 }
224 }
225
226 _al_event_source_unlock(es);
227 }
228
_al_android_generate_joystick_axis_event(int index,int stick,int axis,float value)229 void _al_android_generate_joystick_axis_event(int index, int stick, int axis, float value)
230 {
231 if (!initialized || index >= andjoy_num_joysticks())
232 return;
233
234 ALLEGRO_JOYSTICK_ANDROID *joystick = *((ALLEGRO_JOYSTICK_ANDROID **)_al_vector_ref(&joysticks, index));
235 ALLEGRO_JOYSTICK *joy = &joystick->parent;
236
237 ALLEGRO_EVENT_SOURCE *es = al_get_joystick_event_source();
238
239 ALLEGRO_EVENT event;
240
241 _al_event_source_lock(es);
242
243 if (_al_event_source_needs_to_generate_event(es)) {
244 event.joystick.id = joy;
245 event.joystick.type = ALLEGRO_EVENT_JOYSTICK_AXIS;
246 event.joystick.timestamp = al_get_time();
247 event.joystick.stick = stick;
248 event.joystick.axis = axis;
249 event.joystick.pos = value;
250 event.joystick.button = 0;
251
252 joystick->joystate.stick[stick].axis[axis] = value;
253
254 _al_event_source_emit_event(es, &event);
255 }
256 _al_event_source_unlock(es);
257 }
258
_al_android_generate_joystick_button_event(int index,int button,bool down)259 void _al_android_generate_joystick_button_event(int index, int button, bool down)
260 {
261 int type;
262
263 if (!initialized || index >= andjoy_num_joysticks())
264 return;
265
266 ALLEGRO_JOYSTICK_ANDROID *joystick = *((ALLEGRO_JOYSTICK_ANDROID **)_al_vector_ref(&joysticks, index));
267 ALLEGRO_JOYSTICK *joy = &joystick->parent;
268
269 ALLEGRO_EVENT_SOURCE *es = al_get_joystick_event_source();
270
271 ALLEGRO_EVENT event;
272
273 _al_event_source_lock(es);
274
275 if (down)
276 type = ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN;
277 else
278 type = ALLEGRO_EVENT_JOYSTICK_BUTTON_UP;
279
280 if (_al_event_source_needs_to_generate_event(es)) {
281 event.joystick.id = joy;
282 event.joystick.type = type;
283 event.joystick.timestamp = al_get_time();
284 event.joystick.stick = 0;
285 event.joystick.axis = 0;
286 event.joystick.pos = 0;
287 event.joystick.button = button;
288
289 joystick->joystate.button[button] = type == ALLEGRO_EVENT_JOYSTICK_BUTTON_DOWN ? 1 : 0;
290
291 _al_event_source_emit_event(es, &event);
292 }
293 _al_event_source_unlock(es);
294 }
295
andjoy_get_name(ALLEGRO_JOYSTICK * joy)296 static char const *andjoy_get_name(ALLEGRO_JOYSTICK *joy)
297 {
298 int i;
299 (void)joy;
300
301 for (i = 0; i < (int)_al_vector_size(&joysticks); i++) {
302 ALLEGRO_JOYSTICK_ANDROID *andjoy = *((ALLEGRO_JOYSTICK_ANDROID **)_al_vector_ref(&joysticks, i));
303 if ((ALLEGRO_JOYSTICK *)andjoy == joy)
304 return andjoy->name;
305 }
306
307 return "";
308 }
309
andjoy_get_active(ALLEGRO_JOYSTICK * joy)310 static bool andjoy_get_active(ALLEGRO_JOYSTICK *joy)
311 {
312 (void)joy;
313 return true;
314 }
315
316 ALLEGRO_JOYSTICK_DRIVER _al_android_joystick_driver = {
317 AL_ID('A', 'N', 'D', 'R'),
318 "",
319 "",
320 "android joystick",
321 andjoy_init_joystick,
322 andjoy_exit_joystick,
323 andjoy_reconfigure_joysticks,
324 andjoy_num_joysticks,
325 andjoy_get_joystick,
326 andjoy_release_joystick,
327 andjoy_get_joystick_state,
328 andjoy_get_name,
329 andjoy_get_active
330 };
331