128 lines
2.4 KiB
Go
128 lines
2.4 KiB
Go
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()
|
|
}
|