Add playback slider
This commit is contained in:
parent
f6c9c5e976
commit
866074a15a
61
editor.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
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
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
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…
Reference in New Issue