- Add GStreamer as mandatory core dependency in install.sh - Create controller_gstreamer.go wrapping GStreamerPlayer - Add missing methods to GStreamerPlayer (SetWindow, Stop, SetFullScreen) - Fix GstSeekFlags type casting issue - Update build scripts to always use -tags gstreamer - Update controller_linux.go build tag to exclude when gstreamer enabled - Add comprehensive migration documentation GStreamer replaces the broken FFmpeg pipe-based UnifiedPlayer. GStreamer 1.26+ provides frame-accurate seeking and reliable A/V sync. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
137 lines
3.7 KiB
Go
137 lines
3.7 KiB
Go
//go:build gstreamer
|
|
|
|
package player
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.leaktechnologies.dev/stu/VideoTools/internal/logging"
|
|
)
|
|
|
|
// newController creates a GStreamer-based controller for embedded video playback
|
|
func newController() Controller {
|
|
config := Config{
|
|
Backend: BackendAuto,
|
|
WindowWidth: 640,
|
|
WindowHeight: 360,
|
|
Volume: 1.0,
|
|
Muted: false,
|
|
AutoPlay: false,
|
|
HardwareAccel: false,
|
|
PreviewMode: false, // Full playback mode
|
|
AudioOutput: "auto",
|
|
VideoOutput: "rgb24",
|
|
CacheEnabled: true,
|
|
CacheSize: 64 * 1024 * 1024,
|
|
LogLevel: LogInfo,
|
|
}
|
|
|
|
player, err := NewGStreamerPlayer(config)
|
|
if err != nil {
|
|
logging.Error(logging.CatPlayer, "Failed to create GStreamer player: %v", err)
|
|
return &stubController{}
|
|
}
|
|
|
|
logging.Info(logging.CatPlayer, "GStreamer controller initialized (GStreamer %s)", "1.26+")
|
|
return &gstreamerController{
|
|
player: player,
|
|
}
|
|
}
|
|
|
|
// gstreamerController wraps GStreamerPlayer to implement the Controller interface
|
|
type gstreamerController struct {
|
|
player *GStreamerPlayer
|
|
}
|
|
|
|
func (c *gstreamerController) Load(path string, offset float64) error {
|
|
if c.player == nil {
|
|
return fmt.Errorf("GStreamer player not initialized")
|
|
}
|
|
|
|
offsetDuration := time.Duration(offset * float64(time.Second))
|
|
logging.Debug(logging.CatPlayer, "Loading video: path=%s offset=%.3fs", path, offset)
|
|
|
|
return c.player.Load(path, offsetDuration)
|
|
}
|
|
|
|
func (c *gstreamerController) SetWindow(x, y, w, h int) {
|
|
if c.player == nil {
|
|
return
|
|
}
|
|
c.player.SetWindow(x, y, w, h)
|
|
}
|
|
|
|
func (c *gstreamerController) Play() error {
|
|
if c.player == nil {
|
|
return fmt.Errorf("GStreamer player not initialized")
|
|
}
|
|
return c.player.Play()
|
|
}
|
|
|
|
func (c *gstreamerController) Pause() error {
|
|
if c.player == nil {
|
|
return fmt.Errorf("GStreamer player not initialized")
|
|
}
|
|
return c.player.Pause()
|
|
}
|
|
|
|
func (c *gstreamerController) Seek(offset float64) error {
|
|
if c.player == nil {
|
|
return fmt.Errorf("GStreamer player not initialized")
|
|
}
|
|
|
|
offsetDuration := time.Duration(offset * float64(time.Second))
|
|
return c.player.SeekToTime(offsetDuration)
|
|
}
|
|
|
|
func (c *gstreamerController) SetVolume(level float64) error {
|
|
if c.player == nil {
|
|
return fmt.Errorf("GStreamer player not initialized")
|
|
}
|
|
|
|
// Controller uses 0-100 scale, GStreamer uses 0.0-1.0
|
|
normalizedLevel := level / 100.0
|
|
return c.player.SetVolume(normalizedLevel)
|
|
}
|
|
|
|
func (c *gstreamerController) FullScreen() error {
|
|
if c.player == nil {
|
|
return fmt.Errorf("GStreamer player not initialized")
|
|
}
|
|
return c.player.SetFullScreen(true)
|
|
}
|
|
|
|
func (c *gstreamerController) Stop() error {
|
|
if c.player == nil {
|
|
return fmt.Errorf("GStreamer player not initialized")
|
|
}
|
|
return c.player.Stop()
|
|
}
|
|
|
|
func (c *gstreamerController) Close() {
|
|
if c.player != nil {
|
|
c.player.Close()
|
|
}
|
|
}
|
|
|
|
// stubController provides a no-op implementation when GStreamer fails to initialize
|
|
type stubController struct{}
|
|
|
|
func (s *stubController) Load(path string, offset float64) error {
|
|
return fmt.Errorf("GStreamer player not available")
|
|
}
|
|
|
|
func (s *stubController) SetWindow(x, y, w, h int) {}
|
|
func (s *stubController) Play() error { return fmt.Errorf("GStreamer player not available") }
|
|
func (s *stubController) Pause() error { return fmt.Errorf("GStreamer player not available") }
|
|
func (s *stubController) Seek(offset float64) error {
|
|
return fmt.Errorf("GStreamer player not available")
|
|
}
|
|
func (s *stubController) SetVolume(level float64) error {
|
|
return fmt.Errorf("GStreamer player not available")
|
|
}
|
|
func (s *stubController) FullScreen() error { return fmt.Errorf("GStreamer player not available") }
|
|
func (s *stubController) Stop() error { return fmt.Errorf("GStreamer player not available") }
|
|
func (s *stubController) Close() {}
|