Browse Source

Add playback slider

master
Trevor Slocum 11 months ago
parent
commit
866074a15a
  1. 61
      editor.go
  2. 5
      go.mod
  3. 10
      go.sum
  4. 51
      player.go

61
editor.go

@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net"
"path"
"strings"
"time"
@ -16,8 +17,11 @@ import (
var (
app *cview.Application
editorPaused bool
statusBuffer *cview.TextView
editorPaused bool
statusBuffer *cview.TextView
lengthBuffer *cview.TextView
slider *cview.Slider
castInfoBuffer *cview.TextView
editorCursor time.Duration
editorCursorTime time.Time
@ -57,14 +61,28 @@ func updateStatus() {
if !editorPaused && editorStatus == "playing" {
cursor += time.Since(editorCursorTime)
}
statusBuffer.SetText(fmt.Sprintf("%d:%02d", int(cursor.Minutes())%60, int(cursor.Seconds())%60))
ms := ((cursor.Nanoseconds() / int64(time.Millisecond)) % 1000) / 100
statusBuffer.SetText(fmt.Sprintf("%d:%02d.%d", int(cursor.Minutes()), int(cursor.Seconds())%60, ms))
}
func updateSlider() {
lengthBuffer.SetText(fmt.Sprintf("%d:%02d", int(loadedCastLength.Minutes()), int(loadedCastLength.Seconds())%60))
slider.SetProgress(int(float64(editorCursor) / float64(loadedCastLength) * 100))
}
func handleUpdateUI() {
t := time.NewTicker(time.Second)
t := time.NewTicker(100 * time.Millisecond)
i := 0
for range t.C {
updateStatus()
if i == 0 {
updateSlider()
}
app.Draw()
i++
if i > 9 {
i = 0
}
}
}
@ -103,7 +121,31 @@ func runEditor(controlAddress string, force bool) {
statusBuffer = cview.NewTextView()
app.SetRoot(statusBuffer, true)
lengthBuffer = cview.NewTextView()
lengthBuffer.SetTextAlign(cview.AlignRight)
lengthBuffer.SetText("0:00")
sliderChanged := func(value int) {
c := time.Duration(float64(loadedCastLength) * (float64(value) / 100))
sendCommand(&command{commandPlay, c, ""})
}
slider = cview.NewSlider()
slider.SetChangedFunc(sliderChanged)
castInfoBuffer = cview.NewTextView()
castInfoBuffer.SetTextAlign(cview.AlignCenter)
grid := cview.NewGrid()
grid.SetRows(-1, 1, 3, -1)
grid.AddItem(cview.NewTextView(), 0, 0, 1, 2, 0, 0, true)
grid.AddItem(statusBuffer, 1, 0, 1, 1, 0, 0, false)
grid.AddItem(lengthBuffer, 1, 1, 1, 1, 0, 0, false)
grid.AddItem(slider, 2, 0, 1, 2, 0, 0, true)
grid.AddItem(castInfoBuffer, 3, 0, 1, 2, 0, 0, true)
grid.AddItem(cview.NewTextView(), 4, 0, 1, 2, 0, 0, true)
app.SetRoot(grid, true)
quit := func(ev *tcell.EventKey) *tcell.EventKey {
app.Stop()
@ -136,7 +178,6 @@ func runEditor(controlAddress string, force bool) {
c := editorCursor + 5*time.Second
editorCursor = c
sendCommand(&command{commandPlay, c, ""})
updateStatus()
return nil
}
@ -147,7 +188,6 @@ func runEditor(controlAddress string, force bool) {
}
editorCursor = c
sendCommand(&command{commandPlay, c, ""})
updateStatus()
return nil
}
@ -164,6 +204,13 @@ func runEditor(controlAddress string, force bool) {
go handleUpdateUI()
err = loadCast(filePath)
if err != nil {
log.Fatalf("failed to load cast at %s: %s", filePath, err)
}
castInfoBuffer.SetText(path.Base(filePath))
castCommand <- &command{commandLoad, 0, filePath}
castCommand <- &command{commandPlay, 0, ""}

5
go.mod

@ -9,6 +9,7 @@ require (
github.com/onsi/gomega v1.10.3 // indirect
github.com/pkg/errors v0.9.1 // indirect
gitlab.com/tslocum/cbind v0.1.3
gitlab.com/tslocum/cview v1.5.1-0.20201023011306-a55c8124901e
golang.org/x/sys v0.0.0-20201022201747-fb209a7c41cd
gitlab.com/tslocum/cview v1.5.1-0.20201027161105-30838d75cd4c
golang.org/x/sys v0.0.0-20201027140754-0fcbb8f4928c
golang.org/x/text v0.3.4 // indirect
)

10
go.sum

@ -42,8 +42,8 @@ github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
gitlab.com/tslocum/cbind v0.1.3 h1:FT/fTQ4Yj3eo5021lB3IbkIt8eVtYGhrw/xur+cjvUU=
gitlab.com/tslocum/cbind v0.1.3/go.mod h1:RvwYE3auSjBNlCmWeGspzn+jdLUVQ8C2QGC+0nP9ChI=
gitlab.com/tslocum/cview v1.5.1-0.20201023011306-a55c8124901e h1:v+oeAUTHF3LuT4bjM3ZQVx5tpRPTVmowebqWAnqrkWo=
gitlab.com/tslocum/cview v1.5.1-0.20201023011306-a55c8124901e/go.mod h1:IEfcfqcDG4Tm28XM+H8TEtbrqjpieAewfcJvQ9SgcRM=
gitlab.com/tslocum/cview v1.5.1-0.20201027161105-30838d75cd4c h1:tG9OWKDrt1uMEJ102+lnShCtGmROfHQT6QvFI2CQU5Q=
gitlab.com/tslocum/cview v1.5.1-0.20201027161105-30838d75cd4c/go.mod h1:IEfcfqcDG4Tm28XM+H8TEtbrqjpieAewfcJvQ9SgcRM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -64,12 +64,14 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201022201747-fb209a7c41cd h1:WgqgiQvkiZWz7XLhphjt2GI2GcGCTIZs9jqXMWmH+oc=
golang.org/x/sys v0.0.0-20201022201747-fb209a7c41cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201027140754-0fcbb8f4928c h1:2+jF2APAgFgXJnYOQGDGGiRvvEo6OhqZGQf46n9xgEw=
golang.org/x/sys v0.0.0-20201027140754-0fcbb8f4928c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

51
player.go

@ -10,12 +10,15 @@ import (
)
var (
playerCursor time.Duration
loadedCast *cast.Cast
playing bool
castCommand = make(chan *command)
interrupt = make(chan struct{})
goToTime = make(chan time.Duration)
playerCursor time.Duration
loadedCast *cast.Cast
loadedCastLength time.Duration
playing bool
castCommand = make(chan *command)
interrupt = make(chan struct{})
goToTime = make(chan time.Duration)
playerPaused bool
)
func handleCast() {
@ -27,6 +30,8 @@ func handleCast() {
switch c.Type {
case commandLoad:
//interruptPlayback()
playerCursor = 0
err := loadCast(c.S)
if err != nil {
log.Fatalf("failed to load cast at %s: %s", c.S, err)
@ -36,20 +41,21 @@ func handleCast() {
resetScreen()
case commandPlay:
if !playing {
interruptPlayback()
go play(c.D)
} else {
goToTime <- c.D
}
case commandPause:
interruptPlayback()
playerPaused = true
//interruptPlayback()
case commandResume:
if !playing {
playerPaused = false
/*if playing {
interruptPlayback()
go play(c.D)
go play(playerCursor)
} else {
goToTime <- c.D
}
//goToTime <- c.D
}*/
}
}
}
@ -72,7 +78,10 @@ func loadCast(filePath string) error {
return err
}
loadedCast = c
length := time.Duration(c.EventStream[len(c.EventStream)-1].Time * float64(time.Second))
loadedCast, loadedCastLength = c, length
return nil
}
@ -87,6 +96,20 @@ func play(at time.Duration) {
var fastForward time.Duration
start := time.Now().Add(at * -1)
for _, ev := range loadedCast.EventStream {
if playerPaused {
for {
time.Sleep(10 * time.Millisecond)
if !playerPaused {
break
}
select {
case <-interrupt:
break
default:
}
}
}
t := time.Duration(ev.Time * float64(time.Second))
if ev.Type == "i" {
continue
@ -139,7 +162,7 @@ func play(at time.Duration) {
case <-t.C:
}
playerCursor = time.Since(start)
if time.Since(lastPing) >= 1*time.Second {
if time.Since(lastPing) >= 10*time.Millisecond {
status := "stopped"
if playing {
status = "playing"

Loading…
Cancel
Save