initial add
This commit is contained in:
393
joystick.c
Normal file
393
joystick.c
Normal file
@@ -0,0 +1,393 @@
|
||||
#include "cell.h"
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
// Joystick type enum to string
|
||||
static const char *joystick_type_to_string(SDL_JoystickType type) {
|
||||
switch (type) {
|
||||
case SDL_JOYSTICK_TYPE_GAMEPAD: return "gamepad";
|
||||
case SDL_JOYSTICK_TYPE_WHEEL: return "wheel";
|
||||
case SDL_JOYSTICK_TYPE_ARCADE_STICK: return "arcade_stick";
|
||||
case SDL_JOYSTICK_TYPE_FLIGHT_STICK: return "flight_stick";
|
||||
case SDL_JOYSTICK_TYPE_DANCE_PAD: return "dance_pad";
|
||||
case SDL_JOYSTICK_TYPE_GUITAR: return "guitar";
|
||||
case SDL_JOYSTICK_TYPE_DRUM_KIT: return "drum_kit";
|
||||
case SDL_JOYSTICK_TYPE_ARCADE_PAD: return "arcade_pad";
|
||||
case SDL_JOYSTICK_TYPE_THROTTLE: return "throttle";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
// Connection state to string
|
||||
static const char *connection_state_to_string(SDL_JoystickConnectionState state) {
|
||||
switch (state) {
|
||||
case SDL_JOYSTICK_CONNECTION_WIRED: return "wired";
|
||||
case SDL_JOYSTICK_CONNECTION_WIRELESS: return "wireless";
|
||||
case SDL_JOYSTICK_CONNECTION_UNKNOWN: return "unknown";
|
||||
default: return "invalid";
|
||||
}
|
||||
}
|
||||
|
||||
// SDL_Joystick class
|
||||
void SDL_Joystick_free(JSRuntime *rt, SDL_Joystick *joystick) {
|
||||
if (joystick) SDL_CloseJoystick(joystick);
|
||||
}
|
||||
|
||||
QJSCLASS(SDL_Joystick,)
|
||||
|
||||
// SDL_LockJoysticks()
|
||||
JSC_CCALL(joystick_lock,
|
||||
SDL_LockJoysticks();
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
// SDL_UnlockJoysticks()
|
||||
JSC_CCALL(joystick_unlock,
|
||||
SDL_UnlockJoysticks();
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
// SDL_HasJoystick() -> bool
|
||||
JSC_CCALL(joystick_has,
|
||||
return JS_NewBool(js, SDL_HasJoystick());
|
||||
)
|
||||
|
||||
// SDL_GetJoysticks() -> array of joystick IDs
|
||||
JSC_CCALL(joystick_get_joysticks,
|
||||
int count = 0;
|
||||
SDL_JoystickID *joysticks = SDL_GetJoysticks(&count);
|
||||
if (!joysticks) return JS_NewArray(js);
|
||||
|
||||
JSValue arr = JS_NewArray(js);
|
||||
for (int i = 0; i < count; i++) {
|
||||
JS_SetPropertyUint32(js, arr, i, JS_NewUint32(js, joysticks[i]));
|
||||
}
|
||||
SDL_free(joysticks);
|
||||
return arr;
|
||||
)
|
||||
|
||||
// SDL_GetJoystickNameForID(id) -> string
|
||||
JSC_CCALL(joystick_get_name_for_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
const char *name = SDL_GetJoystickNameForID(id);
|
||||
return name ? JS_NewString(js, name) : JS_NULL;
|
||||
)
|
||||
|
||||
// SDL_GetJoystickPathForID(id) -> string
|
||||
JSC_CCALL(joystick_get_path_for_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
const char *path = SDL_GetJoystickPathForID(id);
|
||||
return path ? JS_NewString(js, path) : JS_NULL;
|
||||
)
|
||||
|
||||
// SDL_GetJoystickPlayerIndexForID(id) -> number
|
||||
JSC_CCALL(joystick_get_player_index_for_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
return JS_NewInt32(js, SDL_GetJoystickPlayerIndexForID(id));
|
||||
)
|
||||
|
||||
// SDL_GetJoystickGUIDForID(id) -> string
|
||||
JSC_CCALL(joystick_get_guid_for_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
SDL_GUID guid = SDL_GetJoystickGUIDForID(id);
|
||||
char buf[64];
|
||||
SDL_GUIDToString(guid, buf, sizeof(buf));
|
||||
return JS_NewString(js, buf);
|
||||
)
|
||||
|
||||
// SDL_GetJoystickVendorForID(id) -> number
|
||||
JSC_CCALL(joystick_get_vendor_for_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
return JS_NewUint32(js, SDL_GetJoystickVendorForID(id));
|
||||
)
|
||||
|
||||
// SDL_GetJoystickProductForID(id) -> number
|
||||
JSC_CCALL(joystick_get_product_for_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
return JS_NewUint32(js, SDL_GetJoystickProductForID(id));
|
||||
)
|
||||
|
||||
// SDL_GetJoystickProductVersionForID(id) -> number
|
||||
JSC_CCALL(joystick_get_product_version_for_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
return JS_NewUint32(js, SDL_GetJoystickProductVersionForID(id));
|
||||
)
|
||||
|
||||
// SDL_GetJoystickTypeForID(id) -> string
|
||||
JSC_CCALL(joystick_get_type_for_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
SDL_JoystickType type = SDL_GetJoystickTypeForID(id);
|
||||
return JS_NewString(js, joystick_type_to_string(type));
|
||||
)
|
||||
|
||||
// SDL_OpenJoystick(id) -> Joystick object
|
||||
JSC_CCALL(joystick_open,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
SDL_Joystick *joystick = SDL_OpenJoystick(id);
|
||||
if (!joystick) return JS_NULL;
|
||||
return SDL_Joystick2js(js, joystick);
|
||||
)
|
||||
|
||||
// SDL_GetJoystickFromID(id) -> Joystick object (does not take ownership)
|
||||
JSC_CCALL(joystick_get_from_id,
|
||||
uint32_t id;
|
||||
JS_ToUint32(js, &id, argv[0]);
|
||||
SDL_Joystick *joystick = SDL_GetJoystickFromID(id);
|
||||
if (!joystick) return JS_NULL;
|
||||
// Note: This returns an existing joystick, not a new one
|
||||
// We should not free it when the JS object is garbage collected
|
||||
return SDL_Joystick2js(js, joystick);
|
||||
)
|
||||
|
||||
// SDL_GetJoystickFromPlayerIndex(player_index) -> Joystick object
|
||||
JSC_CCALL(joystick_get_from_player_index,
|
||||
int player_index;
|
||||
JS_ToInt32(js, &player_index, argv[0]);
|
||||
SDL_Joystick *joystick = SDL_GetJoystickFromPlayerIndex(player_index);
|
||||
if (!joystick) return JS_NULL;
|
||||
return SDL_Joystick2js(js, joystick);
|
||||
)
|
||||
|
||||
// Joystick instance methods
|
||||
JSC_CCALL(joystick_get_name,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
const char *name = SDL_GetJoystickName(joystick);
|
||||
return name ? JS_NewString(js, name) : JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_path,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
const char *path = SDL_GetJoystickPath(joystick);
|
||||
return path ? JS_NewString(js, path) : JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_player_index,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewInt32(js, SDL_GetJoystickPlayerIndex(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_set_player_index,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
int player_index;
|
||||
JS_ToInt32(js, &player_index, argv[0]);
|
||||
return JS_NewBool(js, SDL_SetJoystickPlayerIndex(joystick, player_index));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_guid,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
SDL_GUID guid = SDL_GetJoystickGUID(joystick);
|
||||
char buf[64];
|
||||
SDL_GUIDToString(guid, buf, sizeof(buf));
|
||||
return JS_NewString(js, buf);
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_vendor,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewUint32(js, SDL_GetJoystickVendor(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_product,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewUint32(js, SDL_GetJoystickProduct(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_product_version,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewUint32(js, SDL_GetJoystickProductVersion(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_serial,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
const char *serial = SDL_GetJoystickSerial(joystick);
|
||||
return serial ? JS_NewString(js, serial) : JS_NULL;
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_type,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
SDL_JoystickType type = SDL_GetJoystickType(joystick);
|
||||
return JS_NewString(js, joystick_type_to_string(type));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_id,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewUint32(js, SDL_GetJoystickID(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_num_axes,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewInt32(js, SDL_GetNumJoystickAxes(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_num_balls,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewInt32(js, SDL_GetNumJoystickBalls(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_num_hats,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewInt32(js, SDL_GetNumJoystickHats(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_num_buttons,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
return JS_NewInt32(js, SDL_GetNumJoystickButtons(joystick));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_axis,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
int axis;
|
||||
JS_ToInt32(js, &axis, argv[0]);
|
||||
return JS_NewInt32(js, SDL_GetJoystickAxis(joystick, axis));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_ball,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
int ball;
|
||||
JS_ToInt32(js, &ball, argv[0]);
|
||||
int dx, dy;
|
||||
if (!SDL_GetJoystickBall(joystick, ball, &dx, &dy)) return JS_NULL;
|
||||
JSValue result = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, result, "dx", JS_NewInt32(js, dx));
|
||||
JS_SetPropertyStr(js, result, "dy", JS_NewInt32(js, dy));
|
||||
return result;
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_hat,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
int hat;
|
||||
JS_ToInt32(js, &hat, argv[0]);
|
||||
return JS_NewUint32(js, SDL_GetJoystickHat(joystick, hat));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_button,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
int button;
|
||||
JS_ToInt32(js, &button, argv[0]);
|
||||
return JS_NewBool(js, SDL_GetJoystickButton(joystick, button));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_rumble,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
uint32_t low_freq, high_freq, duration_ms;
|
||||
JS_ToUint32(js, &low_freq, argv[0]);
|
||||
JS_ToUint32(js, &high_freq, argv[1]);
|
||||
JS_ToUint32(js, &duration_ms, argv[2]);
|
||||
return JS_NewBool(js, SDL_RumbleJoystick(joystick, low_freq, high_freq, duration_ms));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_rumble_triggers,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
uint32_t left, right, duration_ms;
|
||||
JS_ToUint32(js, &left, argv[0]);
|
||||
JS_ToUint32(js, &right, argv[1]);
|
||||
JS_ToUint32(js, &duration_ms, argv[2]);
|
||||
return JS_NewBool(js, SDL_RumbleJoystickTriggers(joystick, left, right, duration_ms));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_set_led,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
int r, g, b;
|
||||
JS_ToInt32(js, &r, argv[0]);
|
||||
JS_ToInt32(js, &g, argv[1]);
|
||||
JS_ToInt32(js, &b, argv[2]);
|
||||
return JS_NewBool(js, SDL_SetJoystickLED(joystick, r, g, b));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_connection_state,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
SDL_JoystickConnectionState state = SDL_GetJoystickConnectionState(joystick);
|
||||
return JS_NewString(js, connection_state_to_string(state));
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_get_power_info,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
int percent;
|
||||
SDL_PowerState state = SDL_GetJoystickPowerInfo(joystick, &percent);
|
||||
|
||||
JSValue result = JS_NewObject(js);
|
||||
const char *state_str;
|
||||
switch (state) {
|
||||
case SDL_POWERSTATE_ON_BATTERY: state_str = "on_battery"; break;
|
||||
case SDL_POWERSTATE_NO_BATTERY: state_str = "no_battery"; break;
|
||||
case SDL_POWERSTATE_CHARGING: state_str = "charging"; break;
|
||||
case SDL_POWERSTATE_CHARGED: state_str = "charged"; break;
|
||||
default: state_str = "unknown"; break;
|
||||
}
|
||||
JS_SetPropertyStr(js, result, "state", JS_NewString(js, state_str));
|
||||
JS_SetPropertyStr(js, result, "percent", JS_NewInt32(js, percent));
|
||||
return result;
|
||||
)
|
||||
|
||||
JSC_CCALL(joystick_close,
|
||||
SDL_Joystick *joystick = js2SDL_Joystick(js, self);
|
||||
SDL_CloseJoystick(joystick);
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_SDL_Joystick_funcs[] = {
|
||||
MIST_FUNC_DEF(joystick, get_name, 0),
|
||||
MIST_FUNC_DEF(joystick, get_path, 0),
|
||||
MIST_FUNC_DEF(joystick, get_player_index, 0),
|
||||
MIST_FUNC_DEF(joystick, set_player_index, 1),
|
||||
MIST_FUNC_DEF(joystick, get_guid, 0),
|
||||
MIST_FUNC_DEF(joystick, get_vendor, 0),
|
||||
MIST_FUNC_DEF(joystick, get_product, 0),
|
||||
MIST_FUNC_DEF(joystick, get_product_version, 0),
|
||||
MIST_FUNC_DEF(joystick, get_serial, 0),
|
||||
MIST_FUNC_DEF(joystick, get_type, 0),
|
||||
MIST_FUNC_DEF(joystick, get_id, 0),
|
||||
MIST_FUNC_DEF(joystick, get_num_axes, 0),
|
||||
MIST_FUNC_DEF(joystick, get_num_balls, 0),
|
||||
MIST_FUNC_DEF(joystick, get_num_hats, 0),
|
||||
MIST_FUNC_DEF(joystick, get_num_buttons, 0),
|
||||
MIST_FUNC_DEF(joystick, get_axis, 1),
|
||||
MIST_FUNC_DEF(joystick, get_ball, 1),
|
||||
MIST_FUNC_DEF(joystick, get_hat, 1),
|
||||
MIST_FUNC_DEF(joystick, get_button, 1),
|
||||
MIST_FUNC_DEF(joystick, rumble, 3),
|
||||
MIST_FUNC_DEF(joystick, rumble_triggers, 3),
|
||||
MIST_FUNC_DEF(joystick, set_led, 3),
|
||||
MIST_FUNC_DEF(joystick, get_connection_state, 0),
|
||||
MIST_FUNC_DEF(joystick, get_power_info, 0),
|
||||
MIST_FUNC_DEF(joystick, close, 0),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_joystick_funcs[] = {
|
||||
MIST_FUNC_DEF(joystick, lock, 0),
|
||||
MIST_FUNC_DEF(joystick, unlock, 0),
|
||||
MIST_FUNC_DEF(joystick, has, 0),
|
||||
MIST_FUNC_DEF(joystick, get_joysticks, 0),
|
||||
MIST_FUNC_DEF(joystick, get_name_for_id, 1),
|
||||
MIST_FUNC_DEF(joystick, get_path_for_id, 1),
|
||||
MIST_FUNC_DEF(joystick, get_player_index_for_id, 1),
|
||||
MIST_FUNC_DEF(joystick, get_guid_for_id, 1),
|
||||
MIST_FUNC_DEF(joystick, get_vendor_for_id, 1),
|
||||
MIST_FUNC_DEF(joystick, get_product_for_id, 1),
|
||||
MIST_FUNC_DEF(joystick, get_product_version_for_id, 1),
|
||||
MIST_FUNC_DEF(joystick, get_type_for_id, 1),
|
||||
MIST_FUNC_DEF(joystick, open, 1),
|
||||
MIST_FUNC_DEF(joystick, get_from_id, 1),
|
||||
MIST_FUNC_DEF(joystick, get_from_player_index, 1),
|
||||
};
|
||||
|
||||
CELL_USE_INIT(
|
||||
SDL_Init(SDL_INIT_JOYSTICK);
|
||||
QJSCLASSPREP_FUNCS(SDL_Joystick);
|
||||
|
||||
JSValue ret = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js, ret, js_joystick_funcs, countof(js_joystick_funcs));
|
||||
|
||||
// Export axis constants
|
||||
JS_SetPropertyStr(js, ret, "AXIS_MAX", JS_NewInt32(js, SDL_JOYSTICK_AXIS_MAX));
|
||||
JS_SetPropertyStr(js, ret, "AXIS_MIN", JS_NewInt32(js, SDL_JOYSTICK_AXIS_MIN));
|
||||
|
||||
return ret;
|
||||
)
|
||||
Reference in New Issue
Block a user