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 }