PlaylistController
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package playback
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type PlaylistController struct {
|
||||
playlist Playlist
|
||||
retry RetryPolicy
|
||||
sessions chan<- SessionCommand
|
||||
|
||||
mu sync.RWMutex
|
||||
snapshot PlaylistSnapshot
|
||||
hasSnapshot bool
|
||||
}
|
||||
|
||||
type PlaylistSnapshot struct {
|
||||
State PlaylistState
|
||||
Entry PlaylistEntry
|
||||
}
|
||||
|
||||
var (
|
||||
ErrNilSessionCommandChannel = errors.New("session-command channel is nil")
|
||||
)
|
||||
|
||||
func NewPlaylistController(
|
||||
playlist Playlist,
|
||||
retry RetryPolicy,
|
||||
sessions chan<- SessionCommand,
|
||||
) (*PlaylistController, error) {
|
||||
if err := playlist.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := retry.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sessions == nil {
|
||||
return nil, ErrNilSessionCommandChannel
|
||||
}
|
||||
return &PlaylistController{
|
||||
playlist: playlist,
|
||||
retry: retry,
|
||||
sessions: sessions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *PlaylistController) Run(
|
||||
ctx context.Context,
|
||||
commands <-chan PlaylistCommand,
|
||||
) error {
|
||||
state := PlaylistState{}
|
||||
c.publish(state)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
|
||||
case command, ok := <-commands:
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
next, sessionCommand, apply, err := ApplyPlaylistSelection(
|
||||
c.playlist,
|
||||
state,
|
||||
command,
|
||||
c.retry,
|
||||
)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if apply {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case c.sessions <- sessionCommand:
|
||||
}
|
||||
}
|
||||
|
||||
state = next
|
||||
c.publish(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *PlaylistController) Snapshot() (PlaylistSnapshot, bool) {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
return c.snapshot, c.hasSnapshot
|
||||
}
|
||||
|
||||
func (c *PlaylistController) publish(state PlaylistState) {
|
||||
entry, _ := state.Entry(c.playlist)
|
||||
|
||||
c.mu.Lock()
|
||||
c.snapshot = PlaylistSnapshot{State: state, Entry: entry}
|
||||
c.hasSnapshot = true
|
||||
c.mu.Unlock()
|
||||
}
|
||||
Reference in New Issue
Block a user