// 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 }