From c9fb750331a05d43586b06fc6d2334618c5389cb Mon Sep 17 00:00:00 2001
From: Derick Rethans <github@derickrethans.nl>
Date: Fri, 15 Sep 2023 17:26:16 +0100
Subject: [PATCH 1/2] Add mutexes around writing to maps and raw writes

---
 comms.go      | 5 +++++
 streamdeck.go | 8 +++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/comms.go b/comms.go
index 146fd5f..7e5dade 100644
--- a/comms.go
+++ b/comms.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"image"
 	"image/color"
+	"sync"
 
 	"github.com/karalabe/hid"
 )
@@ -66,6 +67,7 @@ type Device struct {
 	fd                   *hid.Device
 	deviceType           deviceType
 	buttonPressListeners []func(int, *Device, error)
+	mu                   sync.Mutex // controls access to writing raw data
 }
 
 // Open a Streamdeck device, the most common entry point
@@ -233,6 +235,9 @@ func (d *Device) WriteRawImageToButton(btnIndex int, rawImg image.Image) error {
 }
 
 func (d *Device) rawWriteToButton(btnIndex int, rawImage []byte) error {
+	d.mu.Lock()
+	defer d.mu.Unlock()
+
 	// Based on set_key_image from https://github.com/abcminiuser/python-elgato-streamdeck/blob/master/src/StreamDeck/Devices/StreamDeckXL.py#L151
 
 	if Min(Max(btnIndex, 0), int(d.deviceType.numberOfButtons)) != btnIndex {
diff --git a/streamdeck.go b/streamdeck.go
index ab0644b..96066db 100644
--- a/streamdeck.go
+++ b/streamdeck.go
@@ -1,6 +1,9 @@
 package streamdeck
 
-import "image"
+import (
+	"image"
+	"sync"
+)
 
 // ButtonDisplay is the interface to satisfy for displaying on a button
 type ButtonDisplay interface {
@@ -31,6 +34,7 @@ type StreamDeck struct {
 	dev        *Device
 	buttons    map[int]Button
 	decorators map[int]ButtonDecorator
+	mu         sync.Mutex
 }
 
 // New will return a new instance of a `StreamDeck`, and is the main entry point for the higher-level interface.  It will return an error if there is no StreamDeck plugged in.
@@ -56,6 +60,8 @@ func (sd *StreamDeck) GetName() string {
 func (sd *StreamDeck) AddButton(btnIndex int, b Button) {
 	b.RegisterUpdateHandler(sd.ButtonUpdateHandler)
 	b.SetButtonIndex(btnIndex)
+	sd.mu.Lock()
+	defer sd.mu.Unlock()
 	sd.buttons[btnIndex] = b
 	sd.updateButton(b)
 }

From 45f1d8e2bd02b1629ca66bda6e66e703302693d8 Mon Sep 17 00:00:00 2001
From: Derick Rethans <github@derickrethans.nl>
Date: Fri, 15 Sep 2023 17:26:26 +0100
Subject: [PATCH 2/2] gofmt fixes

---
 comms.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/comms.go b/comms.go
index 7e5dade..cc01643 100644
--- a/comms.go
+++ b/comms.go
@@ -139,12 +139,12 @@ func (d *Device) SetBrightness(pct int) error {
 }
 
 // GetButtonImageSize returns the size of the images to uploaded to the buttons
-func (d* Device) GetButtonImageSize() image.Point {
+func (d *Device) GetButtonImageSize() image.Point {
 	return d.deviceType.imageSize
 }
 
 // GetNumButtonsOnDevice returns the number of button this device has
-func (d* Device) GetNumButtonsOnDevice() uint {
+func (d *Device) GetNumButtonsOnDevice() uint {
 	return d.deviceType.numberOfButtons
 }