1
0
Fork 0
mirror of https://github.com/Luzifer/streamdeck.git synced 2024-10-18 05:04:18 +00:00

Fix: Prevent drawing elements from previous page

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2020-06-06 16:13:49 +02:00
parent 42c0ec2f11
commit c8a6c79369
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
5 changed files with 43 additions and 15 deletions

View file

@ -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))})
}

View file

@ -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")
}
}

View file

@ -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")
}

View file

@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"os"
"os/signal"
@ -30,6 +31,8 @@ var (
userConfig config
activePage page
activePageCtx context.Context
activePageCtxCancel context.CancelFunc
activePageName string
activeLoops []refreshingDisplayElement
@ -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)
}
}

View file

@ -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)
}