color.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package main
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/spf13/cobra"
  6. intrgb "netdome.biz/paul/qmk-rgb/internal/rgb"
  7. )
  8. func NewColorCmd() *cobra.Command {
  9. return &cobra.Command{
  10. Use: "color <hex>|rgb:<hex>|hsv:<h>,<s>,<v>",
  11. Short: "Set RGB color",
  12. Long: "Set the color of the selected zones from one of three notations:\n" +
  13. " ff0000 six digit hex, hue and saturation only\n" +
  14. " rgb:ff0000 the same, written out\n" +
  15. " hsv:0,255,255 hue, saturation and value, each 0-255\n" +
  16. "\n" +
  17. "The hex notations say nothing about brightness, so they leave it alone.\n" +
  18. "The keyboard has no value register for a color: the value of an hsv:\n" +
  19. "notation is written to the brightness of the same zones, and the\n" +
  20. "brightness the keyboard ended up holding is reported.\n" +
  21. "\n" +
  22. "Every notation is read back, so a color the keyboard rounded or refused\n" +
  23. "is reported instead of being claimed as set.",
  24. Args: cobra.ExactArgs(1),
  25. RunE: func(cmd *cobra.Command, args []string) error {
  26. spec, err := intrgb.ParseColorSpec(args[0])
  27. if err != nil {
  28. return err
  29. }
  30. zones, err := selectedZones()
  31. if err != nil {
  32. return err
  33. }
  34. proto, err := openRGBProtocol()
  35. if err != nil {
  36. return err
  37. }
  38. defer proto.Close()
  39. colors, err := setColorVerified(proto, zones, spec.H, spec.S)
  40. if err != nil {
  41. return fmt.Errorf("set color: %w", err)
  42. }
  43. if !spec.HasValue() {
  44. printColorResult(cmd, colors, nil)
  45. return nil
  46. }
  47. brightness, err := setBrightnessVerified(proto, zones, spec.V)
  48. if err != nil {
  49. return fmt.Errorf("set brightness from %s: %w", args[0], err)
  50. }
  51. printColorResult(cmd, colors, brightness)
  52. return nil
  53. },
  54. }
  55. }
  56. // printColorResult states the color every zone actually holds. The brightness
  57. // results are nil for a notation that did not write one, and then no brightness
  58. // is mentioned: the command must not imply it set something it left alone.
  59. func printColorResult(cmd *cobra.Command, colors []colorResult, brightness []zoneResult) {
  60. request := ""
  61. if len(colors) > 0 {
  62. request = fmt.Sprintf("hue %d sat %d", colors[0].RequestedHue, colors[0].RequestedSaturation)
  63. if len(brightness) > 0 {
  64. request += fmt.Sprintf(" brightness %d", brightness[0].Requested)
  65. }
  66. }
  67. if !anyColorMismatch(colors) && !anyMismatch(brightness) {
  68. fmt.Fprintf(cmd.OutOrStdout(), "Color set to %s\n", request)
  69. return
  70. }
  71. var b strings.Builder
  72. b.WriteString("Color")
  73. for i, c := range colors {
  74. fmt.Fprintf(&b, " %s hue %d sat %d", c.Zone, c.Hue, c.Saturation)
  75. if i < len(brightness) {
  76. fmt.Fprintf(&b, " brightness %d", brightness[i].Applied)
  77. }
  78. }
  79. fmt.Fprintf(&b, " (requested %s)", request)
  80. fmt.Fprintln(cmd.OutOrStdout(), b.String())
  81. }
  82. // anyColorMismatch reports whether any zone stored another color.
  83. func anyColorMismatch(results []colorResult) bool {
  84. for _, r := range results {
  85. if r.Mismatch() {
  86. return true
  87. }
  88. }
  89. return false
  90. }