Add modular capture backends, resolution profiles, Wayland support
This commit is contained in:
parent
3b363192f2
commit
80ba9b1b90
16 changed files with 2266 additions and 45 deletions
129
pkg/engine/capture/backends/window_win32.go
Normal file
129
pkg/engine/capture/backends/window_win32.go
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
//go:build windows
|
||||
|
||||
// Windows window capture using BitBlt and DXGI APIs.
|
||||
package backends
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"unsafe"
|
||||
|
||||
"git.cloonar.com/openclawd/iso-bot/pkg/engine/capture"
|
||||
)
|
||||
|
||||
// Win32Config holds configuration for Windows window capture.
|
||||
type Win32Config struct {
|
||||
// WindowTitle is the exact window title to capture.
|
||||
WindowTitle string `yaml:"window_title"`
|
||||
|
||||
// WindowClass is the window class name (alternative to title).
|
||||
WindowClass string `yaml:"window_class"`
|
||||
|
||||
// UseDirectX enables DXGI-based capture for better performance.
|
||||
// Falls back to GDI BitBlt if DXGI fails.
|
||||
UseDirectX bool `yaml:"use_directx"`
|
||||
|
||||
// CaptureCursor includes the mouse cursor in captured frames.
|
||||
CaptureCursor bool `yaml:"capture_cursor"`
|
||||
}
|
||||
|
||||
// Win32Source captures from a Windows window using Win32 APIs.
|
||||
type Win32Source struct {
|
||||
config Win32Config
|
||||
windowHWND uintptr
|
||||
width int
|
||||
height int
|
||||
}
|
||||
|
||||
// NewWin32Source creates a Windows window capture source.
|
||||
func NewWin32Source(configMap map[string]interface{}) (capture.Source, error) {
|
||||
var config Win32Config
|
||||
|
||||
// Extract config from map
|
||||
if title, ok := configMap["window_title"].(string); ok {
|
||||
config.WindowTitle = title
|
||||
}
|
||||
if class, ok := configMap["window_class"].(string); ok {
|
||||
config.WindowClass = class
|
||||
}
|
||||
if dx, ok := configMap["use_directx"].(bool); ok {
|
||||
config.UseDirectX = dx
|
||||
}
|
||||
if cursor, ok := configMap["capture_cursor"].(bool); ok {
|
||||
config.CaptureCursor = cursor
|
||||
}
|
||||
|
||||
// Validate config
|
||||
if config.WindowTitle == "" && config.WindowClass == "" {
|
||||
return nil, fmt.Errorf("either window_title or window_class must be specified")
|
||||
}
|
||||
|
||||
return &Win32Source{
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Name returns a description of this capture source.
|
||||
func (w *Win32Source) Name() string {
|
||||
if w.config.WindowTitle != "" {
|
||||
return fmt.Sprintf("Win32 Window: %s", w.config.WindowTitle)
|
||||
}
|
||||
return fmt.Sprintf("Win32 Window Class: %s", w.config.WindowClass)
|
||||
}
|
||||
|
||||
// Capture grabs a single frame from the window.
|
||||
func (w *Win32Source) Capture() (image.Image, error) {
|
||||
// TODO: Implement Win32 window capture
|
||||
// 1. Find window handle using FindWindow/FindWindowEx
|
||||
// 2. Get window dimensions with GetWindowRect
|
||||
// 3. Create compatible DC and bitmap
|
||||
// 4. Use BitBlt or DXGI to capture window content
|
||||
// 5. Convert to Go image.Image
|
||||
return nil, fmt.Errorf("Win32 capture not implemented yet")
|
||||
}
|
||||
|
||||
// CaptureRegion grabs a sub-region of the window.
|
||||
func (w *Win32Source) CaptureRegion(r capture.Region) (image.Image, error) {
|
||||
// TODO: Implement region capture
|
||||
// Use BitBlt with source coordinates offset by region.X, region.Y
|
||||
return nil, fmt.Errorf("Win32 region capture not implemented yet")
|
||||
}
|
||||
|
||||
// Size returns the window dimensions.
|
||||
func (w *Win32Source) Size() (width, height int) {
|
||||
// TODO: Get actual window size from GetWindowRect
|
||||
return w.width, w.height
|
||||
}
|
||||
|
||||
// Close releases Win32 resources.
|
||||
func (w *Win32Source) Close() error {
|
||||
// TODO: Release DCs, bitmaps, and other Win32 handles
|
||||
return nil
|
||||
}
|
||||
|
||||
// findWindow locates a window by title or class name.
|
||||
func (w *Win32Source) findWindow() (uintptr, error) {
|
||||
// TODO: Use FindWindow/FindWindowEx APIs
|
||||
// Handle both window title and class name searches
|
||||
return 0, fmt.Errorf("window lookup not implemented")
|
||||
}
|
||||
|
||||
// getDXGIOutput attempts to capture using DXGI Desktop Duplication API.
|
||||
func (w *Win32Source) getDXGIOutput() (image.Image, error) {
|
||||
// TODO: Implement DXGI Desktop Duplication
|
||||
// 1. Create DXGI factory and enumerate adapters/outputs
|
||||
// 2. Create output duplication interface
|
||||
// 3. Acquire next frame
|
||||
// 4. Map texture and copy to Go image
|
||||
return nil, fmt.Errorf("DXGI capture not implemented")
|
||||
}
|
||||
|
||||
// getBitBltOutput captures using traditional GDI BitBlt.
|
||||
func (w *Win32Source) getBitBltOutput() (image.Image, error) {
|
||||
// TODO: Implement BitBlt capture
|
||||
// 1. Get window DC with GetWindowDC
|
||||
// 2. Create compatible DC and bitmap
|
||||
// 3. BitBlt window content to bitmap
|
||||
// 4. Get bitmap bits and convert to image.RGBA
|
||||
return nil, fmt.Errorf("BitBlt capture not implemented")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue