improve repl
add addr & help commands, don't restart if paused
This commit is contained in:
parent
c3ee33f8ce
commit
6f2e2fd666
2
main.go
2
main.go
|
@ -83,7 +83,7 @@ func main() {
|
|||
|
||||
// local 🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊
|
||||
wg.Add(1)
|
||||
go pixelflut.Flut(img, offset, *shuffle, false, false, false, *address, *connections, stopChan, &wg)
|
||||
go pixelflut.Flut(img, offset, *shuffle, false, false, *address, *connections, stopChan, &wg)
|
||||
}
|
||||
|
||||
} else if *hevringAddr != "" {
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
// using `conns` connections. Pixels are sent column wise, unless `shuffle`
|
||||
// is set. Stops when stop is closed.
|
||||
// @cleanup: use FlutTask{} as arg
|
||||
func Flut(img *image.NRGBA, position image.Point, shuffle, rgbsplit, randoffset, recreateConns bool, address string, conns int, stop chan bool, wg *sync.WaitGroup) {
|
||||
func Flut(img *image.NRGBA, position image.Point, shuffle, rgbsplit, randoffset bool, address string, conns int, stop chan bool, wg *sync.WaitGroup) {
|
||||
var cmds commands
|
||||
if rgbsplit {
|
||||
// do a RGB split of white
|
||||
|
|
|
@ -34,10 +34,17 @@ type FlutTask struct {
|
|||
MaxConns int
|
||||
Img *image.NRGBA
|
||||
Offset image.Point
|
||||
Paused bool
|
||||
Shuffle bool // TODO: refactor these as RenderOpts bitfield
|
||||
RGBSplit bool
|
||||
RandOffset bool
|
||||
NewConn bool
|
||||
}
|
||||
|
||||
func (t FlutTask) String() string {
|
||||
return fmt.Sprintf(
|
||||
" %d conns @ %s\n img %v offset %v\n shuffle %v rgbsplit %v randoffset %v paused %v",
|
||||
t.MaxConns, t.Address, t.Img.Bounds().Size(), t.Offset, t.Shuffle, t.RGBSplit, t.RandOffset, t.Paused,
|
||||
)
|
||||
}
|
||||
|
||||
type FlutAck struct{ Ok bool }
|
||||
|
@ -54,11 +61,11 @@ func (h *Hevring) Flut(task FlutTask, reply *FlutAck) error {
|
|||
close(h.taskQuit)
|
||||
}
|
||||
|
||||
fmt.Printf("[hevring] Rán gave us /w o r k/! %v\n", task)
|
||||
fmt.Printf("[hevring] Rán gave us /w o r k/!\n%v\n", task)
|
||||
h.task = task
|
||||
h.taskQuit = make(chan bool)
|
||||
|
||||
go pixelflut.Flut(task.Img, task.Offset, task.Shuffle, task.RGBSplit, task.RandOffset, task.NewConn, task.Address, task.MaxConns, h.taskQuit, nil)
|
||||
go pixelflut.Flut(task.Img, task.Offset, task.Shuffle, task.RGBSplit, task.RandOffset, task.Address, task.MaxConns, h.taskQuit, nil)
|
||||
reply.Ok = true
|
||||
return nil
|
||||
}
|
||||
|
|
16
rpc/ran.go
16
rpc/ran.go
|
@ -109,12 +109,14 @@ func (r *Rán) applyTask(t FlutTask) {
|
|||
return
|
||||
}
|
||||
r.task = t
|
||||
for _, c := range r.clients {
|
||||
if t.Paused {
|
||||
return
|
||||
}
|
||||
for i, c := range r.clients {
|
||||
ack := FlutAck{}
|
||||
// @speed: should send tasks async
|
||||
err := c.Call("Hevring.Flut", r.task, &ack)
|
||||
if err != nil || !ack.Ok {
|
||||
log.Printf("[rán] client didn't accept task")
|
||||
log.Printf("[rán] client %d didn't accept task", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,5 +144,11 @@ func (r *Rán) SetTask(img *image.NRGBA, offset image.Point, address string, max
|
|||
// fetch server state & sample foreign activity in image regions. assign
|
||||
// subregions to clients (per connection), considering their bandwidth.
|
||||
|
||||
r.applyTask(FlutTask{address, maxConns, img, offset, true})
|
||||
r.applyTask(FlutTask{
|
||||
Address: address,
|
||||
MaxConns: maxConns,
|
||||
Img: img,
|
||||
Offset: offset,
|
||||
Shuffle: true,
|
||||
})
|
||||
}
|
||||
|
|
81
rpc/repl.go
81
rpc/repl.go
|
@ -21,8 +21,8 @@ type Fluter interface {
|
|||
toggleMetrics()
|
||||
}
|
||||
|
||||
const commandMode = "CMD"
|
||||
const textMode = "TXT"
|
||||
const commandMode = "cmd"
|
||||
const textMode = "txt"
|
||||
|
||||
// RunREPL starts reading os.Stdin for commands to apply to the given Fluter
|
||||
func RunREPL(f Fluter) {
|
||||
|
@ -31,13 +31,16 @@ func RunREPL(f Fluter) {
|
|||
var textCol image.Image = image.White
|
||||
var bgCol image.Image = image.Transparent
|
||||
|
||||
fmt.Print("[rán] REPL is active. ")
|
||||
printHelp()
|
||||
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
inputStr := scanner.Text()
|
||||
|
||||
switch mode {
|
||||
switch strings.ToLower(mode) {
|
||||
case textMode:
|
||||
if inputStr == commandMode {
|
||||
if strings.ToLower(inputStr) == commandMode {
|
||||
fmt.Println("[rán] command mode")
|
||||
mode = commandMode
|
||||
continue
|
||||
|
@ -50,52 +53,48 @@ func RunREPL(f Fluter) {
|
|||
input := strings.Split(inputStr, " ")
|
||||
cmd := strings.ToLower(input[0])
|
||||
args := input[1:]
|
||||
t := f.getTask()
|
||||
printTask := true
|
||||
|
||||
switch cmd {
|
||||
case "stop":
|
||||
t.Paused = true
|
||||
f.stopTask()
|
||||
printTask = false
|
||||
|
||||
case "start":
|
||||
f.applyTask(f.getTask())
|
||||
t.Paused = false
|
||||
|
||||
case "offset":
|
||||
if len(args) == 2 {
|
||||
if len(args) == 1 && args[0] == "rand" {
|
||||
t.RandOffset = true
|
||||
t.Offset = image.Point{}
|
||||
} else if len(args) == 2 {
|
||||
t.RandOffset = false
|
||||
x, err := strconv.Atoi(args[0])
|
||||
y, err2 := strconv.Atoi(args[1])
|
||||
if err == nil && err2 == nil {
|
||||
t := f.getTask()
|
||||
t.Offset = image.Pt(x, y)
|
||||
f.applyTask(t)
|
||||
}
|
||||
}
|
||||
|
||||
case "conns":
|
||||
if len(args) == 1 {
|
||||
if conns, err := strconv.Atoi(args[0]); err == nil {
|
||||
t := f.getTask()
|
||||
t.MaxConns = conns
|
||||
f.applyTask(t)
|
||||
}
|
||||
}
|
||||
|
||||
case "addr":
|
||||
if len(args) == 1 {
|
||||
t.Address = args[0]
|
||||
}
|
||||
|
||||
case "shuffle":
|
||||
t := f.getTask()
|
||||
t.Shuffle = !t.Shuffle
|
||||
f.applyTask(t)
|
||||
|
||||
case "rgbsplit":
|
||||
t := f.getTask()
|
||||
t.RGBSplit = !t.RGBSplit
|
||||
f.applyTask(t)
|
||||
|
||||
case "randoffset":
|
||||
t := f.getTask()
|
||||
t.RandOffset = !t.RandOffset
|
||||
f.applyTask(t)
|
||||
|
||||
case "newconn":
|
||||
t := f.getTask()
|
||||
t.NewConn = !t.NewConn
|
||||
f.applyTask(t)
|
||||
|
||||
case "txt":
|
||||
if len(args) > 0 {
|
||||
|
@ -110,35 +109,59 @@ func RunREPL(f Fluter) {
|
|||
bgCol = parseColorOrPalette(args[2])
|
||||
}
|
||||
if len(args) < 4 {
|
||||
fmt.Printf("[rán] text mode, return via %v\n", commandMode)
|
||||
fmt.Printf("[rán] text mode, return via '%v'\n", strings.ToUpper(commandMode))
|
||||
mode = textMode
|
||||
printTask = false
|
||||
} else {
|
||||
input := strings.Join(args[3:], " ")
|
||||
t := f.getTask()
|
||||
t.Img = render.RenderText(input, textSize, textCol, bgCol)
|
||||
f.applyTask(t)
|
||||
}
|
||||
|
||||
case "img":
|
||||
if len(args) > 0 {
|
||||
path := strings.Join(args, " ")
|
||||
t := f.getTask()
|
||||
if img, err := render.ReadImage(path); err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
t.Img = render.ImgToNRGBA(img)
|
||||
f.applyTask(t)
|
||||
}
|
||||
}
|
||||
|
||||
case "metrics":
|
||||
f.toggleMetrics()
|
||||
printTask = false
|
||||
|
||||
default:
|
||||
printTask = false
|
||||
fmt.Print("[rán] unknown command. ")
|
||||
printHelp()
|
||||
}
|
||||
|
||||
if printTask {
|
||||
fmt.Println(t)
|
||||
}
|
||||
f.applyTask(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printHelp() {
|
||||
fmt.Println(`available commands:
|
||||
start start fluting
|
||||
stop pause fluting
|
||||
conns <n> set number of connections per client
|
||||
addr <host>:<port> set target server
|
||||
offset <x> <y> set top-left offset
|
||||
offset rand random offset for each draw
|
||||
metrics toggle bandwidth reporting (may cost some performance)
|
||||
|
||||
img <filepath> set image
|
||||
txt <scale> <color <bgcolor> <txt> send text
|
||||
txt [<scale> [<color> [<bgcolor>]] enter interactive text mode
|
||||
rgbsplit toggle RGB split effect
|
||||
shuffle toggle between column-wise & randomized draw order`)
|
||||
}
|
||||
|
||||
// try to parse as hex-encoded RGB color,
|
||||
// alternatively treat it as palette name. If both fail,
|
||||
// give image.Transparent
|
||||
|
|
Loading…
Reference in New Issue