Refactoring #3
@@ -0,0 +1,127 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
mxladapter "mxl-player/internal/adapter/mxl"
|
||||
"mxl-player/internal/output"
|
||||
"mxl-player/internal/playback"
|
||||
)
|
||||
|
||||
type playerPlayback struct {
|
||||
Controller *playback.SessionController
|
||||
Commands chan playback.SessionCommand
|
||||
Video *playback.VideoBridge
|
||||
Status *playback.StatusStore
|
||||
Audio *output.SDLAudioSink
|
||||
}
|
||||
|
||||
func newPlayerPlayback(
|
||||
audioDevice uint32,
|
||||
retry playback.RetryPolicy,
|
||||
) (*playerPlayback, error) {
|
||||
videoBridge := playback.NewVideoBridge()
|
||||
statusStore := playback.NewStatusStore()
|
||||
audioSink := output.NewSDLAudioSink(audioDevice)
|
||||
|
||||
observe := func(status playback.Status) {
|
||||
statusStore.Observe(status)
|
||||
|
||||
if status.Err != nil {
|
||||
log.Printf(
|
||||
"%s: state=%v attempt=%d failed=%d: %v",
|
||||
status.Unit,
|
||||
status.State,
|
||||
status.Attempt,
|
||||
status.FailedAttempts,
|
||||
status.Err,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf(
|
||||
"%s: state=%v attempt=%d failed=%d",
|
||||
status.Unit,
|
||||
status.State,
|
||||
status.Attempt,
|
||||
status.FailedAttempts,
|
||||
)
|
||||
}
|
||||
|
||||
videoWorker, err := playback.NewVideoWorker(
|
||||
mxladapter.VideoFactory{},
|
||||
videoBridge,
|
||||
retry,
|
||||
mxladapter.ShouldRetry,
|
||||
observe,
|
||||
)
|
||||
if err != nil {
|
||||
_ = audioSink.Close()
|
||||
return nil, err
|
||||
}
|
||||
videoSlot, err := playback.NewVideoSlot(videoWorker)
|
||||
if err != nil {
|
||||
_ = audioSink.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
audioWorker, err := playback.NewAudioWorker(
|
||||
mxladapter.AudioFactory{},
|
||||
audioSink,
|
||||
retry,
|
||||
mxladapter.ShouldRetry,
|
||||
observe,
|
||||
)
|
||||
if err != nil {
|
||||
_ = audioSink.Close()
|
||||
return nil, err
|
||||
}
|
||||
audioSlot, err := playback.NewAudioSlot(audioWorker)
|
||||
if err != nil {
|
||||
_ = audioSink.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
syncWorker, err := playback.NewSyncWorker(
|
||||
mxladapter.SyncFactory{},
|
||||
videoBridge,
|
||||
audioSink,
|
||||
retry,
|
||||
mxladapter.ShouldRetry,
|
||||
observe,
|
||||
)
|
||||
if err != nil {
|
||||
_ = audioSink.Close()
|
||||
return nil, err
|
||||
}
|
||||
syncSlot, err := playback.NewSyncSlot(syncWorker)
|
||||
if err != nil {
|
||||
_ = audioSink.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
controller, err := playback.NewSessionController(
|
||||
videoSlot,
|
||||
audioSlot,
|
||||
syncSlot,
|
||||
func(video, audio playback.FeedConfig) bool {
|
||||
return video.Domain == audio.Domain
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
_ = audioSink.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &playerPlayback{
|
||||
Controller: controller,
|
||||
Commands: make(chan playback.SessionCommand, 32),
|
||||
Video: videoBridge,
|
||||
Status: statusStore,
|
||||
Audio: audioSink,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *playerPlayback) Close() error {
|
||||
return p.Audio.Close()
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"mxl-player/internal/playback"
|
||||
)
|
||||
|
||||
func validRuntimeRetryPolicy() playback.RetryPolicy {
|
||||
return playback.RetryPolicy{
|
||||
MaxAttempts: 3,
|
||||
InitialDelay: time.Millisecond,
|
||||
MaxDelay: time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPlayerPlaybackBuildsCompleteRuntime(t *testing.T) {
|
||||
runtime, err := newPlayerPlayback(123, validRuntimeRetryPolicy())
|
||||
if err != nil {
|
||||
t.Fatalf("newPlayerPlayback() error = %v", err)
|
||||
}
|
||||
if runtime.Controller == nil || runtime.Video == nil || runtime.Status == nil || runtime.Audio == nil {
|
||||
t.Fatalf("newPlayerPlayback() = %#v", runtime)
|
||||
}
|
||||
if runtime.Commands == nil || cap(runtime.Commands) != 32 {
|
||||
t.Fatalf("command channel = %#v, capacity = %d", runtime.Commands, cap(runtime.Commands))
|
||||
}
|
||||
if err := runtime.Close(); err != nil {
|
||||
t.Fatalf("Close() error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPlayerPlaybackRejectsInvalidRetryPolicy(t *testing.T) {
|
||||
runtime, err := newPlayerPlayback(123, playback.RetryPolicy{})
|
||||
if runtime != nil {
|
||||
t.Fatalf("newPlayerPlayback() runtime = %#v, want nil", runtime)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("newPlayerPlayback() error is nil")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user