122 lines
2.7 KiB
Go
122 lines
2.7 KiB
Go
package playback
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
ErrPlaylistFeedUUIDRequired = errors.New("playlist feed UUID is required when its domain is configured")
|
|
ErrPlaylistEntryEmpty = errors.New("playlist entry must contain at least one feed")
|
|
ErrPlaylistSyncFeedsRequired = errors.New("synchronized playlist entry requires both video and audio feeds")
|
|
ErrPlaylistDurationNegative = errors.New("playlist entry duration cannot be negative")
|
|
ErrPlaylistFailurePolicy = errors.New("invalid playlist failure policy")
|
|
)
|
|
|
|
type PlaylistFailurePolicy uint8
|
|
|
|
const (
|
|
PlaylistFailureWait PlaylistFailurePolicy = iota
|
|
PlaylistFailureNext
|
|
)
|
|
|
|
func (p PlaylistFailurePolicy) String() string {
|
|
switch p {
|
|
case PlaylistFailureWait:
|
|
return "wait"
|
|
case PlaylistFailureNext:
|
|
return "next"
|
|
default:
|
|
return fmt.Sprintf("PlaylistFailurePolicy(%d)", uint8(p))
|
|
}
|
|
}
|
|
|
|
func (p PlaylistFailurePolicy) Validate() error {
|
|
if p != PlaylistFailureWait && p != PlaylistFailureNext {
|
|
return ErrPlaylistFailurePolicy
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type PlaylistFeed struct {
|
|
Domain string
|
|
UUID string
|
|
}
|
|
|
|
type PlaylistEntry struct {
|
|
Name string
|
|
Video PlaylistFeed
|
|
Audio PlaylistFeed
|
|
SyncRequested bool
|
|
Duration time.Duration
|
|
}
|
|
|
|
type Playlist struct {
|
|
Entries []PlaylistEntry
|
|
Loop bool
|
|
OnFailure PlaylistFailurePolicy
|
|
}
|
|
|
|
func (f PlaylistFeed) IsConfigured() bool {
|
|
return f.UUID != ""
|
|
}
|
|
|
|
func (f PlaylistFeed) Validate() error {
|
|
if f.UUID != "" && f.Domain == "" {
|
|
return ErrFeedDomainRequired
|
|
}
|
|
if f.Domain != "" && f.UUID == "" {
|
|
return ErrPlaylistFeedUUIDRequired
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (e PlaylistEntry) Validate() error {
|
|
if err := e.Video.Validate(); err != nil {
|
|
return fmt.Errorf("video: %w", err)
|
|
}
|
|
if err := e.Audio.Validate(); err != nil {
|
|
return fmt.Errorf("audio: %w", err)
|
|
}
|
|
if !e.Video.IsConfigured() && !e.Audio.IsConfigured() {
|
|
return ErrPlaylistEntryEmpty
|
|
}
|
|
if e.SyncRequested && (!e.Video.IsConfigured() || !e.Audio.IsConfigured()) {
|
|
return ErrPlaylistSyncFeedsRequired
|
|
}
|
|
if e.Duration < 0 {
|
|
return ErrPlaylistDurationNegative
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p Playlist) Validate() error {
|
|
if err := p.OnFailure.Validate(); err != nil {
|
|
return err
|
|
}
|
|
for index, entry := range p.Entries {
|
|
if err := entry.Validate(); err != nil {
|
|
return fmt.Errorf("playlist entry %d: %w", index, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (e PlaylistEntry) SessionConfig(retry RetryPolicy) SessionConfig {
|
|
return SessionConfig{
|
|
Video: FeedConfig{
|
|
Domain: e.Video.Domain,
|
|
UUID: e.Video.UUID,
|
|
Active: e.Video.UUID != "",
|
|
},
|
|
Audio: FeedConfig{
|
|
Domain: e.Audio.Domain,
|
|
UUID: e.Audio.UUID,
|
|
Active: e.Audio.UUID != "",
|
|
},
|
|
SyncRequested: e.SyncRequested,
|
|
Retry: retry,
|
|
}
|
|
}
|