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
123 lines
2.8 KiB
Go
123 lines
2.8 KiB
Go
package cache
|
|
|
|
import (
|
|
"os"
|
|
"time"
|
|
|
|
"fyne.io/fyne/v2"
|
|
)
|
|
|
|
var (
|
|
ValidDuration = 1 * time.Minute
|
|
cleanTaskInterval = ValidDuration / 2
|
|
|
|
lastClean time.Time
|
|
skippedCleanWithCanvasRefresh = false
|
|
|
|
// testing purpose only
|
|
timeNow = time.Now
|
|
)
|
|
|
|
func init() {
|
|
if t, err := time.ParseDuration(os.Getenv("FYNE_CACHE")); err == nil {
|
|
ValidDuration = t
|
|
cleanTaskInterval = ValidDuration / 2
|
|
}
|
|
}
|
|
|
|
// Clean run cache clean task, it should be called on paint events.
|
|
func Clean(canvasRefreshed bool) {
|
|
now := timeNow()
|
|
// do not run clean task too fast
|
|
if now.Sub(lastClean) < 10*time.Second {
|
|
if canvasRefreshed {
|
|
skippedCleanWithCanvasRefresh = true
|
|
}
|
|
return
|
|
}
|
|
if skippedCleanWithCanvasRefresh {
|
|
skippedCleanWithCanvasRefresh = false
|
|
canvasRefreshed = true
|
|
}
|
|
if !canvasRefreshed && now.Sub(lastClean) < cleanTaskInterval {
|
|
return
|
|
}
|
|
destroyExpiredSvgs(now)
|
|
destroyExpiredFontMetrics(now)
|
|
if canvasRefreshed {
|
|
// Destroy renderers on canvas refresh to avoid flickering screen.
|
|
destroyExpiredRenderers(now)
|
|
// canvases cache should be invalidated only on canvas refresh, otherwise there wouldn't
|
|
// be a way to recover them later
|
|
destroyExpiredCanvases(now)
|
|
}
|
|
lastClean = timeNow()
|
|
}
|
|
|
|
// CleanCanvas performs a complete remove of all the objects that belong to the specified
|
|
// canvas. Usually used to free all objects from a closing windows.
|
|
func CleanCanvas(canvas fyne.Canvas) {
|
|
canvases.Range(func(obj fyne.CanvasObject, cinfo *canvasInfo) bool {
|
|
if cinfo.canvas != canvas {
|
|
return true
|
|
}
|
|
|
|
canvases.Delete(obj)
|
|
|
|
wid, ok := obj.(fyne.Widget)
|
|
if !ok {
|
|
return true
|
|
}
|
|
rinfo, ok := renderers.LoadAndDelete(wid)
|
|
if !ok {
|
|
return true
|
|
}
|
|
rinfo.renderer.Destroy()
|
|
overrides.Delete(wid)
|
|
return true
|
|
})
|
|
}
|
|
|
|
// ResetThemeCaches clears all the svg and text size cache maps
|
|
func ResetThemeCaches() {
|
|
svgs.Clear()
|
|
fontSizeCache.Clear()
|
|
}
|
|
|
|
// destroyExpiredCanvases deletes objects from the canvases cache.
|
|
func destroyExpiredCanvases(now time.Time) {
|
|
canvases.Range(func(obj fyne.CanvasObject, cinfo *canvasInfo) bool {
|
|
if cinfo.isExpired(now) {
|
|
canvases.Delete(obj)
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
// destroyExpiredRenderers deletes the renderer from the cache and calls
|
|
// renderer.Destroy()
|
|
func destroyExpiredRenderers(now time.Time) {
|
|
renderers.Range(func(wid fyne.Widget, rinfo *rendererInfo) bool {
|
|
if rinfo.isExpired(now) {
|
|
rinfo.renderer.Destroy()
|
|
overrides.Delete(wid)
|
|
renderers.Delete(wid)
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
type expiringCache struct {
|
|
expires time.Time
|
|
}
|
|
|
|
// isExpired check if the cache data is expired.
|
|
func (c *expiringCache) isExpired(now time.Time) bool {
|
|
return c.expires.Before(now)
|
|
}
|
|
|
|
// setAlive updates expiration time.
|
|
func (c *expiringCache) setAlive() {
|
|
c.expires = timeNow().Add(ValidDuration)
|
|
}
|