rgb.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. intdevice "netdome.biz/paul/impact-80/internal/device"
  6. intrgb "netdome.biz/paul/impact-80/internal/rgb"
  7. "netdome.biz/paul/impact-80/internal/via"
  8. )
  9. type zoneProtocol interface {
  10. SetValue(via.LEDType, uint8, uint8) error
  11. SetColor(via.LEDType, uint8, uint8) error
  12. }
  13. type rgbProtocol interface {
  14. zoneProtocol
  15. GetValue(via.LEDType, uint8) ([]byte, error)
  16. Close() error
  17. }
  18. var openRGBProtocol = func() (rgbProtocol, error) {
  19. proto, _, err := OpenDevice()
  20. if err != nil {
  21. return nil, err
  22. }
  23. return proto, nil
  24. }
  25. func forEachSelectedZone(zones []intrgb.Zone, fn func(intrgb.Zone, via.LEDType) error) error {
  26. channels := zoneChannels(zones)
  27. for i, zone := range zones {
  28. if err := fn(zone, channels[i]); err != nil {
  29. return err
  30. }
  31. }
  32. return nil
  33. }
  34. func setValueOnZones(proto zoneProtocol, zones []intrgb.Zone, param, value uint8) error {
  35. return forEachSelectedZone(zones, func(_ intrgb.Zone, channel via.LEDType) error {
  36. return proto.SetValue(channel, param, value)
  37. })
  38. }
  39. func setBrightnessOnZones(proto zoneProtocol, zones []intrgb.Zone, value uint8) error {
  40. return setValueOnZones(proto, zones, uint8(intrgb.Brightness), value)
  41. }
  42. func setSpeedOnZones(proto zoneProtocol, zones []intrgb.Zone, value uint8) error {
  43. return setValueOnZones(proto, zones, uint8(intrgb.Speed), value)
  44. }
  45. func setColorOnZones(proto zoneProtocol, zones []intrgb.Zone, hue, saturation uint8) error {
  46. return forEachSelectedZone(zones, func(_ intrgb.Zone, channel via.LEDType) error {
  47. return proto.SetColor(channel, hue, saturation)
  48. })
  49. }
  50. func disableLightingOnZones(proto zoneProtocol, zones []intrgb.Zone) error {
  51. return forEachSelectedZone(zones, func(_ intrgb.Zone, channel via.LEDType) error {
  52. if err := proto.SetValue(channel, uint8(intrgb.EffectID), 0); err != nil {
  53. return err
  54. }
  55. return proto.SetValue(channel, uint8(intrgb.Brightness), 0)
  56. })
  57. }
  58. func enableLightingOnZones(proto zoneProtocol, zones []intrgb.Zone) error {
  59. return forEachSelectedZone(zones, func(zone intrgb.Zone, channel via.LEDType) error {
  60. if err := proto.SetValue(channel, uint8(intrgb.EffectID), intrgb.DefaultEffect(zone)); err != nil {
  61. return err
  62. }
  63. return proto.SetValue(channel, uint8(intrgb.Brightness), 160)
  64. })
  65. }
  66. func setModeOnZones(proto zoneProtocol, zones []intrgb.Zone, value uint8) error {
  67. return setValueOnZones(proto, zones, uint8(intrgb.EffectID), value)
  68. }
  69. func OpenDevice() (*via.Protocol, intdevice.Keyboard, error) {
  70. if _, err := selectedZones(); err != nil {
  71. return nil, intdevice.Keyboard{}, err
  72. }
  73. keyboards, err := intdevice.LoadKeyboards()
  74. if err != nil {
  75. return nil, intdevice.Keyboard{}, fmt.Errorf("load keyboards: %w", err)
  76. }
  77. devices, err := intdevice.Discover(keyboards)
  78. if err != nil {
  79. return nil, intdevice.Keyboard{}, fmt.Errorf("discover: %w", err)
  80. }
  81. if len(devices) == 0 {
  82. return nil, intdevice.Keyboard{}, fmt.Errorf("no VIA-compatible keyboard found")
  83. }
  84. var dev intdevice.Device
  85. if targetDevice != "" {
  86. for _, d := range devices {
  87. if d.Path == targetDevice {
  88. dev = d
  89. break
  90. }
  91. }
  92. if dev.Path == "" {
  93. return nil, intdevice.Keyboard{}, fmt.Errorf("device %s not found", targetDevice)
  94. }
  95. } else if len(devices) == 1 {
  96. dev = devices[0]
  97. } else {
  98. return nil, intdevice.Keyboard{}, fmt.Errorf("multiple devices found, use --device to specify")
  99. }
  100. proto, err := via.New(dev)
  101. if err != nil {
  102. return nil, intdevice.Keyboard{}, fmt.Errorf("open protocol: %w", err)
  103. }
  104. return proto, dev.Keyboard, nil
  105. }
  106. func lightingEnabled(mode, brightness uint8) bool {
  107. return mode != 0 && brightness > 0
  108. }
  109. func ParseUint8(s string) (uint8, error) {
  110. v, err := strconv.ParseUint(s, 10, 8)
  111. if err != nil {
  112. return 0, fmt.Errorf("invalid value: %w", err)
  113. }
  114. return uint8(v), nil
  115. }