Major improvements to UnifiedPlayer: 1. GetFrameImage() now works when paused for responsive UI updates 2. Play() method properly starts FFmpeg process 3. Frame display loop runs continuously for smooth video display 4. Disabled audio temporarily to fix video playback fundamentals 5. Simplified FFmpeg command to focus on video stream only Player now: - Generates video frames correctly - Shows video when paused - Has responsive progress tracking - Starts playback properly Next steps: Re-enable audio playback once video is stable
202 lines
5.2 KiB
Go
202 lines
5.2 KiB
Go
package widget
|
|
|
|
import (
|
|
"time"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/canvas"
|
|
"fyne.io/fyne/v2/internal/widget"
|
|
"fyne.io/fyne/v2/theme"
|
|
)
|
|
|
|
const (
|
|
infiniteRefreshRate = 50 * time.Millisecond
|
|
maxProgressBarInfiniteWidthRatio = 1.0 / 5
|
|
minProgressBarInfiniteWidthRatio = 1.0 / 20
|
|
progressBarInfiniteStepSizeRatio = 1.0 / 50
|
|
)
|
|
|
|
type infProgressRenderer struct {
|
|
widget.BaseRenderer
|
|
background, bar canvas.Rectangle
|
|
animation fyne.Animation
|
|
wasRunning bool
|
|
progress *ProgressBarInfinite
|
|
}
|
|
|
|
// MinSize calculates the minimum size of a progress bar.
|
|
func (p *infProgressRenderer) MinSize() fyne.Size {
|
|
th := p.progress.Theme()
|
|
innerPad2 := th.Size(theme.SizeNameInnerPadding) * 2
|
|
// this is to create the same size infinite progress bar as regular progress bar
|
|
text := fyne.MeasureText("100%", th.Size(theme.SizeNameText), fyne.TextStyle{})
|
|
|
|
return fyne.NewSize(text.Width+innerPad2, text.Height+innerPad2)
|
|
}
|
|
|
|
func (p *infProgressRenderer) updateBar(done float32) {
|
|
size := p.progress.Size()
|
|
progressWidth := size.Width
|
|
spanWidth := progressWidth + (progressWidth * (maxProgressBarInfiniteWidthRatio / 2))
|
|
maxBarWidth := progressWidth * maxProgressBarInfiniteWidthRatio
|
|
|
|
barCenterX := spanWidth*done - (spanWidth-progressWidth)/2
|
|
barPos := fyne.NewPos(barCenterX-maxBarWidth/2, 0)
|
|
barSize := fyne.NewSize(maxBarWidth, size.Height)
|
|
if barPos.X < 0 {
|
|
barSize.Width += barPos.X
|
|
barPos.X = 0
|
|
}
|
|
if barPos.X+barSize.Width > progressWidth {
|
|
barSize.Width = progressWidth - barPos.X
|
|
}
|
|
|
|
p.bar.Resize(barSize)
|
|
p.bar.Move(barPos)
|
|
canvas.Refresh(&p.bar)
|
|
}
|
|
|
|
// Layout the components of the infinite progress bar
|
|
func (p *infProgressRenderer) Layout(size fyne.Size) {
|
|
p.background.Resize(size)
|
|
}
|
|
|
|
// Refresh updates the size and position of the horizontal scrolling infinite progress bar
|
|
func (p *infProgressRenderer) Refresh() {
|
|
running := p.progress.Running()
|
|
if running {
|
|
if !p.wasRunning {
|
|
p.start()
|
|
}
|
|
return // we refresh from the goroutine
|
|
} else if p.wasRunning {
|
|
p.stop()
|
|
return
|
|
}
|
|
|
|
th := p.progress.Theme()
|
|
v := fyne.CurrentApp().Settings().ThemeVariant()
|
|
cornerRadius := th.Size(theme.SizeNameInputRadius)
|
|
primaryColor := th.Color(theme.ColorNamePrimary, v)
|
|
|
|
p.background.FillColor = progressBlendColor(primaryColor)
|
|
p.background.CornerRadius = cornerRadius
|
|
p.bar.FillColor = primaryColor
|
|
p.bar.CornerRadius = cornerRadius
|
|
p.background.Refresh()
|
|
p.bar.Refresh()
|
|
canvas.Refresh(p.progress.super())
|
|
}
|
|
|
|
// Start the infinite progress bar background thread to update it continuously
|
|
func (p *infProgressRenderer) start() {
|
|
p.animation.Duration = time.Second * 3
|
|
p.animation.Tick = p.updateBar
|
|
p.animation.Curve = fyne.AnimationLinear
|
|
p.animation.RepeatCount = fyne.AnimationRepeatForever
|
|
p.animation.AutoReverse = true
|
|
|
|
p.wasRunning = true
|
|
p.animation.Start()
|
|
}
|
|
|
|
// Stop the background thread from updating the infinite progress bar
|
|
func (p *infProgressRenderer) stop() {
|
|
p.wasRunning = false
|
|
p.animation.Stop()
|
|
}
|
|
|
|
func (p *infProgressRenderer) Destroy() {
|
|
p.progress.running = false
|
|
|
|
p.stop()
|
|
}
|
|
|
|
// ProgressBarInfinite widget creates a horizontal panel that indicates waiting indefinitely
|
|
// An infinite progress bar loops 0% -> 100% repeatedly until Stop() is called
|
|
type ProgressBarInfinite struct {
|
|
BaseWidget
|
|
running bool
|
|
}
|
|
|
|
// Show this widget, if it was previously hidden
|
|
func (p *ProgressBarInfinite) Show() {
|
|
p.running = true
|
|
|
|
p.BaseWidget.Show()
|
|
}
|
|
|
|
// Hide this widget, if it was previously visible
|
|
func (p *ProgressBarInfinite) Hide() {
|
|
p.running = false
|
|
|
|
p.BaseWidget.Hide()
|
|
}
|
|
|
|
// Start the infinite progress bar animation
|
|
func (p *ProgressBarInfinite) Start() {
|
|
if p.running {
|
|
return
|
|
}
|
|
|
|
p.running = true
|
|
p.BaseWidget.Refresh()
|
|
}
|
|
|
|
// Stop the infinite progress bar animation
|
|
func (p *ProgressBarInfinite) Stop() {
|
|
if !p.running {
|
|
return
|
|
}
|
|
|
|
p.running = false
|
|
p.BaseWidget.Refresh()
|
|
}
|
|
|
|
// Running returns the current state of the infinite progress animation
|
|
func (p *ProgressBarInfinite) Running() bool {
|
|
return p.running
|
|
}
|
|
|
|
// MinSize returns the size that this widget should not shrink below
|
|
func (p *ProgressBarInfinite) MinSize() fyne.Size {
|
|
p.ExtendBaseWidget(p)
|
|
return p.BaseWidget.MinSize()
|
|
}
|
|
|
|
// CreateRenderer is a private method to Fyne which links this widget to its renderer
|
|
func (p *ProgressBarInfinite) CreateRenderer() fyne.WidgetRenderer {
|
|
p.ExtendBaseWidget(p)
|
|
th := p.Theme()
|
|
v := fyne.CurrentApp().Settings().ThemeVariant()
|
|
|
|
primaryColor := th.Color(theme.ColorNamePrimary, v)
|
|
cornerRadius := th.Size(theme.SizeNameInputRadius)
|
|
|
|
render := &infProgressRenderer{
|
|
background: canvas.Rectangle{
|
|
FillColor: progressBlendColor(primaryColor),
|
|
CornerRadius: cornerRadius,
|
|
},
|
|
bar: canvas.Rectangle{
|
|
FillColor: primaryColor,
|
|
CornerRadius: cornerRadius,
|
|
},
|
|
progress: p,
|
|
}
|
|
|
|
render.SetObjects([]fyne.CanvasObject{&render.background, &render.bar})
|
|
|
|
p.running = true
|
|
return render
|
|
}
|
|
|
|
// NewProgressBarInfinite creates a new progress bar widget that loops indefinitely from 0% -> 100%
|
|
// SetValue() is not defined for infinite progress bar
|
|
// To stop the looping progress and set the progress bar to 100%, call ProgressBarInfinite.Stop()
|
|
func NewProgressBarInfinite() *ProgressBarInfinite {
|
|
bar := &ProgressBarInfinite{}
|
|
bar.ExtendBaseWidget(bar)
|
|
return bar
|
|
}
|