Первая версия (CLI-only) #1

Merged
weirdcat merged 26 commits from develop into main 2025-11-27 13:09:27 +03:00
2 changed files with 26 additions and 83 deletions
Showing only changes of commit a7af6f383a - Show all commits

View File

@@ -21,7 +21,5 @@ package screencapturer
type ScreenCapturer interface { type ScreenCapturer interface {
Init() error Init() error
Start() error
Stop() error
Get() (filepath string, err error) Get() (filepath string, err error)
} }

View File

@@ -47,34 +47,36 @@ type wholeScreenCapturer struct {
displayIndex int displayIndex int
displayBounds image.Rectangle displayBounds image.Rectangle
interval int
bufferCount int bufferCount int
tempDirectory string tempDirectory string
initialized bool initialized bool
running bool
files []string files []string
latest string mu sync.RWMutex
done chan struct{}
sync.WaitGroup
mu sync.RWMutex
} }
// Get implements ScreenCapturer. // Get implements ScreenCapturer.
func (w *wholeScreenCapturer) Get() (filepath string, err error) { func (w *wholeScreenCapturer) Get() (filepath string, err error) {
w.mu.RLock() if !w.initialized {
defer w.mu.Unlock() return "", ErrNotInitialized
if !w.initialized { }
return "", ErrNotInitialized
} fp, err := w.captureAndSave()
if w.latest == "" { if err != nil {
return "", errors.New("no screenshot captured yet") w.log.Error("screenshot capture failed", "error", err)
} return "", err
return w.latest, nil }
w.addToBuffer(fp)
return fp, nil
} }
// Init implements ScreenCapturer. // Init implements ScreenCapturer.
func (w *wholeScreenCapturer) Init() (err error) { func (w *wholeScreenCapturer) Init() (err error) {
if w.initialized {
w.log.Debug("wholescreencapturer already initialized, skipping initialization")
return nil
}
displayCount := screenshot.NumActiveDisplays() displayCount := screenshot.NumActiveDisplays()
w.displayIndex = w.config.Screenshot.ScreenIndex % displayCount w.displayIndex = w.config.Screenshot.ScreenIndex % displayCount
@@ -87,9 +89,6 @@ func (w *wholeScreenCapturer) Init() (err error) {
"dy", w.displayBounds.Dy(), "dy", w.displayBounds.Dy(),
) )
w.interval = w.config.Screenshot.Interval
w.log.Debug("screenshot interval set", "interval", w.interval)
w.bufferCount = w.config.Screenshot.BufferCount w.bufferCount = w.config.Screenshot.BufferCount
w.log.Debug("screenshot buffer count set", "count", w.bufferCount) w.log.Debug("screenshot buffer count set", "count", w.bufferCount)
@@ -100,65 +99,10 @@ func (w *wholeScreenCapturer) Init() (err error) {
w.log.Debug("temporary directory created", "path", w.tempDirectory) w.log.Debug("temporary directory created", "path", w.tempDirectory)
w.files = make([]string, 0, w.bufferCount) w.files = make([]string, 0, w.bufferCount)
w.latest = ""
w.initialized = true w.initialized = true
return nil return nil
} }
// Start implements ScreenCapturer.
func (w *wholeScreenCapturer) Start() error {
if !w.initialized {
return ErrNotInitialized
}
if w.running {
w.log.Debug("wholescreencapturer is already running, ignoring start")
return nil
}
w.running = true
w.Go(func() {
w.captureLoop()
})
w.log.Debug("wholescreencapturer started")
return nil
}
// Stop implements ScreenCapturer.
func (w *wholeScreenCapturer) Stop() error {
if !w.initialized {
return ErrNotInitialized
}
if !w.running {
w.log.Debug("wholescreencapturer is not running, ignoring stop")
return nil
}
w.log.Debug("stopping wholescreencapturer")
close(w.done)
w.Wait()
w.running = false
w.log.Debug("wholescreencapturer stopped")
return nil
}
func (w *wholeScreenCapturer) captureLoop() {
ticker := time.NewTicker(time.Duration(w.interval) * time.Second)
defer ticker.Stop()
for {
select {
case <-w.done:
w.log.Debug("capture loop stopped")
return
case <-ticker.C:
fp, err := w.captureAndSave()
if err != nil {
w.log.Error("screenshot capture failed", "error", err)
continue
}
w.addToBuffer(fp)
}
}
}
func (w *wholeScreenCapturer) captureAndSave() (string, error) { func (w *wholeScreenCapturer) captureAndSave() (string, error) {
img, err := screenshot.CaptureRect(w.displayBounds) img, err := screenshot.CaptureRect(w.displayBounds)
if err != nil { if err != nil {
@@ -191,7 +135,6 @@ func (w *wholeScreenCapturer) addToBuffer(fp string) {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() defer w.mu.Unlock()
w.files = append(w.files, fp) w.files = append(w.files, fp)
w.latest = fp
if len(w.files) > w.bufferCount { if len(w.files) > w.bufferCount {
old := w.files[0] old := w.files[0]
@@ -214,7 +157,6 @@ func NewWholeScreenCapturer(
capturer := &wholeScreenCapturer{ capturer := &wholeScreenCapturer{
config: config, config: config,
log: log, log: log,
done: make(chan struct{}),
} }
lc.Append(fx.StopHook(func(ctx context.Context) error { lc.Append(fx.StopHook(func(ctx context.Context) error {
if !capturer.initialized { if !capturer.initialized {
@@ -222,15 +164,18 @@ func NewWholeScreenCapturer(
return nil return nil
} }
log.Debug("stopping wholescreencapturer") log.Debug("cleaning up wholescreencapturer")
err := capturer.Stop() // Clean up all screenshot files
if err != nil { capturer.mu.Lock()
log.Error("failed to stop wholescreencapturer gracefully") defer capturer.mu.Unlock()
return err for _, file := range capturer.files {
if err := os.Remove(file); err != nil {
log.Warn("failed to remove screenshot file during cleanup", "path", file, "error", err)
}
} }
err = os.RemoveAll(capturer.tempDirectory) err := os.RemoveAll(capturer.tempDirectory)
if err != nil { if err != nil {
log.Error("failed to remove temp directory") log.Error("failed to remove temp directory")
return err return err