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

Implement dynamic exec displays

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2019-11-21 23:54:27 +01:00
parent eee8f31f82
commit fcbbfc0c30
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
3 changed files with 66 additions and 10 deletions

View file

@ -11,21 +11,25 @@ import (
"os"
"os/exec"
"strings"
"time"
"github.com/golang/freetype"
"github.com/golang/freetype/truetype"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)
func init() {
registerDisplayElement("exec", displayElementCommand{})
registerDisplayElement("exec", &displayElementExec{})
}
type displayElementCommand struct{}
type displayElementExec struct {
running bool
}
func (d displayElementCommand) Display(idx int, attributes map[string]interface{}) error {
func (d displayElementExec) Display(idx int, attributes map[string]interface{}) error {
var (
err error
img draw.Image = image.NewRGBA(image.Rect(0, 0, sd.IconSize(), sd.IconSize()))
@ -107,7 +111,35 @@ func (d displayElementCommand) Display(idx int, attributes map[string]interface{
return errors.Wrap(sd.FillImage(idx, img), "Unable to set image")
}
func (displayElementCommand) drawText(c *freetype.Context, text string, textColor color.Color, fontsize float64, border int) error {
func (d *displayElementExec) StartLoopDisplay(idx int, attributes map[string]interface{}) error {
d.running = true
var interval = 5 * time.Second
if v, ok := attributes["interval"].(int); ok {
interval = time.Duration(v) * time.Second
}
go func() {
for tick := time.NewTicker(interval); ; <-tick.C {
if !d.running {
return
}
if err := d.Display(idx, attributes); err != nil {
log.WithError(err).Error("Unable to refresh element")
}
}
}()
return nil
}
func (d *displayElementExec) StopLoopDisplay() error {
d.running = false
return nil
}
func (displayElementExec) drawText(c *freetype.Context, text string, textColor color.Color, fontsize float64, border int) error {
c.SetSrc(image.NewUniform(color.RGBA{0x0, 0x0, 0x0, 0x0})) // Transparent for text size guessing
var (
@ -140,7 +172,7 @@ func (displayElementCommand) drawText(c *freetype.Context, text string, textColo
return err
}
func (displayElementCommand) getImageFromDisk(filename string) (image.Image, error) {
func (displayElementExec) getImageFromDisk(filename string) (image.Image, error) {
f, err := os.Open(filename)
if err != nil {
return nil, errors.Wrap(err, "Unable to open image")
@ -155,7 +187,7 @@ func (displayElementCommand) getImageFromDisk(filename string) (image.Image, err
return img, nil
}
func (displayElementCommand) loadFont() (*truetype.Font, error) {
func (displayElementExec) loadFont() (*truetype.Font, error) {
fontRaw, err := ioutil.ReadFile(userConfig.RenderFont)
if err != nil {
return nil, errors.Wrap(err, "Unable to read font file")

View file

@ -25,6 +25,7 @@ var (
userConfig config
activePage page
activeLoops []refreshingDisplayElement
sd *streamdeck.Client
@ -130,6 +131,14 @@ func main() {
}
func togglePage(page string) error {
// Reset potentially running looped elements
for _, l := range activeLoops {
if err := l.StopLoopDisplay(); err != nil {
return errors.Wrap(err, "Unable to stop element refresh")
}
}
activeLoops = nil
activePage = userConfig.Pages[page]
sd.ClearAllKeys()

View file

@ -15,6 +15,11 @@ type displayElement interface {
Display(idx int, attributes map[string]interface{}) error
}
type refreshingDisplayElement interface {
StartLoopDisplay(idx int, attributes map[string]interface{}) error
StopLoopDisplay() error
}
var (
registeredActions = map[string]reflect.Type{}
registeredActionsLock sync.Mutex
@ -53,7 +58,17 @@ func callDisplayElement(idx int, kd keyDefinition) error {
return errors.Errorf("Unknown display type %q", kd.Display.Type)
}
inst := reflect.New(t).Interface().(displayElement)
return inst.Display(idx, kd.Display.Attributes)
var inst interface{}
if t.Kind() == reflect.Ptr {
inst = reflect.New(t.Elem()).Interface()
} else {
inst = reflect.New(t).Interface()
}
if t.Implements(reflect.TypeOf((*refreshingDisplayElement)(nil)).Elem()) {
activeLoops = append(activeLoops, inst.(refreshingDisplayElement))
return inst.(refreshingDisplayElement).StartLoopDisplay(idx, kd.Display.Attributes)
}
return inst.(displayElement).Display(idx, kd.Display.Attributes)
}