feat(player): run the old backend through the new contract

DR-245, first half. `LegacyPlayer` implements `MediaPlayer` over the existing
`PlayerBackend`, so engines not yet ported — ExoPlayer, the webview element,
the null backend — keep working while `PlayerController` moves across. Without
it the port would have to land all four engines at once.

It also makes the two designs comparable on one engine and one file. `open`
reproduces the old sequence faithfully: load, play, then seek for a start
position, with the seek's failure ignored exactly as callers used to ignore
it. Making it pass would defeat the point.

Running both engines over the same media is more informative than expected:

  MpvPlayer     9/9
  LegacyPlayer  8/9 - transport_settings_round_trip fails

Two things fall out of that. The start-position case now passes on *both*,
because DR-241 was fixed inside MpvBackend rather than only in the new engine
— so the suite confirms that fix independently, on a path it was not written
against. And the one genuine failure is a capability gap rather than a bug:
the old trait has no mute and no playback rate, so `LegacyPlayer` reports them
unsupported instead of folding mute into volume and losing the user's level.

That is the abstraction earning its keep on the first run: a missing
capability that was previously invisible is now a named, failing case.

The runner takes an engine argument:

    player-conformance <media-file> [mpv|legacy]
This commit is contained in:
2026-08-22 21:23:39 +02:00
parent a3190cd52b
commit 8904acb5f7
5 changed files with 232 additions and 24 deletions
+2
View File
@@ -12,6 +12,8 @@ pub mod events;
pub mod fake_player;
#[cfg(test)]
mod fake_player_conformance;
#[cfg(any(test, feature = "conformance"))]
pub mod legacy_player;
pub mod media;
pub mod media_player;
#[cfg(target_os = "linux")]