Skip to content

Commit 21ca2b0

Browse files
committed
Add Controller.set_led, remove print-on-failure-for-sdl3 for Joystick.set_led, and use pg_RGBAFromObjEx instead of pg_RGBAFromObj
1 parent 6cb9bd9 commit 21ca2b0

File tree

5 files changed

+67
-7
lines changed

5 files changed

+67
-7
lines changed

docs/reST/ref/joystick.rst

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,12 @@ variable. See :ref:`environment variables <environment-variables>` for more deta
361361
| :sl:`Set the LED color of the joystick`
362362
| :sg:`set_led(color_arg) -> bool`
363363
364-
Set the color of the LED on the joystick. The argument is a ``pygame.Color``
365-
instance or a tuple of RGB(A) values (alpha being ignored). The color
366-
will be set to the joystick's LED, if it has one. If the joystick does
367-
not have an LED, then this method will do nothing and return False.
368-
Returns True if the LED was set successfully.
364+
Set the color of the LED on the joystick. The argument is a
365+
``pygame.Color``-compatible value (alpha being ignored). The
366+
joystick's LED, if it has one, will be set to the input color.
367+
If the joystick does not have an addressable LED, then this
368+
method will do nothing and return False. Returns True if the
369+
LED was set successfully.
369370

370371
.. versionadded:: 2.5.6
371372

docs/reST/ref/sdl2_controller.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,4 +288,20 @@ events related to controllers.
288288

289289
.. ## Controller.stop_rumble ##
290290
291+
.. method:: set_led
292+
293+
| :sl:`Set the LED color of the controller`
294+
| :sg:`set_led(color_arg) -> bool`
295+
296+
Set the color of the LED on the controller. The argument is a
297+
``pygame.Color``-compatible value (alpha being ignored). The
298+
controller's LED, if it has one, will be set to the input color.
299+
If the controller does not have an addressable LED, then this
300+
method will do nothing and return False. Returns True if the
301+
LED was set successfully.
302+
303+
.. versionadded:: 2.5.6
304+
305+
.. ## Controller.set_led ##
306+
291307
.. ## pygame._sdl2.controller ##

src_c/_sdl2/controller.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,35 @@ controller_stop_rumble(pgControllerObject *self, PyObject *_null)
388388
Py_RETURN_NONE;
389389
}
390390

391+
static PyObject*
392+
controller_set_led(pgControllerObject *self, PyObject *arg)
393+
{
394+
CONTROLLER_INIT_CHECK();
395+
396+
Uint8 colors[4] = {0, 0, 0, 0};
397+
398+
if (!pg_RGBAFromObjEx(arg, colors, PG_COLOR_HANDLE_ALL)) {
399+
return RAISE(PyExc_TypeError,
400+
"set_led must be passed in a Color-compatible argument");
401+
}
402+
403+
#if !SDL_VERSION_ATLEAST(3, 0, 0)
404+
if (SDL_GameControllerSetLED(self->controller, colors[0], colors[1], colors[2]) < 0) {
405+
Py_RETURN_FALSE;
406+
}
407+
Py_RETURN_TRUE;
408+
#else
409+
// SDL3 renames the function and sets an error message on failure
410+
bool result = SDL_SetGamepadLED(self->controller, colors[0], colors[1], colors[2]);
411+
if (!result) {
412+
// Clear the SDL error message that SDL set, for example if it didn't
413+
// have an addressable LED
414+
(void)SDL_GetError();
415+
}
416+
return PyBool_FromLong(result);
417+
#endif
418+
}
419+
391420
static PyMethodDef controller_methods[] = {
392421
{"from_joystick", (PyCFunction)controller_from_joystick,
393422
METH_CLASS | METH_VARARGS | METH_KEYWORDS,
@@ -414,6 +443,7 @@ static PyMethodDef controller_methods[] = {
414443
DOC_SDL2_CONTROLLER_CONTROLLER_RUMBLE},
415444
{"stop_rumble", (PyCFunction)controller_stop_rumble, METH_NOARGS,
416445
DOC_SDL2_CONTROLLER_CONTROLLER_STOPRUMBLE},
446+
{"set_led", (PyCFunction)controller_set_led, METH_O, DOC_SDL2_CONTROLLER_CONTROLLER_SETLED},
417447
{NULL, NULL, 0, NULL}};
418448

419449
static PyMemberDef controller_members[] = {
@@ -569,6 +599,11 @@ MODINIT_DEFINE(controller)
569599
return NULL;
570600
}
571601

602+
import_pygame_color();
603+
if (PyErr_Occurred()) {
604+
return NULL;
605+
}
606+
572607
import_pygame_joystick();
573608
if (PyErr_Occurred()) {
574609
return NULL;

src_c/doc/sdl2_controller_doc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@
2121
#define DOC_SDL2_CONTROLLER_CONTROLLER_SETMAPPING "set_mapping(mapping) -> int\nAssign a mapping to the controller"
2222
#define DOC_SDL2_CONTROLLER_CONTROLLER_RUMBLE "rumble(low_frequency, high_frequency, duration) -> bool\nStart a rumbling effect"
2323
#define DOC_SDL2_CONTROLLER_CONTROLLER_STOPRUMBLE "stop_rumble() -> None\nStop any rumble effect playing"
24+
#define DOC_SDL2_CONTROLLER_CONTROLLER_SETLED "set_led(color_arg) -> bool\nSet the LED color of the controller"

src_c/joystick.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ joy_set_led(PyObject *self, PyObject *arg)
543543

544544
Uint8 colors[4] = {0, 0, 0, 0};
545545

546-
if (!pg_RGBAFromObj(arg, colors)) {
546+
if (!pg_RGBAFromObjEx(arg, colors, PG_COLOR_HANDLE_ALL)) {
547547
return RAISE(PyExc_TypeError,
548548
"set_led must be passed in a Color-compatible argument");
549549
}
@@ -557,7 +557,9 @@ joy_set_led(PyObject *self, PyObject *arg)
557557
// SDL3 renames the function and sets an error message on failure
558558
bool result = SDL_SetJoystickLED(joy, colors[0], colors[1], colors[2]);
559559
if (!result) {
560-
printf("%s\n", SDL_GetError());
560+
// Clear the SDL error message that SDL set, for example if it didn't
561+
// have an addressable LED
562+
(void)SDL_GetError();
561563
}
562564
return PyBool_FromLong(result);
563565
#endif
@@ -698,6 +700,11 @@ MODINIT_DEFINE(joystick)
698700
return NULL;
699701
}
700702

703+
import_pygame_color();
704+
if (PyErr_Occurred()) {
705+
return NULL;
706+
}
707+
701708
/* type preparation */
702709
if (PyType_Ready(&pgJoystick_Type) == -1) {
703710
return NULL;

0 commit comments

Comments
 (0)