Skip to content

Allow slideshow holds slower than one frame per second - #161

Draft
lfarrand wants to merge 3 commits into
mainfrom
cursor/slow-slideshow-interval-915b
Draft

lfarrand wants to merge 3 commits into
mainfrom
cursor/slow-slideshow-interval-915b

Conversation

@lfarrand

@lfarrand lfarrand commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

--interval is now 100–65536 ms (default stays 500). Values above 1000 ms are slower than one frame per second: each shard stays on screen for multiple seconds, so a receiver that was skipping frames can collect every image in one pass instead of waiting through several full cycles.

Two things kept a long hold from actually playing:

  • Animated PNG wrote the first shard as an untimed fallback. Stills are loaded with metadata skipped, which left AnimateRootFrame off, so that frame had no fcTL delay and was skipped at the start of the cycle. The root frame is now part of the timed sequence, and every frame uses the same hold.
  • APNG stores the delay as a 16-bit numerator and denominator (intervalMs/1000 seconds). ImageSharp casts both parts to ushort. 65536/1000 reduces to 8192/125, so both parts fit. 65537 is coprime to 1000 and does not reduce; the unreduced numerator truncates and the hold collapses to 1/1000 s. The CLI only required ≥ 100 ms, so those values were accepted and then shown for a fraction of a second. 100–65536 ms is the contiguous range that reduces into those fields exactly. Faster intervals in that range, including the 100 ms minimum and the 500 ms default, are unchanged.

HTML slideshow.html still uses setTimeout with that millisecond value. slideshow.apng uses the same interval. This stays on the cross-platform HTML and ffmpeg receive --screen path.

The printed cycle length is imageCount * (long)intervalMs / 1000.0. At the 5,000,000-image ceiling and a 65536 ms hold that product is 327,680,000,000, which is computed in 64 bits.

Test plan

  • dotnet restore QrShard.slnx --locked-mode
  • dotnet build QrShard.slnx -c Release -warnaserror (SDK 10.0.400, rollForward: disable) — 0 warnings, 0 errors
  • dotnet test tests/QrShard.Tests/QrShard.Tests.csproj -c Release -- --filter-class QrShard.Tests.VideoDecodeTests — 26 passed
    • HTML round-trip requires the exact statement const interval = {ms}; (a non-digit follows the number) and both window.setTimeout(queueNext, interval) calls plus window.setTimeout(() => queueNext(0), interval)
    • 99 and 65537 throw Slideshow interval must be an integer from 100 to 65536 ms. against a real frame, so the empty-list guard cannot satisfy the test
    • SlideshowCycleSeconds(5_000_000, 65536) is 327,680,000 seconds, which the wrapped Int32 product is not
    • CLI --interval 5000 prints 5000 ms/image, ~5 s per cycle and writes const interval = 5000;
  • dotnet test tests/QrShard.Tests/QrShard.Tests.csproj -c Release -- --filter-class QrShard.Tests.DecodeSafetyRoundTests — 18 passed on the previous commit, including CLI rejection of 50, 65537, and non-integers before any images are written
Open in Web Open in Cursor 

APNG was leaving the first shard as an untimed fallback, and fcTL's 16-bit
delay fraction truncated holds that did not reduce into a ushort. The shared
interval is now 100–65535 ms so a multi-second hold is exact in both the HTML
page and slideshow.apng.

Co-authored-by: lfarrand <lfarrand@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 12:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The maximum interval is off by one because 65,536 ms remains exactly representable in APNG fields.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Extends slideshow holds beyond one second while keeping HTML and APNG timing consistent.

Changes:

  • Adds APNG root-frame timing and reduced delay fractions.
  • Validates and documents the new interval range.
  • Adds boundary and round-trip tests.
File Description
src/​QrShard.Core/​SlideshowWriter.cs Implements APNG timing and interval validation.
src/​QrShard/​Cli.cs Validates intervals and safely calculates cycle duration.
tests/​QrShard.Tests/​VideoDecodeTests.cs Tests timing and slow intervals.
tests/​QrShard.Tests/​DecodeSafetyRoundTests.cs Tests CLI boundary rejection.
README.md Documents longer slideshow holds.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/QrShard.Core/SlideshowWriter.cs Outdated
65536/1000 reduces to 8192/125, so both 16-bit fcTL fields fit. 65537 is the first millisecond that stays unreduced and overflows.

Co-authored-by: lfarrand <lfarrand@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 13:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The implemented 65536 ms maximum contradicts the PR description and test plan’s stated 65535 ms contract.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
Resolved since last review (1)

Comment thread src/QrShard.Core/SlideshowWriter.cs
The HTML check now requires the exact interval assignment and both playback timers, the out-of-range test requires the interval message on a real frame, and the printed cycle length stays a 64-bit product at the 5,000,000-image ceiling.

Co-authored-by: lfarrand <lfarrand@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 30, 2026 22:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The implementation is consistent across HTML, APNG, CLI validation, documentation, and comprehensive tests.

Review effort: Balanced
Findings: None

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants