Cthulhu is no longer a fork. Now it is a screen reader written in Golang.
This commit is contained in:
1 parent
a998fe67de
commit
069fc674dc
708 files changed
+112482
-532
No files matched your search
@@ -0,0 +1,96 @@
|
||||
// Cthulhu screen reader.
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/config"
|
||||
"git.stormux.org/storm/cthulhu/internal/input"
|
||||
)
|
||||
|
||||
// runtimeWorkers owns the event-loop companion workers. Only the event loop
|
||||
// consumes reviewRequests; command and clipboard workers send to bounded queues.
|
||||
// Each done channel closes after its worker exits. commandError is read after
|
||||
// commandDone closes, so no additional synchronization is needed.
|
||||
type runtimeWorkers struct {
|
||||
reviewRequests <-chan struct{}
|
||||
attributeRequests <-chan struct{}
|
||||
commandDone <-chan struct{}
|
||||
clipboardDone <-chan struct{}
|
||||
inputDone <-chan struct{}
|
||||
copyDone <-chan struct{}
|
||||
autoClipboardDone <-chan struct{}
|
||||
commandError error
|
||||
internalUIDone <-chan struct{}
|
||||
internalUI *internalUI
|
||||
}
|
||||
|
||||
// startRuntimeWorkers preserves startup order: clipboard, command, input, copy.
|
||||
// The caller cancels ctx and joins these workers before stopping output services.
|
||||
func startRuntimeWorkers(ctx context.Context, command commandRuntime, inputListener InputListener, settings config.Settings, copyChanges <-chan struct{}, braille *brailleWorker) *runtimeWorkers {
|
||||
speech := gatedSpeech{speech: command.speechOutput, gate: command.focusGate}
|
||||
learn := &learnModePresenter{tentacles: command.tentacles, ctx: ctx, logger: command.logger, speech: speech, braille: braille, live: command.live}
|
||||
if owner, ok := command.commands.(interface{ BrowseNavigationEnabled() bool }); ok {
|
||||
learn.browse = owner
|
||||
}
|
||||
command.learn = learn
|
||||
clipboardRequests := make(chan struct{}, 1)
|
||||
clipboardDone := runClipboardWorker(ctx, clipboardRequests, speech, readClipboardMessage)
|
||||
command.clipboardRequests = clipboardRequests
|
||||
reviewRequests := make(chan struct{}, 1)
|
||||
command.reviewRequests = reviewRequests
|
||||
attributeRequests := make(chan struct{}, 1)
|
||||
command.attributeRequests = attributeRequests
|
||||
commandDone := make(chan struct{})
|
||||
workers := &runtimeWorkers{
|
||||
reviewRequests: reviewRequests,
|
||||
attributeRequests: attributeRequests,
|
||||
commandDone: commandDone,
|
||||
clipboardDone: clipboardDone,
|
||||
}
|
||||
if keys, ok := command.commands.(internalUIKeys); ok {
|
||||
ui := &internalUI{notices: make(chan internalUINotice, 4), keys: keys, actions: command.actionSource, interest: command.objectReview, speech: speech, braille: braille, gate: command.focusGate, events: make(chan input.CommandEvent, 32), requests: make(chan internalUIRequest, 1), done: make(chan struct{})}
|
||||
command.internalUI = ui
|
||||
if command.tentacles != nil {
|
||||
command.tentacles.forms = ui
|
||||
command.tentacles.focusedItem = focusedTentacleItem(command.actionSource, ui)
|
||||
}
|
||||
workers.internalUI = ui
|
||||
workers.internalUIDone = ui.done
|
||||
go ui.run(ctx)
|
||||
}
|
||||
go func() {
|
||||
defer close(commandDone)
|
||||
workers.commandError = command.run(ctx)
|
||||
}()
|
||||
|
||||
inputDone := make(chan struct{})
|
||||
if inputListener != nil {
|
||||
go func() {
|
||||
defer close(inputDone)
|
||||
processInputEvents(ctx, command.logger, speech, inputListener, inputEchoSettingsFromConfig(settings), command.live, command.commands, command.ocr)
|
||||
}()
|
||||
} else {
|
||||
close(inputDone)
|
||||
}
|
||||
workers.inputDone = inputDone
|
||||
workers.copyDone = runCopyFeedback(ctx, copyChanges, inputListener, speech, command.live, command.ocr)
|
||||
workers.autoClipboardDone = run_automatic_clipboard(ctx, command.logger, command.live, command.focusGate, speech)
|
||||
return workers
|
||||
}
|
||||
Reference in new issue
Block a user