HeadsetRGBColor: use shared special_keys.COLORS palette
Drop the ad-hoc 10-color preset list and feed special_keys.COLORS (the Xorg rgb.txt palette solaar already uses for DPI button color mapping) directly as the ChoicesValidator choices_universe. Users now pick from the same named colors other parts of the app expose, and we stop inventing a one-off naming scheme. "Off" goes away as a color option — to disable host control, toggle the separate headset-rgb-hostmode setting instead. Picking `black` writes (0,0,0) which effectively turns the LEDs off while host mode stays claimed. This still isn't the "ideal" solaar pattern (Kind.COLOR with Gtk.ColorButton via HeteroValidator), but it reuses existing infrastructure — ChoicesValidator + NamedInts — instead of creating new patterns just for this setting.
This commit is contained in:
parent
059874c210
commit
b90bbf8af3
|
|
@ -1783,38 +1783,24 @@ class HeadsetRGBHostMode(settings.Setting):
|
|||
validator_class = settings_validator.BooleanValidator
|
||||
|
||||
|
||||
# Preset RGB colors for headset-rgb-color. Name → (R, G, B).
|
||||
# "Off" disables host mode and returns control to firmware.
|
||||
_HEADSET_RGB_COLORS = [
|
||||
("Off", None),
|
||||
("Red", (0xFF, 0x00, 0x00)),
|
||||
("Green", (0x00, 0xFF, 0x00)),
|
||||
("Blue", (0x00, 0x00, 0xFF)),
|
||||
("White", (0xFF, 0xFF, 0xFF)),
|
||||
("Yellow", (0xFF, 0xFF, 0x00)),
|
||||
("Cyan", (0x00, 0xFF, 0xFF)),
|
||||
("Magenta", (0xFF, 0x00, 0xFF)),
|
||||
("Orange", (0xFF, 0x80, 0x00)),
|
||||
("Purple", (0x80, 0x00, 0xFF)),
|
||||
]
|
||||
|
||||
|
||||
class HeadsetRGBColor(settings.Setting):
|
||||
"""Set headset RGB zones to a preset color.
|
||||
"""Pick a color from the shared `special_keys.COLORS` palette and apply it
|
||||
to all headset RGB zones via HeadsetRGBHostmode (0x0620).
|
||||
|
||||
Drives HeadsetRGBHostmode (0x0620). On write, enables host mode, queries
|
||||
available zones, sets them all to the chosen RGB color, and commits via
|
||||
FrameEnd. "Off" disables host mode to return control to firmware.
|
||||
On write: enables host mode, queries zone IDs via GetRGBZoneInfo, sets
|
||||
them all to the chosen RGB color via SetRgbZonesSingleValue, commits via
|
||||
FrameEnd. Picking `black` effectively turns the LEDs off; fully disabling
|
||||
host control is done through the separate headset-rgb-hostmode toggle.
|
||||
"""
|
||||
|
||||
name = "headset-rgb-color"
|
||||
label = _("Headset RGB Color")
|
||||
description = _("Set headset LED color (zones set to a single preset).")
|
||||
description = _("Set headset LED color (all zones, from the shared color palette).")
|
||||
feature = _F.HEADSET_RGB_HOSTMODE
|
||||
choices_universe = common.NamedInts(**{name: idx for idx, (name, _rgb) in enumerate(_HEADSET_RGB_COLORS)})
|
||||
choices_universe = special_keys.COLORS
|
||||
validator_class = settings_validator.ChoicesValidator
|
||||
persist = True
|
||||
# Write-only: we don't read back the current color (host mode just reports on/off).
|
||||
# Write-only: we don't read back the current color (0x0620 doesn't expose it).
|
||||
rw_options = {"read_fnid": None, "write_fnid": None}
|
||||
|
||||
@classmethod
|
||||
|
|
@ -1832,49 +1818,48 @@ class HeadsetRGBColor(settings.Setting):
|
|||
def write(self, value, save=True):
|
||||
if value is None:
|
||||
return None
|
||||
idx = int(value)
|
||||
if not (0 <= idx < len(_HEADSET_RGB_COLORS)):
|
||||
try:
|
||||
color_int = int(value)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
name, rgb = _HEADSET_RGB_COLORS[idx]
|
||||
if color_int not in special_keys.COLORS:
|
||||
return None
|
||||
name = str(special_keys.COLORS[color_int])
|
||||
r = (color_int >> 16) & 0xFF
|
||||
g = (color_int >> 8) & 0xFF
|
||||
b = color_int & 0xFF
|
||||
device = self._device
|
||||
if not device.online:
|
||||
logger.info("HeadsetRGBColor: device offline, skipping write of %s", name)
|
||||
return None
|
||||
try:
|
||||
if rgb is None:
|
||||
# "Off" → disable host mode, return to firmware control.
|
||||
logger.info("HeadsetRGBColor: disabling host mode (SetHostModeState 0x00)")
|
||||
resp = device.feature_request(_F.HEADSET_RGB_HOSTMODE, 0x80, b"\x00")
|
||||
logger.info("HeadsetRGBColor: SetHostModeState resp=%s", resp.hex() if resp else resp)
|
||||
else:
|
||||
zone_ids = self._zone_ids(device)
|
||||
if not zone_ids:
|
||||
logger.warning("HeadsetRGBColor: no zones available; cannot set color %s", name)
|
||||
return None
|
||||
r, g, b = rgb
|
||||
logger.info(
|
||||
"HeadsetRGBColor: setting color %s RGB=(%02X,%02X,%02X) on %d zone(s): %s",
|
||||
name,
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
len(zone_ids),
|
||||
[f"0x{z:02X}" for z in zone_ids],
|
||||
)
|
||||
# Enable host mode first.
|
||||
resp = device.feature_request(_F.HEADSET_RGB_HOSTMODE, 0x80, b"\x01")
|
||||
logger.info("HeadsetRGBColor: SetHostModeState(1) resp=%s", resp.hex() if resp else resp)
|
||||
# SetRgbZonesSingleValue: [R, G, B, count, zone_ids...]
|
||||
payload = bytes([r, g, b, len(zone_ids)]) + bytes(zone_ids)
|
||||
resp = device.feature_request(_F.HEADSET_RGB_HOSTMODE, 0x50, payload)
|
||||
logger.info(
|
||||
"HeadsetRGBColor: SetRgbZonesSingleValue payload=%s resp=%s",
|
||||
payload.hex(),
|
||||
resp.hex() if resp else resp,
|
||||
)
|
||||
# FrameEnd: commit the frame.
|
||||
resp = device.feature_request(_F.HEADSET_RGB_HOSTMODE, 0x60, b"\x00\x00\x00\x00")
|
||||
logger.info("HeadsetRGBColor: FrameEnd resp=%s", resp.hex() if resp else resp)
|
||||
zone_ids = self._zone_ids(device)
|
||||
if not zone_ids:
|
||||
logger.warning("HeadsetRGBColor: no zones available; cannot set color %s", name)
|
||||
return None
|
||||
logger.info(
|
||||
"HeadsetRGBColor: setting color %s RGB=(%02X,%02X,%02X) on %d zone(s): %s",
|
||||
name,
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
len(zone_ids),
|
||||
[f"0x{z:02X}" for z in zone_ids],
|
||||
)
|
||||
# Enable host mode first.
|
||||
resp = device.feature_request(_F.HEADSET_RGB_HOSTMODE, 0x80, b"\x01")
|
||||
logger.info("HeadsetRGBColor: SetHostModeState(1) resp=%s", resp.hex() if resp else resp)
|
||||
# SetRgbZonesSingleValue: [R, G, B, count, zone_ids...]
|
||||
payload = bytes([r, g, b, len(zone_ids)]) + bytes(zone_ids)
|
||||
resp = device.feature_request(_F.HEADSET_RGB_HOSTMODE, 0x50, payload)
|
||||
logger.info(
|
||||
"HeadsetRGBColor: SetRgbZonesSingleValue payload=%s resp=%s",
|
||||
payload.hex(),
|
||||
resp.hex() if resp else resp,
|
||||
)
|
||||
# FrameEnd: commit the frame.
|
||||
resp = device.feature_request(_F.HEADSET_RGB_HOSTMODE, 0x60, b"\x00\x00\x00\x00")
|
||||
logger.info("HeadsetRGBColor: FrameEnd resp=%s", resp.hex() if resp else resp)
|
||||
except Exception as e:
|
||||
logger.warning("HeadsetRGBColor write failed for %s: %s", name, e)
|
||||
return None
|
||||
|
|
|
|||
Loading…
Reference in New Issue