add controller logic for visualizations and add to gear menu
This commit is contained in:
@@ -460,11 +460,14 @@ func (p *Player) GetPeaks() (float64, float64, float64, float64) {
|
|||||||
return nInf, nInf, nInf, nInf
|
return nInf, nInf, nInf, nInf
|
||||||
}
|
}
|
||||||
m := prop.(*mpv.Node).Data.(map[string]*mpv.Node)
|
m := prop.(*mpv.Node).Data.(map[string]*mpv.Node)
|
||||||
lPeak, _ := strconv.ParseFloat(m["lavfi.astats.1.Peak_level"].Data.(string), 64)
|
if lPeakNode, ok := m["lavfi.astats.1.Peak_level"]; ok {
|
||||||
|
lPeak, _ := strconv.ParseFloat(lPeakNode.Data.(string), 64)
|
||||||
rPeak, _ := strconv.ParseFloat(m["lavfi.astats.2.Peak_level"].Data.(string), 64)
|
rPeak, _ := strconv.ParseFloat(m["lavfi.astats.2.Peak_level"].Data.(string), 64)
|
||||||
lRMS, _ := strconv.ParseFloat(m["lavfi.astats.1.RMS_level"].Data.(string), 64)
|
lRMS, _ := strconv.ParseFloat(m["lavfi.astats.1.RMS_level"].Data.(string), 64)
|
||||||
rRMS, _ := strconv.ParseFloat(m["lavfi.astats.2.RMS_level"].Data.(string), 64)
|
rRMS, _ := strconv.ParseFloat(m["lavfi.astats.2.RMS_level"].Data.(string), 64)
|
||||||
return lPeak, rPeak, lRMS, rRMS
|
return lPeak, rPeak, lRMS, rRMS
|
||||||
|
}
|
||||||
|
return nInf, nInf, nInf, nInf
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the state and invokes callbacks, if triggered
|
// sets the state and invokes callbacks, if triggered
|
||||||
|
|||||||
@@ -74,15 +74,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
myApp.LocalPlayer.SetPeaksEnabled(true)
|
|
||||||
|
|
||||||
peaks := fyneApp.NewWindow("Peak meter")
|
|
||||||
meter := ui.NewPeakMeter(myApp.LocalPlayer.GetPeaks)
|
|
||||||
peaks.SetContent(meter)
|
|
||||||
meter.Start()
|
|
||||||
peaks.Show()
|
|
||||||
|
|
||||||
mainWindow.ShowAndRun()
|
mainWindow.ShowAndRun()
|
||||||
|
|
||||||
log.Println("Running shutdown tasks...")
|
log.Println("Running shutdown tasks...")
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ type NavigationHandler func(Route)
|
|||||||
type CurPageFunc func() Route
|
type CurPageFunc func() Route
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
|
visualizationData
|
||||||
AppVersion string
|
AppVersion string
|
||||||
App *backend.App
|
App *backend.App
|
||||||
MainWindow fyne.Window
|
MainWindow fyne.Window
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/lang"
|
||||||
|
"github.com/dweymouth/supersonic/ui/visualizations"
|
||||||
|
)
|
||||||
|
|
||||||
|
// embedded in parent controller struct
|
||||||
|
type visualizationData struct {
|
||||||
|
peakMeter *visualizations.PeakMeter
|
||||||
|
|
||||||
|
visualizationAnim *fyne.Animation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) InitVisualizations() {
|
||||||
|
c.App.LocalPlayer.OnStopped(c.stopVisualizationAnim)
|
||||||
|
c.App.LocalPlayer.OnPaused(c.stopVisualizationAnim)
|
||||||
|
c.App.LocalPlayer.OnPlaying(func() {
|
||||||
|
if c.peakMeter != nil {
|
||||||
|
c.startVisualizationAnim()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) ShowPeakMeter() {
|
||||||
|
if c.peakMeter != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
win := fyne.CurrentApp().NewWindow(lang.L("Peak Meter"))
|
||||||
|
win.SetCloseIntercept(func() {
|
||||||
|
c.stopVisualizationAnim()
|
||||||
|
c.peakMeter = nil
|
||||||
|
win.Close()
|
||||||
|
})
|
||||||
|
c.peakMeter = visualizations.NewPeakMeter()
|
||||||
|
win.SetContent(c.peakMeter)
|
||||||
|
c.startVisualizationAnim()
|
||||||
|
win.Show()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) stopVisualizationAnim() {
|
||||||
|
if c.visualizationAnim != nil {
|
||||||
|
c.visualizationAnim.Stop()
|
||||||
|
c.visualizationAnim = nil
|
||||||
|
c.App.LocalPlayer.SetPeaksEnabled(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) startVisualizationAnim() {
|
||||||
|
if c.visualizationAnim == nil {
|
||||||
|
c.App.LocalPlayer.SetPeaksEnabled(true)
|
||||||
|
c.visualizationAnim = fyne.NewAnimation(
|
||||||
|
time.Duration(math.MaxInt64), /*until stopped*/
|
||||||
|
c.tickVisualizations)
|
||||||
|
c.visualizationAnim.Start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) tickVisualizations(_ float32) {
|
||||||
|
lP, rP, lRMS, rRMS := c.App.LocalPlayer.GetPeaks()
|
||||||
|
if c.visualizationData.peakMeter != nil {
|
||||||
|
c.visualizationData.peakMeter.UpdatePeaks(lP, rP, lRMS, rRMS)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/driver/desktop"
|
"fyne.io/fyne/v2/driver/desktop"
|
||||||
|
"fyne.io/fyne/v2/lang"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
|||||||
MainWindow: m.Window,
|
MainWindow: m.Window,
|
||||||
App: app,
|
App: app,
|
||||||
}
|
}
|
||||||
|
m.Controller.InitVisualizations()
|
||||||
m.BrowsingPane = browsing.NewBrowsingPane(app, m.Controller, func() { m.Router.NavigateTo(m.StartupPage()) })
|
m.BrowsingPane = browsing.NewBrowsingPane(app, m.Controller, func() { m.Router.NavigateTo(m.StartupPage()) })
|
||||||
m.Router = browsing.NewRouter(app, m.Controller, m.BrowsingPane)
|
m.Router = browsing.NewRouter(app, m.Controller, m.BrowsingPane)
|
||||||
// inject controller dependencies
|
// inject controller dependencies
|
||||||
@@ -136,6 +138,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
|||||||
m.BrowsingPane.AddSettingsMenuItem("Switch Servers", func() { app.ServerManager.Logout(false) })
|
m.BrowsingPane.AddSettingsMenuItem("Switch Servers", func() { app.ServerManager.Logout(false) })
|
||||||
m.BrowsingPane.AddSettingsMenuItem("Rescan Library", func() { app.ServerManager.Server.RescanLibrary() })
|
m.BrowsingPane.AddSettingsMenuItem("Rescan Library", func() { app.ServerManager.Server.RescanLibrary() })
|
||||||
m.BrowsingPane.AddSettingsMenuSeparator()
|
m.BrowsingPane.AddSettingsMenuSeparator()
|
||||||
|
m.BrowsingPane.AddSettingsMenuItem(lang.L("Show Peak Meter"), m.Controller.ShowPeakMeter)
|
||||||
m.BrowsingPane.AddSettingsMenuItem("Check for Updates", func() {
|
m.BrowsingPane.AddSettingsMenuItem("Check for Updates", func() {
|
||||||
go func() {
|
go func() {
|
||||||
if t := app.UpdateChecker.CheckLatestVersionTag(); t != "" && t != app.VersionTag() {
|
if t := app.UpdateChecker.CheckLatestVersionTag(); t != "" && t != app.VersionTag() {
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package ui
|
package visualizations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
"time"
|
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/canvas"
|
"fyne.io/fyne/v2/canvas"
|
||||||
@@ -20,11 +19,8 @@ const (
|
|||||||
peakHoldFrames = 60
|
peakHoldFrames = 60
|
||||||
)
|
)
|
||||||
|
|
||||||
type PeakFN func() (float64, float64, float64, float64)
|
|
||||||
|
|
||||||
type PeakMeter struct {
|
type PeakMeter struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
peakFnDB PeakFN
|
|
||||||
lPeak float64
|
lPeak float64
|
||||||
rPeak float64
|
rPeak float64
|
||||||
lRMS float64
|
lRMS float64
|
||||||
@@ -34,36 +30,18 @@ type PeakMeter struct {
|
|||||||
lPeakHoldFrame uint64
|
lPeakHoldFrame uint64
|
||||||
rPeakHoldFrame uint64
|
rPeakHoldFrame uint64
|
||||||
frameCounter uint64
|
frameCounter uint64
|
||||||
|
|
||||||
anim *fyne.Animation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPeakMeter(peakFnDB PeakFN) *PeakMeter {
|
func NewPeakMeter() *PeakMeter {
|
||||||
p := &PeakMeter{peakFnDB: peakFnDB}
|
p := &PeakMeter{}
|
||||||
p.ExtendBaseWidget(p)
|
p.ExtendBaseWidget(p)
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PeakMeter) Start() {
|
// UpdatePeaks updates the peaks that are displayed in the meter.
|
||||||
if p.anim != nil {
|
// This function is expected to be called from a fyne.Animation callback,
|
||||||
return
|
// running at 60 Hz
|
||||||
}
|
func (p *PeakMeter) UpdatePeaks(lPeak, rPeak, lRMS, rRMS float64) {
|
||||||
p.anim = fyne.NewAnimation(time.Duration(math.MaxInt64) /*until stopped*/, p.tick)
|
|
||||||
p.anim.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PeakMeter) Stop() {
|
|
||||||
if p.anim != nil {
|
|
||||||
p.anim.Stop()
|
|
||||||
p.anim = nil
|
|
||||||
p.frameCounter = 0
|
|
||||||
p.lPeakHoldFrame = 0
|
|
||||||
p.rPeakHoldFrame = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PeakMeter) tick(_ float32) {
|
|
||||||
lPeak, rPeak, lRMS, rRMS := p.peakFnDB()
|
|
||||||
p.lPeak = lPeak
|
p.lPeak = lPeak
|
||||||
p.rPeak = rPeak
|
p.rPeak = rPeak
|
||||||
lRMS = math.Max(-96, lRMS)
|
lRMS = math.Max(-96, lRMS)
|
||||||
@@ -231,5 +209,4 @@ func (l *peakMeterRenderer) Objects() []fyne.CanvasObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *peakMeterRenderer) Destroy() {
|
func (l *peakMeterRenderer) Destroy() {
|
||||||
l.p.Stop()
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user