Big refactor
Signed-off-by: Martyn Ranyard <m@rtyn.berlin>
This commit is contained in:
parent
2202ba2fc0
commit
bed25ca03c
|
@ -0,0 +1,27 @@
|
||||||
|
package patterns
|
||||||
|
|
||||||
|
func Even(number int) bool {
|
||||||
|
return number %2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func FillPanel(w int, h int, r byte, g byte, b byte) [][]RGBcolor {
|
||||||
|
grid := make([][]RGBcolor, w)
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
grid[i] = make([]RGBcolor, h)
|
||||||
|
}
|
||||||
|
for x := 0; x < w; x++ {
|
||||||
|
for y := 0; y < h; y++ {
|
||||||
|
var rgb [3]byte
|
||||||
|
rgb[0] = r
|
||||||
|
rgb[1] = g
|
||||||
|
rgb[2] = b
|
||||||
|
grid[x][y] = rgb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return grid
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func FillPanelRGB(w int, h int, colour RGBcolor) [][]RGBcolor {
|
||||||
|
return FillPanel(w,h,colour[0],colour[1],colour[2])
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package patterns
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
var sineoffset int = 0
|
||||||
|
var lastSineSpeed uint16 = 0
|
||||||
|
|
||||||
|
func Sinewave(w int, h int, bgColor RGBcolor, fgColor RGBcolor, speed uint16) [][]RGBcolor {
|
||||||
|
if speed != lastSineSpeed {
|
||||||
|
lastSineSpeed = speed
|
||||||
|
sineoffset = 0
|
||||||
|
}
|
||||||
|
sineoffset += int(speed/40)
|
||||||
|
background := FillPanelRGB(w,h,bgColor)
|
||||||
|
for x := 0; x < w; x++ {
|
||||||
|
y := int(math.Round((math.Sin(float64(x+sineoffset))+1) / 2 * float64(h-1)))
|
||||||
|
background[x][y] = fgColor
|
||||||
|
}
|
||||||
|
return background
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastSinePos int = 0
|
||||||
|
|
||||||
|
func SineChase(w int, h int, bgColor RGBcolor, fgColor RGBcolor, speed uint16) [][]RGBcolor {
|
||||||
|
if speed != lastSineSpeed {
|
||||||
|
lastSineSpeed = speed
|
||||||
|
lastSinePos = 0
|
||||||
|
}
|
||||||
|
background := FillPanelRGB(w,h,bgColor)
|
||||||
|
y := int(math.Round((math.Sin(float64(lastSinePos))+1) / 2 * float64(h-1)))
|
||||||
|
background[lastSinePos][y] = fgColor
|
||||||
|
lastSinePos += 1
|
||||||
|
if lastSinePos >= w {
|
||||||
|
lastSinePos = 0
|
||||||
|
}
|
||||||
|
return background
|
||||||
|
}
|
||||||
|
|
||||||
|
func ZigZag(w int, h int) [][]RGBcolor {
|
||||||
|
var bgColor = [3]byte{0,0,0}
|
||||||
|
var fgColor = [3]byte{255,0,0}
|
||||||
|
//var a = [5]int{2, 4, 6, 8, 10}
|
||||||
|
background := FillPanelRGB(w,h,bgColor)
|
||||||
|
for x := 0; x < w; x++ {
|
||||||
|
y := x % (h-1)
|
||||||
|
background[x][y] = fgColor
|
||||||
|
}
|
||||||
|
return background
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package patterns
|
||||||
|
|
||||||
|
// gradient returns from fromX to toX fading from (fromR,fromG,fromB) to (toR,toG,toB)
|
||||||
|
// at least that's the idea.
|
||||||
|
func Gradient(fromR byte, fromG byte, fromB byte, toR byte, toG byte, toB byte, fromX int, toX int) []byte {
|
||||||
|
ret := make([]byte, toX*3)
|
||||||
|
var stepR float32 = (float32(toR) - float32(fromR)) / (float32(toX) - float32(fromX))
|
||||||
|
var stepG float32 = (float32(toG) - float32(fromG)) / (float32(toX) - float32(fromX))
|
||||||
|
var stepB float32 = (float32(toB) - float32(fromB)) / (float32(toX) - float32(fromX))
|
||||||
|
for i := fromX; i < toX*3; i += 3 {
|
||||||
|
ret[i] = fromR + byte(float32(i/3)*stepR)
|
||||||
|
ret[i+1] = fromG + byte(float32(i/3)*stepG)
|
||||||
|
ret[i+2] = fromB + byte(float32(i/3)*stepB)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package patterns
|
||||||
|
|
||||||
|
import "math/rand"
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
func RedPanel(w int, h int) [][]RGBcolor {
|
||||||
|
return FillPanel(w, h, 255, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastColour RGBcolor
|
||||||
|
var lastIteration uint16 = 0
|
||||||
|
|
||||||
|
func RandomColourPanel(w int, h int, speed uint16) [][]RGBcolor {
|
||||||
|
if lastIteration > 0 {
|
||||||
|
lastIteration -= 40
|
||||||
|
}
|
||||||
|
if lastIteration <= 0 {
|
||||||
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
var newColour RGBcolor
|
||||||
|
newColour[0] = byte(r.Intn(255))
|
||||||
|
newColour[1] = byte(r.Intn(255))
|
||||||
|
newColour[2] = byte(r.Intn(255))
|
||||||
|
lastColour = newColour
|
||||||
|
lastIteration = speed
|
||||||
|
}
|
||||||
|
return FillPanel(w, h, lastColour[0], lastColour[1], lastColour[2])
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package patterns
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
type RGBcolor = [3]byte
|
||||||
|
|
||||||
|
func plasmaRGBFromVal(val byte) (byte, byte, byte) {
|
||||||
|
var r byte
|
||||||
|
var g byte
|
||||||
|
var b byte
|
||||||
|
if val < 85 {
|
||||||
|
r = val * 3
|
||||||
|
g = 255 - r
|
||||||
|
b = 0
|
||||||
|
} else if val < 170 {
|
||||||
|
b = (val - 85) * 3
|
||||||
|
r = 255 - b
|
||||||
|
g = 0
|
||||||
|
} else {
|
||||||
|
g = (val - 170) * 3
|
||||||
|
b = 255 - g
|
||||||
|
r = 0
|
||||||
|
}
|
||||||
|
return r, g, b
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func LinearPlasma(l int) []byte {
|
||||||
|
line := make([]byte, l*3)
|
||||||
|
for i := 0; i < l*3; i += 3 {
|
||||||
|
val := byte(i % 256)
|
||||||
|
r, g, b := plasmaRGBFromVal(val)
|
||||||
|
line[i] = r
|
||||||
|
line[i+1] = g
|
||||||
|
line[i+2] = b
|
||||||
|
}
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
|
||||||
|
var offset float64 = 0.5
|
||||||
|
|
||||||
|
func PlasmaPanel(w int, h int, speed uint16) [][]RGBcolor {
|
||||||
|
grid := make([][]RGBcolor, w)
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
grid[i] = make([]RGBcolor, h)
|
||||||
|
}
|
||||||
|
scale := math.Pi * 2.0 / float64(w)
|
||||||
|
step := float64(5 * speed / 40)
|
||||||
|
offset -= step
|
||||||
|
if offset < 0 {
|
||||||
|
offset += 1.0
|
||||||
|
}
|
||||||
|
for y := 0; y < h; y++ {
|
||||||
|
for x := 0; x < w; x++ {
|
||||||
|
u := math.Cos((float64(x) + offset) * scale)
|
||||||
|
v := math.Cos((float64(y) + offset) * scale)
|
||||||
|
w := math.Cos((float64(w) + offset) * scale)
|
||||||
|
e := (u + v + w + 3.0) / 6.0
|
||||||
|
r, g, b := plasmaRGBFromVal(byte((offset + e) * 255))
|
||||||
|
var rgb [3]byte
|
||||||
|
rgb[0] = r
|
||||||
|
rgb[1] = g
|
||||||
|
rgb[2] = b
|
||||||
|
grid[x][y] = rgb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return grid
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package patterns
|
||||||
|
|
||||||
|
func AlternateRGBLinear(R0 byte, G0 byte, B0 byte, R1 byte, G1 byte, B1 byte, fromX int, toX int) []byte {
|
||||||
|
ret := make([]byte, toX*3)
|
||||||
|
for i := fromX; i < toX*3; i += 3 {
|
||||||
|
if Even(i) {
|
||||||
|
ret[i] = R0
|
||||||
|
ret[i+1] = G0
|
||||||
|
ret[i+2] = B0
|
||||||
|
} else {
|
||||||
|
ret[i] = R1
|
||||||
|
ret[i+1] = G1
|
||||||
|
ret[i+2] = B1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package queue
|
||||||
|
|
||||||
|
type QueueItem struct {
|
||||||
|
Effect string
|
||||||
|
Duration uint16
|
||||||
|
Speed uint16 //only used by some patterns
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
package remapping
|
||||||
|
|
||||||
|
type RGBcolor = [3]byte
|
||||||
|
|
||||||
|
func Even(number int) bool {
|
||||||
|
return number %2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Slice512(s []byte) [512]byte {
|
||||||
|
var ret [512]byte
|
||||||
|
for i := range s {
|
||||||
|
if i < 512 {
|
||||||
|
ret[i] = s[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceUnlenthed(s [512]byte) []byte {
|
||||||
|
ret := make([]byte, 512)
|
||||||
|
for i := range s {
|
||||||
|
ret[i] = s[i]
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceRearrange(rowwidth int, rows int, alternaterows bool, inslice []byte) [][]byte {
|
||||||
|
var flippedslice []byte
|
||||||
|
if alternaterows {
|
||||||
|
flippedslice = make([]byte, len(inslice)+3)
|
||||||
|
for r := 0; r < rows; r++ {
|
||||||
|
rowzero := (r * rowwidth * 3)
|
||||||
|
if Even(r) {
|
||||||
|
for c := 0; c < (rowwidth)*3; c += 3 {
|
||||||
|
flippedslice[rowzero+c] = inslice[rowzero+c]
|
||||||
|
flippedslice[rowzero+c+1] = inslice[rowzero+c+1]
|
||||||
|
flippedslice[rowzero+c+2] = inslice[rowzero+c+2]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x := rowwidth * 3
|
||||||
|
for c := 0; c < (rowwidth)*3; c += 3 {
|
||||||
|
x = x - 3
|
||||||
|
flippedslice[rowzero+x] = inslice[rowzero+c]
|
||||||
|
flippedslice[rowzero+x+1] = inslice[rowzero+c+1]
|
||||||
|
flippedslice[rowzero+x+2] = inslice[rowzero+c+2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flippedslice = inslice
|
||||||
|
}
|
||||||
|
currentUniverse := 0
|
||||||
|
currentUniversePosition := 0
|
||||||
|
universes := make([][]byte, (len(flippedslice)/510)+1)
|
||||||
|
currentUniverseSlice := make([]byte, 511)
|
||||||
|
currentRowReverse := false
|
||||||
|
for i := range flippedslice {
|
||||||
|
if currentUniversePosition >= 510 {
|
||||||
|
universes[currentUniverse] = currentUniverseSlice
|
||||||
|
if !currentRowReverse {
|
||||||
|
currentRowReverse = true
|
||||||
|
} else {
|
||||||
|
currentRowReverse = false
|
||||||
|
}
|
||||||
|
currentUniverse += 1
|
||||||
|
currentUniversePosition = 0
|
||||||
|
currentUniverseSlice = make([]byte, 511)
|
||||||
|
}
|
||||||
|
currentUniverseSlice[currentUniversePosition] = flippedslice[i]
|
||||||
|
currentUniversePosition += 1
|
||||||
|
}
|
||||||
|
universes[currentUniverse] = currentUniverseSlice
|
||||||
|
return universes
|
||||||
|
}
|
||||||
|
|
||||||
|
func XYGridToLinear(w int, h int, grid [][]RGBcolor) []byte {
|
||||||
|
ret := make([]byte, w*h*3)
|
||||||
|
i := 0
|
||||||
|
for y := 0; y < h; y++ {
|
||||||
|
for x := 0; x < w; x++ {
|
||||||
|
ret[i] = grid[x][y][0]
|
||||||
|
ret[i+1] = grid[x][y][1]
|
||||||
|
ret[i+2] = grid[x][y][2]
|
||||||
|
i += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package webserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
|
||||||
|
"github.com/gorilla/handlers"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
queue "git.martyn.berlin/martyn/LEDController/internal/queue"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HealthHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
|
response.Header().Add("Content-type", "text/plain")
|
||||||
|
fmt.Fprint(response, "I'm okay jack!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func NotFoundHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
|
response.WriteHeader(404)
|
||||||
|
fmt.Fprint(response, "I'm lost!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func RootHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
|
response.Header().Add("Content-type", "text/plain")
|
||||||
|
fmt.Fprint(response, "Not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
var globalQueue chan queue.QueueItem;
|
||||||
|
|
||||||
|
func PatternHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
|
vars := mux.Vars(request)
|
||||||
|
response.Header().Add("Content-type", "text/plain")
|
||||||
|
var e queue.QueueItem
|
||||||
|
e.Effect = vars["pattern"]
|
||||||
|
i, _ := strconv.Atoi(vars["duration"])
|
||||||
|
e.Duration = uint16(i)
|
||||||
|
_, found := vars["speed"]
|
||||||
|
if found {
|
||||||
|
i, _ := strconv.Atoi(vars["speed"])
|
||||||
|
e.Speed = uint16(i)
|
||||||
|
fmt.Printf("Speed passed %d\n",e.Speed)
|
||||||
|
} else {
|
||||||
|
e.Speed = 40
|
||||||
|
}
|
||||||
|
globalQueue <- e
|
||||||
|
fmt.Fprint(response, "OKAY")
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleHTTP(queueChannel chan queue.QueueItem) {
|
||||||
|
globalQueue = queueChannel
|
||||||
|
r := mux.NewRouter()
|
||||||
|
loggedRouter := handlers.LoggingHandler(os.Stdout, r)
|
||||||
|
r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
|
||||||
|
r.HandleFunc("/", RootHandler)
|
||||||
|
r.HandleFunc("/healthz", HealthHandler)
|
||||||
|
r.HandleFunc("/pattern/{pattern}/{duration}", PatternHandler)
|
||||||
|
r.HandleFunc("/pattern/{pattern}/{duration}/{speed}", PatternHandler)
|
||||||
|
http.Handle("/", r)
|
||||||
|
srv := &http.Server{
|
||||||
|
Handler: loggedRouter,
|
||||||
|
Addr: "0.0.0.0:5353",
|
||||||
|
WriteTimeout: 15 * time.Second,
|
||||||
|
ReadTimeout: 15 * time.Second,
|
||||||
|
}
|
||||||
|
fmt.Println("Listening on 0.0.0.0:5353")
|
||||||
|
srv.ListenAndServe()
|
||||||
|
}
|
218
main.go
218
main.go
|
@ -1,154 +1,114 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
"fmt"
|
|
||||||
|
webserver "git.martyn.berlin/martyn/LEDController/internal/webserver"
|
||||||
|
queue "git.martyn.berlin/martyn/LEDController/internal/queue"
|
||||||
|
remapping "git.martyn.berlin/martyn/LEDController/internal/remapping"
|
||||||
|
patterns "git.martyn.berlin/martyn/LEDController/internal/patterns"
|
||||||
|
|
||||||
"github.com/Hundemeier/go-sacn/sacn"
|
"github.com/Hundemeier/go-sacn/sacn"
|
||||||
)
|
)
|
||||||
|
|
||||||
func even(number int) bool {
|
type RGBcolor = [3]byte
|
||||||
return number%2 == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func slice_rearrange(rowwidth int, rows int, alternaterows bool, inslice []byte) [][]byte {
|
var currentFrame [2][512]byte
|
||||||
var flippedslice []byte
|
var channels [2]chan<-[512]byte
|
||||||
if alternaterows {
|
var sema = make(chan struct{}, 1) // a binary semaphore guarding currentFrame
|
||||||
flippedslice = make([]byte, len(inslice)+3)
|
|
||||||
for r := 0; r < rows; r++ {
|
|
||||||
rowzero := (r*rowwidth*3)
|
|
||||||
if even(r) {
|
|
||||||
for c := 0; c < (rowwidth)*3; c+=3 {
|
|
||||||
flippedslice[rowzero+c] = inslice[rowzero+c]
|
|
||||||
flippedslice[rowzero+c+1] = inslice[rowzero+c+1]
|
|
||||||
flippedslice[rowzero+c+2] = inslice[rowzero+c+2]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
x := rowwidth*3
|
|
||||||
for c := 0; c < (rowwidth)*3; c+=3 {
|
|
||||||
x = x-3
|
|
||||||
fmt.Println(x)
|
|
||||||
flippedslice[rowzero+x] = inslice[rowzero+c]
|
|
||||||
flippedslice[rowzero+x+1] = inslice[rowzero+c+1]
|
|
||||||
flippedslice[rowzero+x+2] = inslice[rowzero+c+2]/*
|
|
||||||
flippedslice[rowzero+c] = inslice[rowzero+(((rowwidth-1)*3)-c)]
|
|
||||||
flippedslice[rowzero+c+1] = inslice[rowzero+(((rowwidth-1)*3)-c)-1]
|
|
||||||
flippedslice[rowzero+c+2] = inslice[rowzero+(((rowwidth-1)*3)-c)-2]*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
flippedslice = inslice
|
|
||||||
}
|
|
||||||
currentUniverse := 0
|
|
||||||
currentUniversePosition := 0
|
|
||||||
universes := make([][]byte, (len(flippedslice)/510)+1)
|
|
||||||
currentUniverseSlice := make([]byte, 511)
|
|
||||||
currentRowReverse := false;
|
|
||||||
for i := range(flippedslice) {
|
|
||||||
if currentUniversePosition >= 510 {
|
|
||||||
fmt.Println("Reached end of universe!")
|
|
||||||
universes[currentUniverse] = currentUniverseSlice
|
|
||||||
if (!currentRowReverse) {
|
|
||||||
currentRowReverse = true
|
|
||||||
} else {
|
|
||||||
currentRowReverse = false
|
|
||||||
}
|
|
||||||
currentUniverse += 1
|
|
||||||
currentUniversePosition = 0
|
|
||||||
currentUniverseSlice = make([]byte, 511)
|
|
||||||
}
|
|
||||||
currentUniverseSlice[currentUniversePosition] = flippedslice[i]
|
|
||||||
currentUniversePosition += 1
|
|
||||||
}
|
|
||||||
universes[currentUniverse] = currentUniverseSlice
|
|
||||||
return universes
|
|
||||||
}
|
|
||||||
|
|
||||||
func alternate(R0 byte, G0 byte, B0 byte, R1 byte, G1 byte, B1 byte, fromX int, toX int) []byte {
|
var currentEffect queue.QueueItem;
|
||||||
ret := make([]byte, toX*3);
|
var globalEffectChannel = make(chan queue.QueueItem, 1024)
|
||||||
for i := fromX; i < toX*3; i+=3 {
|
|
||||||
if even(i) {
|
func foreverLoop() {
|
||||||
ret[i] = R0
|
for /*ever*/ {
|
||||||
ret[i+1] = G0
|
time.Sleep(40 * time.Millisecond) //25fps
|
||||||
ret[i+2] = B0
|
for u := 0; u < 2; u++ {
|
||||||
} else {
|
sema <- struct{}{} // acquire token
|
||||||
ret[i] = R1
|
channels[u] <- currentFrame[u]
|
||||||
ret[i+1] = G1
|
<- sema
|
||||||
ret[i+2] = B1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// gradient returns from fromX to toX fading from (fromR,fromG,fromB) to (toR,toG,toB)
|
|
||||||
// at least that's the idea.
|
|
||||||
func gradient(fromR byte, fromG byte, fromB byte, toR byte, toG byte, toB byte, fromX int, toX int) []byte {
|
|
||||||
ret := make([]byte, toX*3);
|
|
||||||
var stepR float32 = (float32(toR) - float32(fromR)) / (float32(toX) - float32(fromX))
|
|
||||||
var stepG float32 = (float32(toG) - float32(fromG)) / (float32(toX) - float32(fromX))
|
|
||||||
var stepB float32 = (float32(toB) - float32(fromB)) / (float32(toX) - float32(fromX))
|
|
||||||
for i := fromX; i < toX*3; i+=3 {
|
|
||||||
ret[i] = fromR+byte(float32(i/3)*stepR)
|
|
||||||
ret[i+1] = fromG+byte(float32(i/3)*stepG)
|
|
||||||
ret[i+2] = fromB+byte(float32(i/3)*stepB)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func slice512(s []byte) [512]byte {
|
|
||||||
var ret [512]byte
|
|
||||||
for i := range(s) {
|
|
||||||
if i < 512 {
|
|
||||||
ret[i] = s[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func sliceUnlenthed(s [512]byte) []byte {
|
|
||||||
ret := make([]byte, 512)
|
|
||||||
for i := range(s) {
|
|
||||||
ret[i] = s[i]
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
go func() {
|
||||||
|
fmt.Printf("Starting webserver on port %s\n", "5353")
|
||||||
|
webserver.HandleHTTP(globalEffectChannel)
|
||||||
|
}()
|
||||||
//instead of "" you could provide an ip-address that the socket should bind to
|
//instead of "" you could provide an ip-address that the socket should bind to
|
||||||
trans, err := sacn.NewTransmitter("", [16]byte{1, 2, 3}, "test")
|
trans, err := sacn.NewTransmitter("", [16]byte{1, 2}, "test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//activates the first universe
|
//activates the universes
|
||||||
ch1, err := trans.Activate(1)
|
for i := 0; i < 2; i++ {
|
||||||
if err != nil {
|
channels[i], err = trans.Activate(uint16(i+1))
|
||||||
log.Fatal(err)
|
//deactivate the channel on exit
|
||||||
|
defer close(channels[i])
|
||||||
|
trans.SetMulticast(uint16(i+1), false) //this specific setup will not multicast on windows,
|
||||||
|
trans.SetDestinations(uint16(i+1), []string{"192.168.1.139"})
|
||||||
}
|
}
|
||||||
ch2, err := trans.Activate(2)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
//deactivate the channel on exit
|
|
||||||
defer close(ch1)
|
|
||||||
defer close(ch2)
|
|
||||||
|
|
||||||
//set a unicast destination, and/or use multicast
|
// Plasma for start frame
|
||||||
trans.SetMulticast(1, false)//this specific setup will not multicast on windows,
|
rearranged := remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.PlasmaPanel(68, 4, 40)))
|
||||||
//because no bind address was provided
|
currentFrame[0] = remapping.Slice512(rearranged[0])
|
||||||
|
currentFrame[1] = remapping.Slice512(rearranged[1])
|
||||||
|
var e queue.QueueItem
|
||||||
|
e.Effect = "red"
|
||||||
|
e.Duration = 40 * 50
|
||||||
|
globalEffectChannel <- e
|
||||||
|
e.Effect = "plasma"
|
||||||
|
e.Duration = 0
|
||||||
|
e.Speed = 40
|
||||||
|
globalEffectChannel <- e
|
||||||
|
|
||||||
//set some example ip-addresses
|
go func() {
|
||||||
trans.SetDestinations(1, []string{"192.168.1.139"})
|
for /*ever*/ {
|
||||||
trans.SetMulticast(2, false)//this specific setup will not multicast on windows,
|
if currentEffect.Duration > 0 {
|
||||||
trans.SetDestinations(2, []string{"192.168.1.139"})
|
currentEffect.Duration -= 40
|
||||||
|
} else {
|
||||||
//send some random data for 10 seconds
|
if len(globalEffectChannel) > 0 {
|
||||||
for i := 0; i < 20; i++ {
|
currentEffect = <- globalEffectChannel
|
||||||
channels := slice_rearrange(68,4,true,gradient(255,255,255,0,0,0,0,272))
|
}
|
||||||
ch1 <- slice512(channels[0])
|
}
|
||||||
ch2 <- slice512(channels[1])
|
var rearranged [][]byte
|
||||||
time.Sleep(500 * time.Millisecond)
|
switch currentEffect.Effect {
|
||||||
}
|
case "line":
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.ZigZag(68, 4)))
|
||||||
|
case "plasma":
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.PlasmaPanel(68, 4, currentEffect.Speed)))
|
||||||
|
case "red":
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, false, remapping.XYGridToLinear(68, 4, patterns.RedPanel(68,4)))
|
||||||
|
case "random":
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, false, remapping.XYGridToLinear(68, 4, patterns.RandomColourPanel(68,4,currentEffect.Speed)))
|
||||||
|
case "linearplasma":
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, false, patterns.LinearPlasma(68*4))
|
||||||
|
case "gradientred":
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, false, patterns.Gradient(255, 0, 0, 0, 0, 255, 0, 68*4))
|
||||||
|
case "sine":
|
||||||
|
var black patterns.RGBcolor
|
||||||
|
var red patterns.RGBcolor
|
||||||
|
red[0] = 255
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.Sinewave(68, 4, black, red, currentEffect.Speed)))
|
||||||
|
case "sinechase":
|
||||||
|
var black patterns.RGBcolor
|
||||||
|
var red patterns.RGBcolor
|
||||||
|
red[0] = 255
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, true, remapping.XYGridToLinear(68, 4, patterns.SineChase(68, 4, black, red, currentEffect.Speed)))
|
||||||
|
default:
|
||||||
|
rearranged = remapping.SliceRearrange(68, 4, false, remapping.XYGridToLinear(68, 4, patterns.FillPanel(68,4, 128,0,128)))
|
||||||
|
}
|
||||||
|
//rearranged := remapping.SliceRearrange(68,4,true,linearPlasma(68*4))
|
||||||
|
sema <- struct{}{} // acquire token
|
||||||
|
currentFrame[0] = remapping.Slice512(rearranged[0])
|
||||||
|
currentFrame[1] = remapping.Slice512(rearranged[1])
|
||||||
|
<- sema
|
||||||
|
time.Sleep(40 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
foreverLoop();
|
||||||
}
|
}
|
Loading…
Reference in New Issue