94 lines
2.3 KiB
Go
94 lines
2.3 KiB
Go
package playback
|
|
|
|
import "errors"
|
|
|
|
type PlaylistCommandKind uint8
|
|
|
|
const (
|
|
PlaylistSelect PlaylistCommandKind = iota + 1
|
|
PlaylistNext
|
|
PlaylistPrevious
|
|
)
|
|
|
|
type PlaylistCommand struct {
|
|
Kind PlaylistCommandKind
|
|
Index int
|
|
}
|
|
|
|
type PlaylistState struct {
|
|
CurrentIndex int
|
|
HasSelection bool
|
|
}
|
|
|
|
var (
|
|
ErrPlaylistEmpty = errors.New("playlist is empty")
|
|
ErrPlaylistIndexOutOfRange = errors.New("playlist index is out of range")
|
|
ErrUnknownPlaylistCommand = errors.New("unknown playlist command")
|
|
)
|
|
|
|
func ApplyPlaylistCommand(
|
|
playlist Playlist,
|
|
current PlaylistState,
|
|
command PlaylistCommand,
|
|
) (PlaylistState, error) {
|
|
if err := playlist.Validate(); err != nil {
|
|
return current, err
|
|
}
|
|
if len(playlist.Entries) == 0 {
|
|
return current, ErrPlaylistEmpty
|
|
}
|
|
|
|
lastIndex := len(playlist.Entries) - 1
|
|
switch command.Kind {
|
|
case PlaylistSelect:
|
|
if command.Index < 0 || command.Index > lastIndex {
|
|
return current, ErrPlaylistIndexOutOfRange
|
|
}
|
|
return PlaylistState{CurrentIndex: command.Index, HasSelection: true}, nil
|
|
|
|
case PlaylistNext:
|
|
if !current.HasSelection {
|
|
return PlaylistState{CurrentIndex: 0, HasSelection: true}, nil
|
|
}
|
|
if current.CurrentIndex < 0 || current.CurrentIndex > lastIndex {
|
|
return current, ErrPlaylistIndexOutOfRange
|
|
}
|
|
if current.CurrentIndex == lastIndex {
|
|
if playlist.Loop {
|
|
return PlaylistState{CurrentIndex: 0, HasSelection: true}, nil
|
|
}
|
|
return current, nil
|
|
}
|
|
return PlaylistState{CurrentIndex: current.CurrentIndex + 1, HasSelection: true}, nil
|
|
|
|
case PlaylistPrevious:
|
|
if !current.HasSelection {
|
|
index := 0
|
|
if playlist.Loop {
|
|
index = lastIndex
|
|
}
|
|
return PlaylistState{CurrentIndex: index, HasSelection: true}, nil
|
|
}
|
|
if current.CurrentIndex < 0 || current.CurrentIndex > lastIndex {
|
|
return current, ErrPlaylistIndexOutOfRange
|
|
}
|
|
if current.CurrentIndex == 0 {
|
|
if playlist.Loop {
|
|
return PlaylistState{CurrentIndex: lastIndex, HasSelection: true}, nil
|
|
}
|
|
return current, nil
|
|
}
|
|
return PlaylistState{CurrentIndex: current.CurrentIndex - 1, HasSelection: true}, nil
|
|
|
|
default:
|
|
return current, ErrUnknownPlaylistCommand
|
|
}
|
|
}
|
|
|
|
func (s PlaylistState) Entry(playlist Playlist) (PlaylistEntry, bool) {
|
|
if !s.HasSelection || s.CurrentIndex < 0 || s.CurrentIndex >= len(playlist.Entries) {
|
|
return PlaylistEntry{}, false
|
|
}
|
|
return playlist.Entries[s.CurrentIndex], true
|
|
}
|