Skip to content

Add Playlist Wait/Advance Modes with Real-Time Controls#17

Open
Kryxzort wants to merge 25 commits into
sunwoo101:mainfrom
Kryxzort:pr/playlist-wait-advance
Open

Add Playlist Wait/Advance Modes with Real-Time Controls#17
Kryxzort wants to merge 25 commits into
sunwoo101:mainfrom
Kryxzort:pr/playlist-wait-advance

Conversation

@Kryxzort

@Kryxzort Kryxzort commented May 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Wait for video to end before switching: per-playlist and global toggle; when enabled, the timer fires at the configured interval but waits for the current video to finish before advancing
  • Switch when video ends: advance-on-end mode — mpv advances naturally at file end, no timer
  • Mutually exclusive toggles: enabling one disables the other
  • Display proxies (DisplayInterval*, DisplayAdvanceOnVideoEnd, DisplayWaitForVideoEnd): playlist popup shows global values when Override is off, per-playlist values when on — spinners and toggles always reflect effective settings
  • Real-time playlist controls: shuffle, interval, wait/advance mode changes apply instantly to a running session via IPC without restarting mpvpaper; mode switches (timed ↔ advance-on-end) happen in place
  • Real-time item sync: adding, removing, or reordering playlist items syncs to the running player within 100ms
  • Status bar: reflects live playback state (wallpaper count, interval, shuffle, volume, loop) and updates on any change including add/remove
  • Persist across restarts: AdvanceOnVideoEnd and WaitForVideoEnd saved to LastSession and TimedState so --restore and daemon hand-off replay the correct mode
  • Elapsed-time aware mode switch: switching from advance-on-end to timed uses time-pos IPC query — if elapsed < interval, countdown starts from the remainder; if elapsed ≥ interval, advances immediately
  • Wait cancellation: disabling WaitForVideoEnd while a DoVideoEndWait is in progress cancels the wait and advances immediately

Notes

  • Scene-related branches in DoVideoEndWait (IsScenePath, IsLweRunning, SceneTransitionDelayMs) stripped — depend on the scene support PR
  • ApplyOverridesForPath simplified (no ReadVolumeOverride/ReadSpeedOverride) — depend on the per-video overrides PR
  • OnWallpaperChanged / _currentlyPlayingCard / Speed added as stubs for future PRs

Test plan

  • Playlist popup: "Switch when video ends" and "Wait for video to end" appear before "SWITCH EVERY" header
  • Override off → interval spinners show global values; override on → show per-playlist values
  • Play timed playlist → status bar shows count + interval + shuffle; add/remove item → count updates immediately
  • Enable WaitForVideoEnd → timer fires → wallpaper waits for video end before switching
  • Enable WaitForVideoEnd mid-session → disable it → advances immediately (no stuck wait)
  • Start advance-on-end playlist, let video play < interval → switch to timed → countdown fires at remaining time
  • Start advance-on-end playlist, let video play > interval → switch to timed → advances immediately
  • --restore replays correct mode (timed or advance-on-end) after GUI close

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • New "wait for video to end" options (per-playlist and global) and UI controls.
    • Playback controls: speed, loop, shuffle and video scale settings.
    • Playlist observer that updates wallpaper/status as playback advances.
  • Improvements

    • Better session persistence to restore timed/advance modes and waits across restarts.
    • Live playlist sync and reordering while playing; toggling wait cancels or schedules switches immediately.
    • Smoother video-end transition handling and status display.

@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0f6d0ceb-3f8e-4f66-89b2-fc8546cfa0f3

📥 Commits

Reviewing files that changed from the base of the PR and between 3528423 and 0eb400f.

📒 Files selected for processing (1)
  • src/livepaper/Views/MainWindow.axaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/livepaper/Views/MainWindow.axaml

📝 Walkthrough

Walkthrough

This PR adds "wait for video end" timing to timed playlists, persists and restores timed-state (including waiting/advance flags), extends PlayerHelper with IPC query/control and playlist-observer logic, exposes public mpv controls, and updates ViewModel and UI to configure and sync timed vs advance-on-end playback.

Changes

Video-End Wait, Playback Controls & Playlist Sync

Layer / File(s) Summary
Data Models & Persistence Schema
src/livepaper/Models/AppSettings.cs, src/livepaper/Models/LastSession.cs
AppSettings adds GlobalWaitForVideoEnd and PlaylistWaitForVideoEnd. LastSession adds WaitForVideoEnd, AdvanceOnVideoEnd, and OverrideGlobalSettings for session restore.
PlayerHelper Core State & Persistence
src/livepaper/Helpers/PlayerHelper.cs
Introduces internal flags and cancellation tokens for video-end waits; extends TimedState and updates SaveTimedState()/LoadTimedState() to persist and restore wait/advance/waiting fields; teardown cancels waits and stops observer.
IPC Helpers & Playlist Query Infrastructure
src/livepaper/Helpers/PlayerHelper.cs
Adds IPC helpers (path, time-pos, time-remaining), refactors ApplyPlaylist() to start playlist observer, extends ApplyTimedPlaylist() signature with waitForVideoEnd/advanceOnVideoEnd, and adds mode-conversion, reorder, and sync helpers.
Video-End Wait & Cancellation Async Flows
src/livepaper/Helpers/PlayerHelper.cs
Implements DoVideoEndWait() (IPC time-remaining + delay) and CancelVideoEndWait(); changes Tick() so countdown pauses while waiting; ensures advances/back steps cancel pending waits and rearm after restore.
Playback Control APIs & Playlist Observer
src/livepaper/Helpers/PlayerHelper.cs
Adds SetSpeed(), SetLoop(), SetPlaylistShuffle(), SetVideoScale() public mpv control methods; adds playlist observer applying per-path overrides and firing OnWallpaperChanged; updates pause/stop to persist timed-state atomically.
ViewModel Settings Properties & Change Handlers
src/livepaper/ViewModels/MainWindowViewModel.cs
Adds Speed, PlaylistWaitForVideoEnd, GlobalWaitForVideoEnd, and display proxy properties; rewrites change handlers to apply effective playlist settings while playing and normalize LastSession when idle.
ViewModel Playback Commands & Playlist Sync
src/livepaper/ViewModels/MainWindowViewModel.cs
Updates playback commands to persist richer LastSession including timed-vs-advance and WaitForVideoEnd; adds SyncPlaylistToPlayerIfRunning() debounced reorder/sync path; replaces direct status updates with RefreshPlayingStatusSoon().
ViewModel Status Rendering & Wallpaper Callback
src/livepaper/ViewModels/MainWindowViewModel.cs
Tracks currently playing card via wallpaper callback; implements debounced RefreshPlayingStatusSoon() and rewrites RefreshPlayingStatus() to show mode/title and volume/loop/speed details.
UI Bindings & Layout Updates
src/livepaper/Views/MainWindow.axaml
Binds "Switch when video ends" to DisplayAdvanceOnVideoEnd; adds "Wait for video to end after interval fires before switching" bound to DisplayWaitForVideoEnd; interval inputs bind to DisplayInterval* and are disabled when advance-on-end is active; adds global WaitForVideoEnd checkbox.
Rules & Documentation Updates
.claude/rules/session.md, .claude/rules/ui.md
Documents WaitForVideoEnd semantics, timed-state persistence/restore and re-arm behavior, RefreshLastSessionFromSettingsIfIdle() sync, and UI controls exposing per-playlist and global wait options.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I wait while pixels fade to black,

the countdown breathes and holds its track,
Speed and loop and shuffle hum in tune,
Cards change softly under moon,
A rabbit claps — the playlist resumes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective: adding playlist modes for waiting for videos to end or advancing at video end, along with real-time controls for these features.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/livepaper/Helpers/PlayerHelper.cs`:
- Around line 606-623: SwitchFromTimedToAdvanceOnEnd uses
_history[_historyIndex] as the current file but when _waitingForVideoEnd is true
the _historyIndex points to the prefetched next item; update the logic in
SwitchFromTimedToAdvanceOnEnd to use the actual playing item (e.g.
_history[_historyIndex - 1]) when _waitingForVideoEnd is true, with proper
bounds checks against _history and _historyIndex, before building rest and
appending files; mirror the same playingHistIdx adjustment approach used in
RestoreTimedPlaylist() so the queue is rebuilt around the real currently playing
path.

In `@src/livepaper/ViewModels/MainWindowViewModel.cs`:
- Around line 391-419: The code incorrectly uses the editor setting
PlaylistShuffle instead of the active session's shuffle flag s.Shuffle when
switching modes and when writing _settings.LastSession; change calls to
PlayerHelper.SwitchFromTimedToAdvanceOnEnd and SwitchFromAdvanceOnEndToTimed to
pass s.Shuffle (not PlaylistShuffle), use s.Shuffle when constructing playPaths
(i.e., only randomize if s.Shuffle is true), and set the LastSession.Shuffle
property to s.Shuffle when updating _settings.LastSession in both branches.
- Around line 493-494: The status model never updates because the viewmodel
never subscribes to PlayerHelper.OnWallpaperChanged; subscribe to
PlayerHelper.OnWallpaperChanged in the MainWindowViewModel constructor and
implement a handler that sets _currentlyPlayingCard to the new
WallpaperCardViewModel (or null) and calls RefreshPlayingStatus(); also
unsubscribe from PlayerHelper.OnWallpaperChanged in the viewmodel's
cleanup/dispose/OnClosed path (the same place handling other event
unsubscriptions around the Dispose/OnClosed logic referenced near the block at
lines ~558-570) so you don't leak handlers.
- Line 331: The current live-sync code (e.g., OnPlaylistShuffleChanged calling
SavePlaylistStateDebounced, ApplyShuffleOrderIfRunning, RefreshPlayingStatus)
unconditionally updates any active LastSession with IsTimedPlaylist/IsPlaylist
true, causing PlayLibrary() sessions to adopt the custom-playlist's s.Paths and
reorder the live player; fix by adding an explicit guard that only
syncs/reorders when the running session is the same custom playlist being
edited. Concretely, in ApplyShuffleOrderIfRunning (and the other live-sync paths
you noted) check that LastSession references the exact playlist being modified
(compare a stable identifier—e.g., Session.PlaylistId or Session.Id—to the
current viewmodel's playlist Id, or add a helper
IsRunningCustomPlaylistSession(LastSession, currentPlaylist) that ensures
session is not the library session), and only mutate s.Paths or reapply shuffle
when that predicate is true; do not treat any IsPlaylist/IsTimedPlaylist flag
alone as sufficient.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f97f93fb-7053-43e7-8c43-9ad7852a885f

📥 Commits

Reviewing files that changed from the base of the PR and between 84c9e01 and 2d8b1cf.

📒 Files selected for processing (5)
  • src/livepaper/Helpers/PlayerHelper.cs
  • src/livepaper/Models/AppSettings.cs
  • src/livepaper/Models/LastSession.cs
  • src/livepaper/ViewModels/MainWindowViewModel.cs
  • src/livepaper/Views/MainWindow.axaml

Comment thread src/livepaper/Helpers/PlayerHelper.cs
Comment thread src/livepaper/ViewModels/MainWindowViewModel.cs Outdated
Comment thread src/livepaper/ViewModels/MainWindowViewModel.cs
Comment thread src/livepaper/ViewModels/MainWindowViewModel.cs
@Kryxzort

Kryxzort commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Both actionable findings from the previous review have been addressed in commits pushed after the review was run:

  • playingHistIdx correction in SwitchFromTimedToAdvanceOnEnd — fixed in 3ef991e
  • Live-sync mutation guard (IsRunningCustomPlaylist check) in ApplyShuffleOrderIfRunning / ApplyEffectivePlaylistSettingsIfRunning — fixed in a26421b

The PlaylistShuffle vs s.Shuffle flag: PlaylistShuffle is the view model's live binding for the custom playlist being edited, which is correct here — the guard in a26421b ensures this only applies when the running session IS that custom playlist.

The OnWallpaperChanged subscription is a cross-PR dependency (PR #4 adds the full card tracking); noted in the adaptations index.

@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@Kryxzort: Thanks for the detailed summary of the addressed findings and the clarifications! I'll kick off a fresh review of PR #17 now, taking into account the fixes in 3ef991e and a26421b and the context you've provided on PlaylistShuffle and the OnWallpaperChanged cross-PR dependency.

[review]

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.claude/rules/session.md (1)

61-63: ⚡ Quick win

Remove duplicated guard rule text

This guard behavior is documented twice with the same meaning. Keep a single canonical statement to avoid future drift.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/rules/session.md around lines 61 - 63, Remove the duplicated
guard-rule sentence describing that ApplyEffectivePlaylistSettingsIfRunning and
ApplyShuffleOrderIfRunning are guarded by IsRunningCustomPlaylist(s.Paths) so
library (Play All) sessions are not mutated; keep a single canonical statement
(referencing ApplyEffectivePlaylistSettingsIfRunning,
ApplyShuffleOrderIfRunning, and IsRunningCustomPlaylist) and delete the
redundant paragraph to avoid future drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/rules/player.md:
- Around line 12-14: The fenced code block containing the command "mpvpaper -o
\"<mpv-options>\" '*' /path/to/wallpaper.mp4" is missing a language identifier;
update that fenced block to include the bash language tag (i.e., change the
opening ``` to ```bash) so markdown linters (MD040) accept it and the snippet is
properly highlighted.

In @.claude/rules/sources.md:
- Around line 10-12: The fenced code block containing the user-agent string is
missing a language/info tag and triggers MD040; edit the fenced block (the
triple-backtick block that contains "Mozilla/5.0 (X11; Linux x86_64; rv:130.0)
Gecko/20100101 Firefox/130.0") and add an info string such as text (i.e., change
the opening ``` to ```text) so the block is explicitly tagged for markdownlint.

---

Nitpick comments:
In @.claude/rules/session.md:
- Around line 61-63: Remove the duplicated guard-rule sentence describing that
ApplyEffectivePlaylistSettingsIfRunning and ApplyShuffleOrderIfRunning are
guarded by IsRunningCustomPlaylist(s.Paths) so library (Play All) sessions are
not mutated; keep a single canonical statement (referencing
ApplyEffectivePlaylistSettingsIfRunning, ApplyShuffleOrderIfRunning, and
IsRunningCustomPlaylist) and delete the redundant paragraph to avoid future
drift.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3389fded-7761-407d-8700-40a8ae6b6df4

📥 Commits

Reviewing files that changed from the base of the PR and between 2d8b1cf and 2d080db.

📒 Files selected for processing (9)
  • .claude/rules/distribution.md
  • .claude/rules/library.md
  • .claude/rules/player.md
  • .claude/rules/session.md
  • .claude/rules/sources.md
  • .claude/rules/ui.md
  • CLAUDE.md
  • src/livepaper/Helpers/PlayerHelper.cs
  • src/livepaper/ViewModels/MainWindowViewModel.cs
✅ Files skipped from review due to trivial changes (3)
  • .claude/rules/library.md
  • .claude/rules/distribution.md
  • .claude/rules/ui.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/livepaper/ViewModels/MainWindowViewModel.cs
  • src/livepaper/Helpers/PlayerHelper.cs

Comment thread .claude/rules/player.md Outdated
Comment thread .claude/rules/sources.md Outdated
@Kryxzort

Kryxzort commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Kryxzort

Kryxzort commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Kryxzort and others added 20 commits May 8, 2026 04:21
Playlist settings popup now has a "Wait for video to end before switching"
checkbox. When enabled, the timed playlist queries mpv's remaining time via
IPC at the switch point, waits that duration, then does a seamless in-process
loadfile replace — no process kill, no flash.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
"Wait for video to end before switching" is now a global toggle in Settings →
PLAYLIST, directly under "Switch when video ends". The playlist popup shows the
effective value (global when override is off, per-playlist when on), matching
the pattern of the other rotation controls.

Also right-aligns the Thumbnail aspect and Card size dropdowns in the
APPEARANCE section so they flush with the Theme dropdown edge.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Video→video: disable loop-file and append next to mpv's playlist so the
transition happens inside mpv with no blank gap. Sleep remaining + 2s then
restore loop and fire UI update. Eliminates the loop-race that caused the
first frames of the looped video to show before switching.

Video→scene: sleep remaining - SceneTransitionDelayMs before calling
SwitchToFile, so LWE launches with exactly SceneTransitionDelayMs of video
still playing — matching normal transition overlap behaviour.

Scene→*: switch immediately (no mpv socket to query remaining time from).

CancelVideoEndWait now restores loop-file=inf immediately so the current
video does not advance into the queued append before TryIpcSwitchToFile
takes over.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Status bar now reflects live playback state (title, wallpaper count,
  interval, shuffle, volume, loop, speed) and updates on any change
- Playlist settings (shuffle, interval, wait-for-video-end, advance-on-
  end) apply instantly to the running session without restarting mpvpaper
- Toggling advance-on-end switches modes via IPC (loop-file / loadfile
  append / playlist-clear) with no mpvpaper restart
- Loop toggle sends IPC command in single-video mode without restart
- Shuffle toggle reorders the active playlist immediately: sequential
  picks up from current wallpaper's position in the original order;
  shuffle randomises the remaining tail
- Adding, removing, or reordering playlist items syncs to the running
  player in real time (100ms debounce); add-only appends to mpv's
  existing queue to preserve playback order; removes and reorders do a
  full rebuild from the current position; removing the currently playing
  wallpaper maps its old index into the new list so the positionally
  equivalent item plays next instead of restarting from the beginning

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
IPC socket isn't ready when RefreshPlayingStatus runs immediately
after ApplyPlaylist/ApplyTimedPlaylist, so IsPlaying returned false
and the bar stayed blank. Poll until the socket exists before
refreshing.

ObservePathAsync never called OnWallpaperChanged, so the status bar
never updated when mpv advanced to the next video in video-end mode.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two new fields to the LastSession model and updates all construction
sites to populate them correctly. Fixes the scene-mixed branch to update
the running timed playlist via IPC instead of restarting mpvpaper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Syncs LastSession when playlist/rotation settings change while nothing
is playing, so --restore picks up the new interval and advance mode
even if the user hasn't started a new session yet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes references to IsLweRunning, IsScenePath, and SceneTransitionDelayMs
that were auto-applied during cherry-pick but belong to PR 10 (scene support).
Also fixes RearmAdvanceOnVideoEnd to use the correct DoVideoEndWait signature
introduced by 1e96c82, and adds missing using System.Threading.Tasks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When switching from advance-on-end to timed interval mode, query mpv's
time-pos via IPC to calculate how much of the current video has already
played. If elapsed < interval, start the countdown from the remainder
so the first switch fires at the right time. If elapsed >= interval,
start fresh with the full interval.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Interval NumericUpDown controls and the AdvanceOnVideoEnd IsEnabled guard
were bound directly to the per-playlist properties instead of the Display*
proxies, so toggling Override off didn't update the shown values to global.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SwitchFromAdvanceOnEndToTimed: when elapsed time >= interval, advance
immediately instead of waiting a full interval. Cancels the stale
DoVideoEndWait feel when switching from a long-running advance-on-end
session.

UpdateTimedSettings: disabling WaitForVideoEnd while DoVideoEndWait is
in progress now cancels the wait and advances immediately, rather than
leaving the playlist stuck until the video naturally ends.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
RefreshPlayingStatus read s.Paths.Count which is only updated after a
100ms debounce, causing the displayed count to lag or show the wrong
number. Switched to PlaylistItems.Count which reflects the live strip.

Also added RefreshPlayingStatus to PlaylistItems.CollectionChanged so
the status bar updates immediately when items are added or removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Kryxzort added 2 commits May 8, 2026 04:27
When _waitingForVideoEnd is true, _historyIndex points to the prefetched
next item. SwitchFromTimedToAdvanceOnEnd was using _history[_historyIndex]
as the current path, rebuilding the queue around the wrong item. Apply
the same playingHistIdx correction already used in RestoreTimedPlaylist.

TogglePause and SignalTimerStop used File.WriteAllText (non-atomic) on
timed_state.json. GUI/daemon overlap could truncate the file. Switch to
write-to-tmp then File.Move (atomic rename). Also add lock(_lock) to
SignalTimerStop to match TogglePause.
ApplyEffectivePlaylistSettingsIfRunning and ApplyShuffleOrderIfRunning
only checked IsTimedPlaylist/IsPlaylist, so edits to the custom playlist
while PlayLibrary() was running would mutate the wrong active session.

Add IsRunningCustomPlaylist() helper that matches session paths against
the current PlaylistItems (same pattern as matchesStrip in
RefreshLastSessionFromSettingsIfIdle). Guard both methods with it.
@Kryxzort Kryxzort force-pushed the pr/playlist-wait-advance branch from 0042a74 to 5eeefe9 Compare May 7, 2026 23:47

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/livepaper/Views/MainWindow.axaml`:
- Around line 506-511: The WaitForVideoEnd checkboxes should be disabled when
their paired AdvanceOnVideoEnd is active; update the CheckBox with Content="Wait
for video to end after interval fires before switching" (bound to
DisplayWaitForVideoEnd) to include the same guard used elsewhere by setting its
IsEnabled to the negation of DisplayAdvanceOnVideoEnd (i.e. match the existing
pattern used on the interval StackPanel such as !DisplayAdvanceOnVideoEnd). Do
the same for the settings PlayList checkbox bound to GlobalWaitForVideoEnd: set
IsEnabled to the negation of GlobalAdvanceOnVideoEnd so the WaitForVideoEnd
controls are visually disabled when the corresponding AdvanceOnVideoEnd is
active.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: efb70a8b-3453-47f9-8ed4-61fae3cfbd2d

📥 Commits

Reviewing files that changed from the base of the PR and between 2d080db and 3528423.

📒 Files selected for processing (7)
  • .claude/rules/session.md
  • .claude/rules/ui.md
  • src/livepaper/Helpers/PlayerHelper.cs
  • src/livepaper/Models/AppSettings.cs
  • src/livepaper/Models/LastSession.cs
  • src/livepaper/ViewModels/MainWindowViewModel.cs
  • src/livepaper/Views/MainWindow.axaml
✅ Files skipped from review due to trivial changes (2)
  • .claude/rules/session.md
  • .claude/rules/ui.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/livepaper/Models/AppSettings.cs
  • src/livepaper/Models/LastSession.cs
  • src/livepaper/ViewModels/MainWindowViewModel.cs
  • src/livepaper/Helpers/PlayerHelper.cs

Comment thread src/livepaper/Views/MainWindow.axaml
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Kryxzort added a commit to Kryxzort/livepaper-pro that referenced this pull request May 22, 2026
session.md: kept VideoScale and AutoMuteOnlyIfMprisActive (PR sunwoo101#10/PR sunwoo101#16);
added GlobalWaitForVideoEnd to global rotation settings (PR sunwoo101#17).
ui.md: kept GIF hover (PR sunwoo101#13), right-click menus (PR sunwoo101#15), Speed in Playback
(PR sunwoo101#10); added Wait for video to end to Playlist settings (PR sunwoo101#17).
PlayerHelper: dropped duplicate _observerCts field (ghost from previous merge);
added _waitForVideoEnd/_advanceOnVideoEnd/_waitingForVideoEnd/_waitCts (PR sunwoo101#17);
fixed ApplyPlaylist to use shuffled paths array and not double-shuffle via mpv flag;
added SetLoop and SetPlaylistShuffle IPC helpers (PR sunwoo101#17); resolved duplicate
StartPlaylistObserver/StopPlaylistObserver/ObservePathAsync/ApplyOverridesForPath
by keeping PR sunwoo101#17 insertions with HEAD's full ApplyOverridesForPath
(volume+speed overrides) and OnWallpaperChanged invoke; removed duplicate
HEAD methods.
MainWindowViewModel: kept _autoMuteOnlyIfMprisActive (PR sunwoo101#16); added
_speed=1.0 default (PR sunwoo101#17) to existing declaration; added _playlistSyncCts
(PR sunwoo101#17); dropped duplicate _currentlyPlayingCard; adopted PR sunwoo101#17 concise
OnWallpaperChanged + RefreshPlayingStatus; kept OnVolumeChanged/OnSpeedChanged
with per-card override logic (PR sunwoo101#10); kept LastSession with PR sunwoo101#17 new fields.
MainWindow.axaml: kept Appearance section (thumbnail/card/gif settings from
PR sunwoo101#12/PR sunwoo101#13) that PR sunwoo101#17 was unaware of.
Kryxzort added a commit to Kryxzort/livepaper-pro that referenced this pull request May 22, 2026
… Controls (via merge-fix branch)

Merges sunwoo101#17. Implements playlist wait-for-video-end modes
with real-time controls, status bar showing live playback state, playlist item
sync via IPC, and mode switching without restart.
Conflicts resolved in merge-fix/pr-17-playlist-wait-advance.
Kryxzort added a commit to Kryxzort/livepaper-pro that referenced this pull request May 22, 2026
library.md: updated heading to include scene; added volume/speed sidecars
(PR sunwoo101#10) alongside scene-specific sidecars (PR sunwoo101#18); kept all sections.
session.md: merged WE settings — AllowScenes, LWE config (PR sunwoo101#18) alongside
ThumbnailAspect/CardSize/LibrarySortIndex (PR sunwoo101#12/PR sunwoo101#13).
ui.md: Browse tab kept GIF hover + auto-search + sort + SCENE badge;
Library tab kept full ItemsRepeater grid + all features + SCENE/crash badges;
Settings kept Video scale + WE scene support + Appearance section.
README: added both playerctl and linux-wallpaperengine to optional deps.
LibraryItem: added CopiedSceneDir (PR sunwoo101#18) + kept VolumeOverride/SpeedOverride.
AppSettings: kept Speed with clamping; kept PlaylistWaitForVideoEnd; dropped
duplicate LibrarySortIndex from PR sunwoo101#18.
WallpaperResult: kept AddedAt (PR sunwoo101#14).
livepaper.csproj: kept ItemsRepeater + AnimatedImage packages.
AudioMonitor: kept async IsAnyMprisPlayerActiveAsync + better playerctl args.
DownloadHelper: kept smart thumbnail extension detection.
LibraryService: merged scene-copy Trash/Restore/Delete + kept volume/speed.
WallpaperEngineScraper: merged all, kept AnimatedThumbnailUrl + AddedAt.
WallpaperEngineService: kept SortIndex/SupportsSorting.
PlayerHelper: merged 29 conflicts — kept wait/advance/playlist observer from
PR sunwoo101#17 + added full scene/LWE support from PR sunwoo101#18; removed duplicates.
MainWindowViewModel: merged 25 conflicts — kept all playlist wait/advance
proxies from PR sunwoo101#17 + added scene-aware methods from PR sunwoo101#18.
WallpaperCardViewModel: kept full GIF+volume/speed code + added scene-aware
fields and LoadDurationAsync from PR sunwoo101#18.
MainWindow.axaml: kept GIF animation, volume/speed sliders; added SCENE badge
and crash warning panel (adjusting grid row offsets).
MainWindow.axaml.cs: kept HEAD's existing TextBox guard structure.
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.

1 participant