diff --git a/backend/app.go b/backend/app.go index d26bd00..fe9de0e 100644 --- a/backend/app.go +++ b/backend/app.go @@ -68,6 +68,7 @@ func StartupApp(appName, appVersionTag, configFile, latestReleaseURL string) (*A PreventClipping: a.Config.ReplayGain.PreventClipping, PreampGain: a.Config.ReplayGain.PreampGainDB, }) + a.Player.SetAudioExclusive(a.Config.LocalPlayback.AudioExclusive) a.ServerManager = NewServerManager(appName) a.PlaybackManager = NewPlaybackManager(a.bgrndCtx, a.ServerManager, a.Player, &a.Config.Scrobbling) @@ -100,7 +101,7 @@ func (a *App) initMPV() error { p := player.NewWithClientName(a.appName) c := a.Config.LocalPlayback c.InMemoryCacheSizeMB = clamp(c.InMemoryCacheSizeMB, 10, 500) - if err := p.Init(c.AudioExclusive, c.InMemoryCacheSizeMB); err != nil { + if err := p.Init(c.InMemoryCacheSizeMB); err != nil { return fmt.Errorf("failed to initialize mpv player: %s", err.Error()) } a.Player = p diff --git a/backend/playbackmanager.go b/backend/playbackmanager.go index 1db3131..1af7591 100644 --- a/backend/playbackmanager.go +++ b/backend/playbackmanager.go @@ -270,6 +270,14 @@ func (p *PlaybackManager) StopAndClearPlayQueue() { p.playQueue = nil } +func (p *PlaybackManager) SetReplayGainOptions(config ReplayGainConfig) { + p.player.SetReplayGainOptions(player.ReplayGainOptions{ + Mode: player.ReplayGainMode(config.Mode), + PreventClipping: config.PreventClipping, + PreampGain: config.PreampGainDB, + }) +} + // call BEFORE updating p.nowPlayingIdx func (p *PlaybackManager) checkScrobble(playDur time.Duration) { if !p.scrobbleCfg.Enabled || len(p.playQueue) == 0 || p.nowPlayingIdx < 0 { diff --git a/player/player.go b/player/player.go index 15ee9e6..87f6bf8 100644 --- a/player/player.go +++ b/player/player.go @@ -63,6 +63,7 @@ type Player struct { vol int replayGainOpts ReplayGainOptions haveRGainOpts bool + audioExclusive bool status Status seeking bool curPlaylistPos int64 @@ -96,7 +97,7 @@ func NewWithClientName(c string) *Player { // Initializes the Player and makes it ready for playback. // Most Player functions will return ErrUnitialized if called before Init. -func (p *Player) Init(audioExclusive bool, maxCacheMB int) error { +func (p *Player) Init(maxCacheMB int) error { if !p.initialized { m, err := CreateMPV() if err != nil { @@ -118,9 +119,7 @@ func (p *Player) Init(audioExclusive bool, maxCacheMB int) error { } m.SetOption("volume", MPVFormatInt64, p.vol) - if audioExclusive { - m.SetOptionString("audio-exclusive", "yes") - } + p.SetAudioExclusive(p.audioExclusive) if p.haveRGainOpts { p.SetReplayGainOptions(p.replayGainOpts) } @@ -259,7 +258,7 @@ func (p *Player) SetVolume(vol int) error { // Sets the ReplayGain options of the player. // Unlike most Player functions, SetReplayGainOptions can be called -// before Init, to set the initial volume of the player on startup. +// before Init, to set the initial replaygain options of the player on startup. func (p *Player) SetReplayGainOptions(options ReplayGainOptions) error { p.replayGainOpts = options p.haveRGainOpts = true @@ -281,6 +280,20 @@ func (p *Player) SetReplayGainOptions(options ReplayGainOptions) error { return nil } +// Sets the audio exclusive option of the player. +// Unlike most Player functions, SetAudioExclusive can be called +// before Init, to set the initial option of the player on startup. +func (p *Player) SetAudioExclusive(tf bool) { + p.audioExclusive = tf + if p.initialized { + val := "no" + if tf { + val = "yes" + } + p.mpv.SetOptionString("audio-exclusive", val) + } +} + // Gets the current volume of the player. func (p *Player) GetVolume() int { return p.vol diff --git a/ui/controller/controller.go b/ui/controller/controller.go index aa67709..4859b16 100644 --- a/ui/controller/controller.go +++ b/ui/controller/controller.go @@ -306,6 +306,12 @@ func (c *Controller) ShowAboutDialog() { func (c *Controller) ShowSettingsDialog() { dlg := dialogs.NewSettingsDialog(c.App.Config) + dlg.OnReplayGainSettingsChanged = func() { + c.App.PlaybackManager.SetReplayGainOptions(c.App.Config.ReplayGain) + } + dlg.OnAudioExclusiveSettingChanged = func() { + c.App.Player.SetAudioExclusive(c.App.Config.LocalPlayback.AudioExclusive) + } pop := widget.NewModalPopUp(dlg, c.MainWindow.Canvas()) dlg.OnDismiss = func() { pop.Hide() diff --git a/ui/dialogs/settingsdialog.go b/ui/dialogs/settingsdialog.go index f309da0..10930ae 100644 --- a/ui/dialogs/settingsdialog.go +++ b/ui/dialogs/settingsdialog.go @@ -10,7 +10,6 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/data/binding" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/widget" ) @@ -60,6 +59,9 @@ func (s *SettingsDialog) createGeneralTab() *container.TabItem { } } percentEntry.Text = strconv.Itoa(s.config.Scrobbling.ThresholdPercent) + if !s.config.Scrobbling.Enabled { + percentEntry.Disable() + } durationEntry := widgets.NewTextRestrictedEntry(twoDigitValidator) durationEntry.SetMinCharWidth(2) @@ -72,6 +74,9 @@ func (s *SettingsDialog) createGeneralTab() *container.TabItem { val := int(math.Round(float64(secs) / 60.)) durationEntry.Text = strconv.Itoa(val) } + if !s.config.Scrobbling.Enabled { + durationEntry.Disable() + } lastScrobbleText := durationEntry.Text if lastScrobbleText == "" { @@ -91,9 +96,12 @@ func (s *SettingsDialog) createGeneralTab() *container.TabItem { } }) durationEnabled.Checked = s.config.Scrobbling.ThresholdTimeSeconds >= 0 + if !s.config.Scrobbling.Enabled { + durationEnabled.Disable() + } - scrobbleEnabled := widget.NewCheckWithData("Send playback statistics to server", binding.BindBool(&s.config.Scrobbling.Enabled)) - scrobbleEnabled.OnChanged = func(checked bool) { + scrobbleEnabled := widget.NewCheck("Send playback statistics to server", func(checked bool) { + s.config.Scrobbling.Enabled = checked if !checked { percentEntry.Disable() durationEnabled.Disable() @@ -105,7 +113,8 @@ func (s *SettingsDialog) createGeneralTab() *container.TabItem { durationEntry.Enable() } } - } + }) + scrobbleEnabled.Checked = s.config.Scrobbling.Enabled return container.NewTabItem("General", container.NewVBox( widget.NewRichText(&widget.TextSegment{Text: "Scrobbling", Style: boldStyle}), @@ -167,11 +176,17 @@ func (s *SettingsDialog) createPlaybackTab() *container.TabItem { } preampGain.Text = strconv.Itoa(int(initVal)) - preventClipping := widget.NewCheckWithData("", binding.BindBool(&s.config.ReplayGain.PreventClipping)) - preventClipping.OnChanged = func(_ bool) { s.onReplayGainSettingsChanged() } + preventClipping := widget.NewCheck("", func(checked bool) { + s.config.ReplayGain.PreventClipping = checked + s.onReplayGainSettingsChanged() + }) + preventClipping.Checked = s.config.ReplayGain.PreventClipping - audioExclusive := widget.NewCheckWithData("Audio exclusive mode", binding.BindBool(&s.config.LocalPlayback.AudioExclusive)) - audioExclusive.OnChanged = func(_ bool) { s.onAudioExclusiveSettingsChanged() } + audioExclusive := widget.NewCheck("Audio exclusive mode", func(checked bool) { + s.config.LocalPlayback.AudioExclusive = checked + s.onAudioExclusiveSettingsChanged() + }) + audioExclusive.Checked = s.config.LocalPlayback.AudioExclusive return container.NewTabItem("Playback", container.NewVBox( widget.NewRichText(&widget.TextSegment{Text: "ReplayGain", Style: boldStyle}),