iso-bot/pkg/engine/capture/backends/registry.go

142 lines
No EOL
4 KiB
Go

// Package backends provides modular screen capture implementations.
//
// Supports various capture sources:
// - Window capture (Win32, X11)
// - Wayland desktop capture
// - VNC client capture
// - SPICE capture for VMs
// - Monitor/screen region capture
// - File-based capture (for testing)
package backends
import (
"fmt"
"strings"
"git.cloonar.com/openclawd/iso-bot/pkg/engine/capture"
)
// BackendType identifies a capture backend implementation.
type BackendType string
const (
BackendWindowWin32 BackendType = "window_win32"
BackendWindowX11 BackendType = "window_x11"
BackendWayland BackendType = "wayland"
BackendVNC BackendType = "vnc"
BackendSpice BackendType = "spice"
BackendMonitor BackendType = "monitor"
BackendFile BackendType = "file"
)
// BackendInfo describes a capture backend.
type BackendInfo struct {
Type BackendType
Name string
Description string
Available bool // true if backend can be used on this platform
}
// Registry manages available capture backends.
type Registry struct {
backends map[BackendType]func(map[string]interface{}) (capture.Source, error)
}
// NewRegistry creates a new backend registry.
func NewRegistry() *Registry {
return &Registry{
backends: make(map[BackendType]func(map[string]interface{}) (capture.Source, error)),
}
}
// Register registers a backend constructor.
func (r *Registry) Register(backendType BackendType, constructor func(map[string]interface{}) (capture.Source, error)) {
r.backends[backendType] = constructor
}
// Create creates a capture source of the specified type with the given config.
func (r *Registry) Create(backendType BackendType, config map[string]interface{}) (capture.Source, error) {
constructor, exists := r.backends[backendType]
if !exists {
return nil, fmt.Errorf("backend %q not registered", backendType)
}
return constructor(config)
}
// ListAvailable returns information about available backends.
func (r *Registry) ListAvailable() []BackendInfo {
var infos []BackendInfo
for backendType := range r.backends {
info := BackendInfo{
Type: backendType,
Available: true,
}
switch backendType {
case BackendWindowWin32:
info.Name = "Windows Window Capture"
info.Description = "Capture specific window using BitBlt/DXGI APIs"
case BackendWindowX11:
info.Name = "X11 Window Capture"
info.Description = "Capture specific window using XGetImage"
case BackendWayland:
info.Name = "Wayland Screen Capture"
info.Description = "Screen capture via PipeWire/xdg-desktop-portal"
case BackendVNC:
info.Name = "VNC Client Capture"
info.Description = "Capture frames from VNC server"
case BackendSpice:
info.Name = "SPICE VM Capture"
info.Description = "Capture from QEMU/KVM SPICE display"
case BackendMonitor:
info.Name = "Monitor Capture"
info.Description = "Full screen or monitor region capture"
case BackendFile:
info.Name = "File Input"
info.Description = "Read from image files or video streams"
}
infos = append(infos, info)
}
return infos
}
// ParseBackendType parses a backend type string.
func ParseBackendType(s string) (BackendType, error) {
switch strings.ToLower(s) {
case "window_win32":
return BackendWindowWin32, nil
case "window_x11":
return BackendWindowX11, nil
case "wayland":
return BackendWayland, nil
case "vnc":
return BackendVNC, nil
case "spice":
return BackendSpice, nil
case "monitor":
return BackendMonitor, nil
case "file":
return BackendFile, nil
default:
return "", fmt.Errorf("unknown backend type: %q", s)
}
}
// GetDefault returns the default backend registry with all available backends registered.
func GetDefault() *Registry {
reg := NewRegistry()
// Register platform-specific backends
reg.Register(BackendWindowWin32, NewWin32Source)
reg.Register(BackendWindowX11, NewX11Source)
reg.Register(BackendWayland, NewWaylandSource)
reg.Register(BackendVNC, NewVNCSource)
reg.Register(BackendSpice, NewSpiceSource)
reg.Register(BackendMonitor, NewMonitorSource)
reg.Register(BackendFile, NewFileSource)
return reg
}