more work for preparing for casting
This commit is contained in:
+18
-11
@@ -11,18 +11,16 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/backend/ipc"
|
"github.com/dweymouth/supersonic/backend/ipc"
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
"github.com/dweymouth/supersonic/backend/player"
|
"github.com/dweymouth/supersonic/backend/player"
|
||||||
"github.com/dweymouth/supersonic/backend/player/dlna"
|
|
||||||
"github.com/dweymouth/supersonic/backend/player/mpv"
|
"github.com/dweymouth/supersonic/backend/player/mpv"
|
||||||
"github.com/dweymouth/supersonic/backend/util"
|
"github.com/dweymouth/supersonic/backend/util"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/supersonic-app/go-upnpcast/device"
|
|
||||||
"github.com/supersonic-app/go-upnpcast/services"
|
|
||||||
|
|
||||||
"github.com/20after4/configdir"
|
"github.com/20after4/configdir"
|
||||||
"github.com/zalando/go-keyring"
|
"github.com/zalando/go-keyring"
|
||||||
@@ -45,7 +43,7 @@ type App struct {
|
|||||||
ServerManager *ServerManager
|
ServerManager *ServerManager
|
||||||
ImageManager *ImageManager
|
ImageManager *ImageManager
|
||||||
PlaybackManager *PlaybackManager
|
PlaybackManager *PlaybackManager
|
||||||
LocalPlayer player.BasePlayer
|
LocalPlayer *mpv.Player
|
||||||
UpdateChecker UpdateChecker
|
UpdateChecker UpdateChecker
|
||||||
MPRISHandler *MPRISHandler
|
MPRISHandler *MPRISHandler
|
||||||
WinSMTC *SMTC
|
WinSMTC *SMTC
|
||||||
@@ -154,6 +152,21 @@ func StartupApp(appName, displayAppName, appVersion, appVersionTag, latestReleas
|
|||||||
a.LrcLibFetcher = NewLrcLibFetcher(a.cacheDir, a.Config.Application.CustomLrcLibUrl, timeout)
|
a.LrcLibFetcher = NewLrcLibFetcher(a.cacheDir, a.Config.Application.CustomLrcLibUrl, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Periodically scan for remote players
|
||||||
|
go func() {
|
||||||
|
t := time.NewTicker(5 * time.Minute)
|
||||||
|
for {
|
||||||
|
a.PlaybackManager.ScanRemotePlayers(a.bgrndCtx)
|
||||||
|
select {
|
||||||
|
case <-a.bgrndCtx.Done():
|
||||||
|
t.Stop()
|
||||||
|
return
|
||||||
|
case <-t.C:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
a.PlaybackManager.OnPlaying(func() {
|
a.PlaybackManager.OnPlaying(func() {
|
||||||
SetSystemSleepDisabled(true)
|
SetSystemSleepDisabled(true)
|
||||||
})
|
})
|
||||||
@@ -275,11 +288,7 @@ func (a *App) initMPV() error {
|
|||||||
if err := p.Init(c.InMemoryCacheSizeMB); err != nil {
|
if err := p.Init(c.InMemoryCacheSizeMB); err != nil {
|
||||||
return fmt.Errorf("failed to initialize mpv player: %s", err.Error())
|
return fmt.Errorf("failed to initialize mpv player: %s", err.Error())
|
||||||
}
|
}
|
||||||
// a.LocalPlayer = p
|
a.LocalPlayer = p
|
||||||
devices, _ := device.SearchMediaRenderers(context.Background(), 10, services.AVTransport)
|
|
||||||
if len(devices) > 0 {
|
|
||||||
a.LocalPlayer, _ = dlna.NewDLNAPlayer(devices[0])
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +296,6 @@ func (a *App) setupMPV() error {
|
|||||||
a.Config.LocalPlayback.Volume = clamp(a.Config.LocalPlayback.Volume, 0, 100)
|
a.Config.LocalPlayback.Volume = clamp(a.Config.LocalPlayback.Volume, 0, 100)
|
||||||
a.LocalPlayer.SetVolume(a.Config.LocalPlayback.Volume)
|
a.LocalPlayer.SetVolume(a.Config.LocalPlayback.Volume)
|
||||||
|
|
||||||
/*
|
|
||||||
devs, err := a.LocalPlayer.ListAudioDevices()
|
devs, err := a.LocalPlayer.ListAudioDevices()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -337,7 +345,6 @@ func (a *App) setupMPV() error {
|
|||||||
}
|
}
|
||||||
copy(eq.BandGains[:], a.Config.LocalPlayback.GraphicEqualizerBands)
|
copy(eq.BandGains[:], a.Config.LocalPlayback.GraphicEqualizerBands)
|
||||||
a.LocalPlayer.SetEqualizer(eq)
|
a.LocalPlayer.SetEqualizer(eq)
|
||||||
*/
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-16
@@ -58,6 +58,9 @@ type playbackEngine struct {
|
|||||||
noIncrementNextTrackChange bool // true iff the nowPlayingIndex should not be incremented on the next onTrackChange
|
noIncrementNextTrackChange bool // true iff the nowPlayingIndex should not be incremented on the next onTrackChange
|
||||||
alreadyScrobbled bool // true iff the previously-playing track was already scrobbled
|
alreadyScrobbled bool // true iff the previously-playing track was already scrobbled
|
||||||
|
|
||||||
|
pendingPlayerChange bool
|
||||||
|
pendingPlayerChangeTimePos float64
|
||||||
|
|
||||||
// to pass to onSongChange listeners; clear once listeners have been called
|
// to pass to onSongChange listeners; clear once listeners have been called
|
||||||
lastScrobbled *mediaprovider.Track
|
lastScrobbled *mediaprovider.Track
|
||||||
scrobbleCfg *ScrobbleConfig
|
scrobbleCfg *ScrobbleConfig
|
||||||
@@ -102,23 +105,8 @@ func NewPlaybackEngine(
|
|||||||
case "One":
|
case "One":
|
||||||
pm.loopMode = LoopOne
|
pm.loopMode = LoopOne
|
||||||
}
|
}
|
||||||
p.OnTrackChange(pm.handleOnTrackChange)
|
|
||||||
p.OnSeek(func() {
|
|
||||||
pm.doUpdateTimePos(true)
|
|
||||||
pm.invokeNoArgCallbacks(pm.onSeek)
|
|
||||||
})
|
|
||||||
p.OnStopped(pm.handleOnStopped)
|
|
||||||
p.OnPaused(func() {
|
|
||||||
pm.playTimeStopwatch.Stop()
|
|
||||||
pm.stopPollTimePos()
|
|
||||||
pm.invokeNoArgCallbacks(pm.onPaused)
|
|
||||||
})
|
|
||||||
p.OnPlaying(func() {
|
|
||||||
pm.playTimeStopwatch.Start()
|
|
||||||
pm.startPollTimePos()
|
|
||||||
pm.invokeNoArgCallbacks(pm.onPlaying)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
pm.registerPlayerCallbacks(p)
|
||||||
s.OnLogout(func() {
|
s.OnLogout(func() {
|
||||||
pm.StopAndClearPlayQueue()
|
pm.StopAndClearPlayQueue()
|
||||||
})
|
})
|
||||||
@@ -126,6 +114,51 @@ func NewPlaybackEngine(
|
|||||||
return pm
|
return pm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *playbackEngine) registerPlayerCallbacks(pl player.BasePlayer) {
|
||||||
|
pl.OnTrackChange(p.handleOnTrackChange)
|
||||||
|
pl.OnSeek(func() {
|
||||||
|
p.doUpdateTimePos(true)
|
||||||
|
p.invokeNoArgCallbacks(p.onSeek)
|
||||||
|
})
|
||||||
|
pl.OnStopped(p.handleOnStopped)
|
||||||
|
pl.OnPaused(func() {
|
||||||
|
p.playTimeStopwatch.Stop()
|
||||||
|
p.stopPollTimePos()
|
||||||
|
p.invokeNoArgCallbacks(p.onPaused)
|
||||||
|
})
|
||||||
|
pl.OnPlaying(func() {
|
||||||
|
p.playTimeStopwatch.Start()
|
||||||
|
p.startPollTimePos()
|
||||||
|
p.invokeNoArgCallbacks(p.onPlaying)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *playbackEngine) SetPlayer(pl player.BasePlayer) {
|
||||||
|
needToUnpause := false
|
||||||
|
|
||||||
|
stat := p.player.GetStatus()
|
||||||
|
switch stat.State {
|
||||||
|
case player.Stopped:
|
||||||
|
// nothing
|
||||||
|
case player.Playing:
|
||||||
|
p.Pause()
|
||||||
|
fallthrough
|
||||||
|
case player.Paused:
|
||||||
|
p.pendingPlayerChangeTimePos = stat.TimePos
|
||||||
|
p.pendingPlayerChange = true
|
||||||
|
needToUnpause = true
|
||||||
|
}
|
||||||
|
|
||||||
|
p.player = pl
|
||||||
|
p.registerPlayerCallbacks(pl)
|
||||||
|
|
||||||
|
if needToUnpause {
|
||||||
|
p.PlayTrackAt(p.nowPlayingIdx)
|
||||||
|
p.SeekSeconds(p.pendingPlayerChangeTimePos)
|
||||||
|
p.pendingPlayerChange = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) PlayTrackAt(idx int) error {
|
func (p *playbackEngine) PlayTrackAt(idx int) error {
|
||||||
if idx < 0 || idx >= len(p.playQueue) {
|
if idx < 0 || idx >= len(p.playQueue) {
|
||||||
return errors.New("track index out of range")
|
return errors.New("track index out of range")
|
||||||
@@ -238,6 +271,15 @@ func (p *playbackEngine) Pause() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *playbackEngine) Continue() error {
|
func (p *playbackEngine) Continue() error {
|
||||||
|
if p.pendingPlayerChange {
|
||||||
|
err := p.PlayTrackAt(p.nowPlayingIdx)
|
||||||
|
if p.pendingPlayerChangeTimePos != 0 {
|
||||||
|
p.SeekSeconds(p.pendingPlayerChangeTimePos)
|
||||||
|
}
|
||||||
|
p.pendingPlayerChange = false
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if p.PlayerStatus().State == player.Stopped {
|
if p.PlayerStatus().State == player.Stopped {
|
||||||
return p.PlayTrackAt(0)
|
return p.PlayTrackAt(0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,16 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
"github.com/dweymouth/supersonic/backend/player"
|
"github.com/dweymouth/supersonic/backend/player"
|
||||||
|
"github.com/dweymouth/supersonic/backend/player/dlna"
|
||||||
"github.com/dweymouth/supersonic/backend/player/mpv"
|
"github.com/dweymouth/supersonic/backend/player/mpv"
|
||||||
"github.com/dweymouth/supersonic/sharedutil"
|
"github.com/dweymouth/supersonic/sharedutil"
|
||||||
|
"github.com/supersonic-app/go-upnpcast/device"
|
||||||
|
"github.com/supersonic-app/go-upnpcast/services"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A high-level MediaProvider-aware playback engine, serves as an
|
// A high-level MediaProvider-aware playback engine, serves as an
|
||||||
@@ -22,11 +26,21 @@ type PlaybackManager struct {
|
|||||||
cmdQueue *playbackCommandQueue
|
cmdQueue *playbackCommandQueue
|
||||||
cfg *AppConfig
|
cfg *AppConfig
|
||||||
|
|
||||||
|
localPlayer player.BasePlayer
|
||||||
|
remotePlayersLock sync.Mutex
|
||||||
|
remotePlayers []remotePlayer
|
||||||
|
|
||||||
autoplay bool
|
autoplay bool
|
||||||
|
|
||||||
lastPlayTime float64
|
lastPlayTime float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type remotePlayer struct {
|
||||||
|
Name string
|
||||||
|
Protocol string
|
||||||
|
new func() (player.BasePlayer, error)
|
||||||
|
}
|
||||||
|
|
||||||
func NewPlaybackManager(
|
func NewPlaybackManager(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
s *ServerManager,
|
s *ServerManager,
|
||||||
@@ -43,6 +57,7 @@ func NewPlaybackManager(
|
|||||||
cmdQueue: q,
|
cmdQueue: q,
|
||||||
cfg: appCfg,
|
cfg: appCfg,
|
||||||
autoplay: playbackCfg.Autoplay,
|
autoplay: playbackCfg.Autoplay,
|
||||||
|
localPlayer: p,
|
||||||
}
|
}
|
||||||
pm.addOnTrackChangeHook()
|
pm.addOnTrackChangeHook()
|
||||||
go pm.runCmdQueue(ctx)
|
go pm.runCmdQueue(ctx)
|
||||||
@@ -81,6 +96,47 @@ func (p *PlaybackManager) addOnTrackChangeHook() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PlaybackManager) ScanRemotePlayers(ctx context.Context) {
|
||||||
|
devices, _ := device.SearchMediaRenderers(ctx, 10, services.AVTransport, services.RenderingControl)
|
||||||
|
|
||||||
|
var discovered []remotePlayer
|
||||||
|
for _, d := range devices {
|
||||||
|
p := remotePlayer{
|
||||||
|
Name: d.FriendlyName,
|
||||||
|
Protocol: "DLNA",
|
||||||
|
new: func() (player.BasePlayer, error) {
|
||||||
|
return dlna.NewDLNAPlayer(d)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
discovered = append(discovered, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.remotePlayersLock.Lock()
|
||||||
|
p.remotePlayers = discovered
|
||||||
|
p.remotePlayersLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PlaybackManager) RemotePlayers() []remotePlayer {
|
||||||
|
p.remotePlayersLock.Lock()
|
||||||
|
players := p.remotePlayers
|
||||||
|
p.remotePlayersLock.Unlock()
|
||||||
|
return players
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PlaybackManager) SetRemotePlayer(rp *remotePlayer) error {
|
||||||
|
if rp == nil {
|
||||||
|
p.engine.SetPlayer(p.localPlayer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
player, err := rp.new()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.engine.SetPlayer(player)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PlaybackManager) CurrentPlayer() player.BasePlayer {
|
func (p *PlaybackManager) CurrentPlayer() player.BasePlayer {
|
||||||
return p.engine.CurrentPlayer()
|
return p.engine.CurrentPlayer()
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-23
@@ -84,66 +84,66 @@ func (r ReplayGainMode) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BasePlayerCallbackImpl struct {
|
type BasePlayerCallbackImpl struct {
|
||||||
onPaused []func()
|
onPaused func()
|
||||||
onStopped []func()
|
onStopped func()
|
||||||
onPlaying []func()
|
onPlaying func()
|
||||||
onSeek []func()
|
onSeek func()
|
||||||
onTrackChange []func()
|
onTrackChange func()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers a callback which is invoked when the player transitions to the Paused state.
|
// Sets a callback which is invoked when the player transitions to the Paused state.
|
||||||
func (p *BasePlayerCallbackImpl) OnPaused(cb func()) {
|
func (p *BasePlayerCallbackImpl) OnPaused(cb func()) {
|
||||||
p.onPaused = append(p.onPaused, cb)
|
p.onPaused = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers a callback which is invoked when the player transitions to the Stopped state.
|
// Sets a callback which is invoked when the player transitions to the Stopped state.
|
||||||
func (p *BasePlayerCallbackImpl) OnStopped(cb func()) {
|
func (p *BasePlayerCallbackImpl) OnStopped(cb func()) {
|
||||||
p.onStopped = append(p.onStopped, cb)
|
p.onStopped = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers a callback which is invoked when the player transitions to the Playing state.
|
// Sets a callback which is invoked when the player transitions to the Playing state.
|
||||||
func (p *BasePlayerCallbackImpl) OnPlaying(cb func()) {
|
func (p *BasePlayerCallbackImpl) OnPlaying(cb func()) {
|
||||||
p.onPlaying = append(p.onPlaying, cb)
|
p.onPlaying = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers a callback which is invoked whenever a seek event occurs.
|
// Registers a callback which is invoked whenever a seek event occurs.
|
||||||
func (p *BasePlayerCallbackImpl) OnSeek(cb func()) {
|
func (p *BasePlayerCallbackImpl) OnSeek(cb func()) {
|
||||||
p.onSeek = append(p.onSeek, cb)
|
p.onSeek = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registers a callback which is invoked when the currently playing track changes,
|
// Registers a callback which is invoked when the currently playing track changes,
|
||||||
// or when playback begins at any time from the Stopped state.
|
// or when playback begins at any time from the Stopped state.
|
||||||
// Callback is invoked with the index of the currently playing track (zero-based).
|
// Callback is invoked with the index of the currently playing track (zero-based).
|
||||||
func (p *BasePlayerCallbackImpl) OnTrackChange(cb func()) {
|
func (p *BasePlayerCallbackImpl) OnTrackChange(cb func()) {
|
||||||
p.onTrackChange = append(p.onTrackChange, cb)
|
p.onTrackChange = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BasePlayerCallbackImpl) InvokeOnPaused() {
|
func (p *BasePlayerCallbackImpl) InvokeOnPaused() {
|
||||||
for _, cb := range p.onPaused {
|
if p.onPaused != nil {
|
||||||
cb()
|
p.onPaused()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BasePlayerCallbackImpl) InvokeOnPlaying() {
|
func (p *BasePlayerCallbackImpl) InvokeOnPlaying() {
|
||||||
for _, cb := range p.onPlaying {
|
if p.onPlaying != nil {
|
||||||
cb()
|
p.onPlaying()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BasePlayerCallbackImpl) InvokeOnStopped() {
|
func (p *BasePlayerCallbackImpl) InvokeOnStopped() {
|
||||||
for _, cb := range p.onStopped {
|
if p.onStopped != nil {
|
||||||
cb()
|
p.onStopped()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BasePlayerCallbackImpl) InvokeOnSeek() {
|
func (p *BasePlayerCallbackImpl) InvokeOnSeek() {
|
||||||
for _, cb := range p.onSeek {
|
if p.onSeek != nil {
|
||||||
cb()
|
p.onSeek()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BasePlayerCallbackImpl) InvokeOnTrackChange() {
|
func (p *BasePlayerCallbackImpl) InvokeOnTrackChange() {
|
||||||
for _, cb := range p.onTrackChange {
|
if p.onTrackChange != nil {
|
||||||
cb()
|
p.onTrackChange()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import (
|
|||||||
fynetooltip "github.com/dweymouth/fyne-tooltip"
|
fynetooltip "github.com/dweymouth/fyne-tooltip"
|
||||||
"github.com/dweymouth/supersonic/backend"
|
"github.com/dweymouth/supersonic/backend"
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
|
"github.com/dweymouth/supersonic/backend/player"
|
||||||
|
"github.com/dweymouth/supersonic/backend/player/mpv"
|
||||||
"github.com/dweymouth/supersonic/sharedutil"
|
"github.com/dweymouth/supersonic/sharedutil"
|
||||||
"github.com/dweymouth/supersonic/ui/dialogs"
|
"github.com/dweymouth/supersonic/ui/dialogs"
|
||||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||||
@@ -268,7 +270,7 @@ func (c *Controller) ShowAboutDialog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) ShowSettingsDialog(themeUpdateCallbk func(), themeFiles map[string]string) {
|
func (c *Controller) ShowSettingsDialog(themeUpdateCallbk func(), themeFiles map[string]string) {
|
||||||
/*
|
|
||||||
devs, err := c.App.LocalPlayer.ListAudioDevices()
|
devs, err := c.App.LocalPlayer.ListAudioDevices()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error listing audio devices: %v", err)
|
log.Printf("error listing audio devices: %v", err)
|
||||||
@@ -317,7 +319,7 @@ func (c *Controller) ShowSettingsDialog(themeUpdateCallbk func(), themeFiles map
|
|||||||
c.ClosePopUpOnEscape(pop)
|
c.ClosePopUpOnEscape(pop)
|
||||||
c.haveModal = true
|
c.haveModal = true
|
||||||
pop.Show()
|
pop.Show()
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) doModalClosed() {
|
func (c *Controller) doModalClosed() {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/lang"
|
"fyne.io/fyne/v2/lang"
|
||||||
"github.com/dweymouth/supersonic/backend/player"
|
"github.com/dweymouth/supersonic/backend/player"
|
||||||
|
"github.com/dweymouth/supersonic/backend/player/mpv"
|
||||||
"github.com/dweymouth/supersonic/ui/shortcuts"
|
"github.com/dweymouth/supersonic/ui/shortcuts"
|
||||||
"github.com/dweymouth/supersonic/ui/util"
|
"github.com/dweymouth/supersonic/ui/util"
|
||||||
"github.com/dweymouth/supersonic/ui/visualizations"
|
"github.com/dweymouth/supersonic/ui/visualizations"
|
||||||
@@ -21,12 +22,14 @@ type visualizationData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) initVisualizations() {
|
func (c *Controller) initVisualizations() {
|
||||||
c.App.LocalPlayer.OnStopped(c.stopVisualizationAnim)
|
c.App.PlaybackManager.OnStopped(c.stopVisualizationAnim)
|
||||||
c.App.LocalPlayer.OnPaused(c.stopVisualizationAnim)
|
c.App.PlaybackManager.OnPaused(c.stopVisualizationAnim)
|
||||||
c.App.LocalPlayer.OnPlaying(func() {
|
c.App.PlaybackManager.OnPlaying(func() {
|
||||||
|
if _, ok := c.App.PlaybackManager.CurrentPlayer().(*mpv.Player); ok {
|
||||||
if c.peakMeter != nil {
|
if c.peakMeter != nil {
|
||||||
c.startVisualizationAnim()
|
c.startVisualizationAnim()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user