Fix panning sounds after scrolling.
This commit is contained in:
1 parent
b2f558c26c
commit
8e76d2341c
14 files changed
+338
-17
No files matched your search
@@ -320,6 +320,7 @@ func presentDocumentResult(logger *slog.Logger, speech speechEnqueuer, result re
|
||||
"source_path", result.DocumentPosition.Object.ID().Path,
|
||||
"virtual_caret_offset", result.DocumentPosition.Offset,
|
||||
"caret_sync_error", result.CaretErr,
|
||||
"sound_geometry_error", result.DocumentSoundErr,
|
||||
"braille_line_available", result.DocumentBrailleLine != nil,
|
||||
"braille_read_error", result.DocumentBrailleErr)
|
||||
}
|
||||
@@ -406,6 +407,25 @@ func presentDocumentResult(logger *slog.Logger, speech speechEnqueuer, result re
|
||||
fallbackText = fallbackSpeech.Text
|
||||
}
|
||||
}
|
||||
if len(cues) > 0 && logger.Enabled(context.Background(), slog.LevelDebug) {
|
||||
// Record the captured geometry actually used for cue generation.
|
||||
// Linked headings use the link's geometry independently of the heading.
|
||||
attributes := []any{
|
||||
"bus", result.DocumentPosition.Snapshot.BusName,
|
||||
"source_path", result.DocumentPosition.Snapshot.Path,
|
||||
"role", result.DocumentPosition.Snapshot.Role,
|
||||
"spatialize_object_sounds", options.SpatializeObjectSounds,
|
||||
"sound_geometry", result.DocumentPosition.Snapshot.SoundGeometry,
|
||||
"cues", cues,
|
||||
}
|
||||
if link := result.DocumentPosition.LinkedHeading; link != nil {
|
||||
attributes = append(attributes,
|
||||
"linked_heading_bus", link.BusName,
|
||||
"linked_heading_path", link.Path,
|
||||
"linked_heading_sound_geometry", link.SoundGeometry)
|
||||
}
|
||||
logger.Debug("document navigation sound positioning", attributes...)
|
||||
}
|
||||
role = result.DocumentPosition.Snapshot.Role
|
||||
if result.DocumentWrapped {
|
||||
if result.DocumentBackwards {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/atspi"
|
||||
"git.stormux.org/storm/cthulhu/internal/presentation"
|
||||
"git.stormux.org/storm/cthulhu/internal/review"
|
||||
)
|
||||
|
||||
@@ -73,6 +74,9 @@ func TestNativeLinkedHeadings(t *testing.T) {
|
||||
t.Fatal(ctx.Err())
|
||||
}
|
||||
}
|
||||
t.Run("sound geometry after scrolling", func(t *testing.T) {
|
||||
testLinkedHeadingSoundGeometry(t, ctx, adapter, focus)
|
||||
})
|
||||
for _, tc := range []struct {
|
||||
level int
|
||||
name, title string
|
||||
@@ -142,6 +146,72 @@ func TestNativeLinkedHeadings(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testLinkedHeadingSoundGeometry(t *testing.T, ctx context.Context, adapter *atspi.Adapter, focus atspi.ObjectID) {
|
||||
t.Helper()
|
||||
tree, err := adapter.CaptureDocument(ctx, focus)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cursor, err := review.NewDocumentCursor(tree)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := cursor.SyncFocus(ctx, focus); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cold, err := cursor.Move(ctx, review.DocumentHeading, 6, false)
|
||||
if err != nil || !cold.Moved || cold.Position.LinkedHeading == nil {
|
||||
t.Fatalf("cold offscreen heading = %+v, %v", cold, err)
|
||||
}
|
||||
if cold.Position.LinkedHeading.SoundGeometry.ObjectKnown {
|
||||
t.Fatal("fixture heading must start offscreen without captured sound geometry")
|
||||
}
|
||||
worker, err := review.NewWorker(adapter, 2*time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
worker.SyncFocus(focus)
|
||||
if err := worker.Start(ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer worker.Stop(context.Background())
|
||||
for _, step := range []struct {
|
||||
backwards bool
|
||||
name string
|
||||
}{
|
||||
{false, "Offscreen first topic"},
|
||||
{false, "Offscreen second topic"},
|
||||
{true, "Offscreen first topic"},
|
||||
} {
|
||||
if err := worker.MoveDocument(review.DocumentHeading, 6, step.backwards); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
select {
|
||||
case result := <-worker.Results():
|
||||
if result.Err != nil || result.CaretErr != nil || result.DocumentSoundErr != nil ||
|
||||
!result.Moved || result.DocumentPosition.Snapshot.Name != step.name {
|
||||
t.Fatalf("scrolled heading result = %+v", result)
|
||||
}
|
||||
link := result.DocumentPosition.LinkedHeading
|
||||
if link == nil || !link.SoundGeometry.ObjectKnown || !link.SoundGeometry.ReferenceKnown {
|
||||
t.Fatalf("scrolled link lacks fresh geometry: %+v", link)
|
||||
}
|
||||
if !result.DocumentPosition.Snapshot.SoundGeometry.ObjectKnown {
|
||||
t.Fatal("scrolled heading lacks fresh geometry")
|
||||
}
|
||||
cues := presentation.SoundCues(*link, presentation.Options{
|
||||
EnableSound: true, PlaySoundForRole: true, SpatializeObjectSounds: true,
|
||||
})
|
||||
if len(cues) != 1 || cues[0].Pan >= -0.3 {
|
||||
t.Fatalf("left-column link lost leftward sound: %+v", cues)
|
||||
}
|
||||
t.Logf("%s after scroll: bounds=%+v pan=%g", step.name, link.SoundGeometry.Object, cues[0].Pan)
|
||||
case <-ctx.Done():
|
||||
t.Fatal(ctx.Err())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func linkedHeadingFixtureFocus(tree *atspi.AccessibleTree) atspi.ObjectID {
|
||||
root, err := tree.Root()
|
||||
if err != nil {
|
||||
|
||||
Reference in new issue
Block a user