Skip to content

fix: Expose an authoritative track refresh - #169

Merged
omaralbeik merged 1 commit into
harflabs:mainfrom
mvanhorn:fix/72-public-track-refresh
Aug 2, 2026
Merged

fix: Expose an authoritative track refresh#169
omaralbeik merged 1 commit into
harflabs:mainfrom
mvanhorn:fix/72-public-track-refresh

Conversation

@mvanhorn

@mvanhorn mvanhorn commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

EventBridge offers the internal sourced event before the public event, but the independent async consumers can resume in either order. A public consumer can therefore receive .tracksChanged or .mediaChanged before Player's main-actor consumer has refreshed audioTracks, videoTracks, and subtitleTracks. Those event cases carry no track payload, and the existing native refreshTracks() operation is not public, so clients currently have no authoritative way to close that race. The issue is open, unassigned, maintainer-authored, and has no prior or competing pull request in the supplied evidence.

Validation

  • On a newly created player with no media, call the public refreshTracks() method and verify all three track arrays remain empty without failure.
  • From a test source that uses ordinary import SwiftVLC, compile and invoke refreshTracks() to guard the public API visibility required by external event consumers.
  • Preserve the existing .tracksChanged and .mediaChanged handler behavior: both continue to call the same refresh operation, fetching audio, video, and subtitle tracks and invalidating selected-track observations.
  • Verify documentation makes the ordering edge explicit: observing either payload-free track-related event does not itself guarantee the mirrored arrays have updated, while calling refreshTracks() on the player actor provides the fresh-read path.

Summary

Promote the existing main-actor Player.refreshTracks() operation to public API instead of changing PlayerEvent associated values, which would force source changes across every event switch. Document that the observable track arrays are asynchronously mirrored snapshots and that raw-event consumers should call refreshTracks() after .tracksChanged or .mediaChanged when they require an immediate native read. Keep the existing implementation and internal event-handler call sites as the single behavior path so public and automatic refreshes fetch all three track types and invalidate selected-track observations identically.

Closes #72

@codecov

codecov Bot commented Aug 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@omaralbeik

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: dc5f3e6317

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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.

Pull request overview

This PR addresses a race where consumers of the public Player.events stream can receive .tracksChanged / .mediaChanged before Player’s mirrored audioTracks / videoTracks / subtitleTracks arrays have been refreshed, by exposing an authoritative refresh operation as public API.

Changes:

  • Promotes Player.refreshTracks() from internal to public and adds API documentation describing the ordering caveat.
  • Adds a new test that verifies refreshTracks() is callable via import SwiftVLC and leaves track arrays empty when no media is loaded.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
Tests/SwiftVLCTests/Player/PlayerPublicTrackRefreshTests.swift Adds a public-API visibility test for Player.refreshTracks() without media.
Sources/SwiftVLC/Player/Player.swift Makes refreshTracks() public and documents when/why public event consumers should call it.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +977 to +980
/// The track arrays are asynchronously mirrored snapshots. Receiving the payload-free
/// ``PlayerEvent/tracksChanged`` or ``PlayerEvent/mediaChanged`` event does not guarantee
/// they are updated; consumers requiring an immediate native read should call this
/// method after either event. This also invalidates selected-track observations.
Comment on lines +1 to +16
import SwiftVLC
import Testing

@Suite(.tags(.mainActor))
@MainActor struct PlayerPublicTrackRefreshTests {
@Test
func `refreshTracks without media leaves public track lists empty`() {
let player = Player()

player.refreshTracks()

#expect(player.audioTracks.isEmpty)
#expect(player.videoTracks.isEmpty)
#expect(player.subtitleTracks.isEmpty)
}
}
@omaralbeik
omaralbeik merged commit 9f67fb2 into harflabs:main Aug 2, 2026
14 checks passed
@omaralbeik

Copy link
Copy Markdown
Member

Thank you @mvanhorn 👏🏼

@mvanhorn

mvanhorn commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Appreciate the quick merge, @omaralbeik. Glad the authoritative track refresh fits the API shape you wanted.

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.

Public events consumers can read a stale track list after .tracksChanged

3 participants