78 lines
2.6 KiB
Go
78 lines
2.6 KiB
Go
package mujica
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"github.com/egoist/mygo/ui"
|
|
)
|
|
|
|
// LoopMode is how playback repeats. The zero value repeats nothing.
|
|
type LoopMode int
|
|
|
|
const (
|
|
LoopOff LoopMode = iota
|
|
LoopAll
|
|
LoopOne
|
|
)
|
|
|
|
// next cycles off, all, one.
|
|
func (m LoopMode) next() LoopMode { return (m + 1) % 3 }
|
|
|
|
// MediaControlsState is what the caller's playback reports.
|
|
type MediaControlsState struct {
|
|
Playing bool
|
|
Loop LoopMode
|
|
Shuffle bool
|
|
// NoPrevious and NoNext disable those buttons at the ends.
|
|
NoPrevious, NoNext bool
|
|
}
|
|
|
|
// MediaControlsOptions are the callbacks; every one is required.
|
|
type MediaControlsOptions struct {
|
|
OnPrevious, OnPlay, OnPause, OnNext func()
|
|
OnLoop func(LoopMode)
|
|
OnShuffle func(bool)
|
|
Disabled bool
|
|
}
|
|
|
|
// MediaControls are previous, play, next, loop and shuffle buttons.
|
|
func MediaControls(c *ui.Context, st MediaControlsState, opts MediaControlsOptions) *ui.Element {
|
|
if opts.OnPrevious == nil || opts.OnPlay == nil || opts.OnPause == nil || opts.OnNext == nil || opts.OnLoop == nil || opts.OnShuffle == nil {
|
|
panic("mujica: MediaControls needs every callback")
|
|
}
|
|
if st.Loop < LoopOff || st.Loop > LoopOne {
|
|
panic(fmt.Sprintf("mujica: unknown LoopMode %d", st.Loop))
|
|
}
|
|
row := ui.Row(c).Gap(Density(c).Unit()).AlignItems(ui.Center).FocusGroup(ui.Horizontal).Role(ui.RoleToolbar).
|
|
Label(msg(c, "media_controls.label")).Disabled(opts.Disabled)
|
|
row.Children(func() {
|
|
shuffle := mediaToggleAction(c, mediaShuffle, msg(c, "media_controls.shuffle"), st.Shuffle)
|
|
if shuffle.Clicked() && !shuffle.IsDisabled() {
|
|
slog.Debug("mujica: media_controls shuffle", "on", !st.Shuffle)
|
|
opts.OnShuffle(!st.Shuffle)
|
|
}
|
|
prev := iconAction(c, mediaPrev, msg(c, "media_controls.previous")).Disabled(st.NoPrevious)
|
|
if prev.Clicked() && !prev.IsDisabled() {
|
|
slog.Debug("mujica: media_controls previous")
|
|
opts.OnPrevious()
|
|
}
|
|
mediaPlayToggle(c, st.Playing, opts.OnPlay, opts.OnPause)
|
|
next := iconAction(c, mediaNext, msg(c, "media_controls.next")).Disabled(st.NoNext)
|
|
if next.Clicked() && !next.IsDisabled() {
|
|
slog.Debug("mujica: media_controls next")
|
|
opts.OnNext()
|
|
}
|
|
icon := mediaRepeat
|
|
if st.Loop == LoopOne {
|
|
icon = mediaRepeatOne
|
|
}
|
|
loop := mediaToggleAction(c, icon, msg(c, []string{"media_controls.loopOff", "media_controls.loopAll", "media_controls.loopOne"}[st.Loop]), st.Loop != LoopOff)
|
|
if loop.Clicked() && !loop.IsDisabled() {
|
|
slog.Debug("mujica: media_controls loop", "mode", st.Loop.next())
|
|
opts.OnLoop(st.Loop.next())
|
|
}
|
|
})
|
|
return row
|
|
}
|