mirror of
https://github.com/Luzifer/streamdeck.git
synced 2024-12-20 17:51:21 +00:00
Fix: Prevent drawing elements from previous page
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
42c0ec2f11
commit
c8a6c79369
5 changed files with 43 additions and 15 deletions
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"image/color"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
@ -12,7 +13,7 @@ func init() {
|
|||
|
||||
type displayElementColor struct{}
|
||||
|
||||
func (d displayElementColor) Display(idx int, attributes map[string]interface{}) error {
|
||||
func (d displayElementColor) Display(ctx context.Context, idx int, attributes map[string]interface{}) error {
|
||||
if name, ok := attributes["color"].(string); ok {
|
||||
return d.displayPredefinedColor(idx, name)
|
||||
}
|
||||
|
@ -22,6 +23,11 @@ func (d displayElementColor) Display(idx int, attributes map[string]interface{})
|
|||
return errors.New("RGBA color definition needs 4 hex values")
|
||||
}
|
||||
|
||||
if err := ctx.Err(); err != nil {
|
||||
// Page context was cancelled, do not draw
|
||||
return err
|
||||
}
|
||||
|
||||
return sd.FillColor(idx, color.RGBA{uint8(rgba[0].(int)), uint8(rgba[1].(int)), uint8(rgba[2].(int)), uint8(rgba[3].(int))})
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"image"
|
||||
"image/color"
|
||||
|
@ -30,7 +31,7 @@ type displayElementExec struct {
|
|||
running bool
|
||||
}
|
||||
|
||||
func (d displayElementExec) Display(idx int, attributes map[string]interface{}) error {
|
||||
func (d displayElementExec) Display(ctx context.Context, idx int, attributes map[string]interface{}) error {
|
||||
var (
|
||||
err error
|
||||
img draw.Image = image.NewRGBA(image.Rect(0, 0, sd.IconSize(), sd.IconSize()))
|
||||
|
@ -141,6 +142,11 @@ func (d displayElementExec) Display(idx int, attributes map[string]interface{})
|
|||
return nil
|
||||
}
|
||||
|
||||
if err := ctx.Err(); err != nil {
|
||||
// Page context was cancelled, do not draw
|
||||
return err
|
||||
}
|
||||
|
||||
return errors.Wrap(sd.FillImage(idx, img), "Unable to set image")
|
||||
}
|
||||
|
||||
|
@ -152,7 +158,7 @@ func (d displayElementExec) NeedsLoop(attributes map[string]interface{}) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (d *displayElementExec) StartLoopDisplay(idx int, attributes map[string]interface{}) error {
|
||||
func (d *displayElementExec) StartLoopDisplay(ctx context.Context, idx int, attributes map[string]interface{}) error {
|
||||
d.running = true
|
||||
|
||||
var interval = 5 * time.Second
|
||||
|
@ -166,7 +172,7 @@ func (d *displayElementExec) StartLoopDisplay(idx int, attributes map[string]int
|
|||
return
|
||||
}
|
||||
|
||||
if err := d.Display(idx, attributes); err != nil {
|
||||
if err := d.Display(ctx, idx, attributes); err != nil {
|
||||
log.WithError(err).Error("Unable to refresh element")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"image"
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
|
@ -15,7 +16,7 @@ func init() {
|
|||
|
||||
type displayElementImage struct{}
|
||||
|
||||
func (d displayElementImage) Display(idx int, attributes map[string]interface{}) error {
|
||||
func (d displayElementImage) Display(ctx context.Context, idx int, attributes map[string]interface{}) error {
|
||||
filename, ok := attributes["path"].(string)
|
||||
if !ok {
|
||||
return errors.New("No path attribute specified")
|
||||
|
@ -34,5 +35,10 @@ func (d displayElementImage) Display(idx int, attributes map[string]interface{})
|
|||
|
||||
img = autoSizeImage(img, sd.IconSize())
|
||||
|
||||
if err := ctx.Err(); err != nil {
|
||||
// Page context was cancelled, do not draw
|
||||
return err
|
||||
}
|
||||
|
||||
return errors.Wrap(sd.FillImage(idx, img), "Unable to set image")
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -28,10 +29,12 @@ var (
|
|||
|
||||
currentBrightness int
|
||||
|
||||
userConfig config
|
||||
activePage page
|
||||
activePageName string
|
||||
activeLoops []refreshingDisplayElement
|
||||
userConfig config
|
||||
activePage page
|
||||
activePageCtx context.Context
|
||||
activePageCtxCancel context.CancelFunc
|
||||
activePageName string
|
||||
activeLoops []refreshingDisplayElement
|
||||
|
||||
sd *streamdeck.Client
|
||||
|
||||
|
@ -208,6 +211,11 @@ func main() {
|
|||
}
|
||||
|
||||
func togglePage(page string) error {
|
||||
if activePageCtxCancel != nil {
|
||||
// Ensure old display events are no longer executed
|
||||
activePageCtxCancel()
|
||||
}
|
||||
|
||||
// Reset potentially running looped elements
|
||||
for _, l := range activeLoops {
|
||||
if err := l.StopLoopDisplay(); err != nil {
|
||||
|
@ -218,11 +226,12 @@ func togglePage(page string) error {
|
|||
|
||||
activePage = userConfig.Pages[page]
|
||||
activePageName = page
|
||||
activePageCtx, activePageCtxCancel = context.WithCancel(context.Background())
|
||||
sd.ClearAllKeys()
|
||||
|
||||
for idx, kd := range activePage.Keys {
|
||||
if kd.Display.Type != "" {
|
||||
if err := callDisplayElement(idx, kd); err != nil {
|
||||
if err := callDisplayElement(activePageCtx, idx, kd); err != nil {
|
||||
return errors.Wrapf(err, "Unable to execute display element on key %d", idx)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
|
@ -13,12 +14,12 @@ type action interface {
|
|||
}
|
||||
|
||||
type displayElement interface {
|
||||
Display(idx int, attributes map[string]interface{}) error
|
||||
Display(ctx context.Context, idx int, attributes map[string]interface{}) error
|
||||
}
|
||||
|
||||
type refreshingDisplayElement interface {
|
||||
NeedsLoop(attributes map[string]interface{}) bool
|
||||
StartLoopDisplay(idx int, attributes map[string]interface{}) error
|
||||
StartLoopDisplay(ctx context.Context, idx int, attributes map[string]interface{}) error
|
||||
StopLoopDisplay() error
|
||||
}
|
||||
|
||||
|
@ -54,7 +55,7 @@ func callAction(a dynamicElement) error {
|
|||
return inst.Execute(a.Attributes)
|
||||
}
|
||||
|
||||
func callDisplayElement(idx int, kd keyDefinition) error {
|
||||
func callDisplayElement(ctx context.Context, idx int, kd keyDefinition) error {
|
||||
t, ok := registeredDisplayElements[kd.Display.Type]
|
||||
if !ok {
|
||||
return errors.Errorf("Unknown display type %q", kd.Display.Type)
|
||||
|
@ -74,8 +75,8 @@ func callDisplayElement(idx int, kd keyDefinition) error {
|
|||
"display_type": kd.Display.Type,
|
||||
}).Debug("Starting loop")
|
||||
activeLoops = append(activeLoops, inst.(refreshingDisplayElement))
|
||||
return inst.(refreshingDisplayElement).StartLoopDisplay(idx, kd.Display.Attributes)
|
||||
return inst.(refreshingDisplayElement).StartLoopDisplay(ctx, idx, kd.Display.Attributes)
|
||||
}
|
||||
|
||||
return inst.(displayElement).Display(idx, kd.Display.Attributes)
|
||||
return inst.(displayElement).Display(ctx, idx, kd.Display.Attributes)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue