pure playlist navigation
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user