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 }