Skip to content

[Spec] 播放器状态与公开 API 契约实现计划 #85

Closed

Description

@wt159

由 wayfinder 地图 #75 的 #76–#84 九张票的 linked decisions 折叠而成;地图已于 2026-11-07 关闭。
完整规格是 doc/player-state-contract.md(§1–§10),唯一 ADR 是 0004。
本 issue 是面向实现、可独立阅读的建设计划,不是地图;决策的完整依据仍在各票的 resolution comment。
实现属图外新 effort:本 spec 之后走 /to-tickets 拆垂直切片 → /implement-spec 在 integration branch 上实现。

Problem Statement

soundbridge::Player 的公开契约一直靠实现隐式决定:公开头对回调线程 / 顺序 / 重入零注释;两条错误路径的 state 与 error 先后不一致;position 回调经二次 asyncRunTask 回投 priority_queue,同刻不保证 FIFO;durationMs == 0 时 seek 的「显式 INVALID_OPERATION」在 void API 上根本无法表达;播放列表错误路径的自动跳轨判据与解码路径不一致。这些空白让调用方(含 app)只能猜,且没有任何一条契约是可红可绿的判据。

Solution

把已裁定的八项决策落成代码内注释 + 生产链最小改动 + 可判定用例,不引入新状态机、不改任何公开签名:

编号 内容
C1 两条错误路径统一为 error→state;skip 失败补一次状态事件
C2 position 二次 asyncRunTask 保证同曲目会话内单调不回退
C3 player.h 加注释:线程 / 重入 / 异常 / 所有权 / 停机期(建议文本见规格 §10.2)
C4 durationMs==0 的 seek 空操作与「无新回调」判据用例
C5 播放列表错误路径是否补 ErrorAction::SkipTrack 检查(规格 §6.3 登记项)
C6 回调顺序 / 幂等 / 必须上报清单的补强用例(不改既有数值)

决策要点:保持三态;回调承诺 SDK 内单一串行线程同步发出、marshal 归调用方、曲目三连固定、错误统一 error→state、回调内禁发命令 / 析构 / 抛异常;七个入口保持 void,被丢弃命令不产生回调也不改查询值;查询是真相源、回调是变更通知;INVALID_OPERATION 是内部降级码不对外暴露,duration() == 0 是唯一「不可 seek」信号。

User Stories

  1. 作为 SDK 接入方,我想从公开头直接读到回调的线程 / 重入 / 所有权约束,不用读实现。
  2. 作为 SDK 接入方,我想在任何错误下都先收到原因、再看到状态变化,且 autoSkip 跳轨成功时不会收到一个撒谎的状态。
  3. 作为 UI 作者,我想 position 回调在同一曲目内单调不回退、换曲时归零,不会因队列同刻无序而倒退。
  4. 作为 UI 作者,我想只用 duration() == 0 就判断不可 seek,不需要额外能力位。
  5. 作为测试作者,我想三态边界、回调三连、幂等、上报清单、时长为零的空操作都有可红可绿的判据。
  6. 作为维护者,我想这些改动不触碰坏输入 55 例与覆盖度基线、不新增 CI gate。

Implementation Decisions

  • 生产链改动集中在错误上报顺序、position 回调的单调钳制、以及播放列表错误路径的口径统一;公开签名与状态机结构不变。
  • 注释文本按规格 §10.2 原样落地(线程 / 重入 / 异常 / 所有权 / 停机期五条),不额外扩写 API 文档或时序图。
  • C5 是登记项:以「统一到与解码路径相同的 ErrorAction::SkipTrack 口径」为推荐,但以不使坏输入基线变红为硬边界;若两者冲突,保留现状并在票里写清理由。
  • INVALID_OPERATION 保持 sdk_utils::status_t = -ENOSYS 的内部降级语义,不进公开 ErrorCode、不经 onError。

Testing Decisions

  • 好测试只断言外部可见行为(回调序列、查询值、状态序列),不断言内部队列调度。
  • 沿用既有接缝:sdk/test/mocks/PlayerMocks.hpp 的回调记录器、sdk_player_tests / sdk_unit_tests / sdk_interaction_tests 三个分组;优先扩展既有记录器而不是新建 mock。
  • 既有数值判据原样复用;重入 / 所有权 / ABI 类只写注释与规格,不做最小可测替身(回调内发命令会自锁)。

Out of Scope

  • app UI 重设计与 PlayerViewState 重构、API 文档 / 时序图 / CLI 接入示例、错误码体系重构。
  • 网络流 / 边下边播 / IAudioSink / 格式扩展;端到端 drift 与观测指标判据。
  • 状态机改写、公开签名变更、新增错误码、CI 分组与 TIMEOUT 调整。

Further Notes

  • 契约漂移的长期观测口径仍属后续 effort;若像 [T13] CI 观测与端到端 drift 记录 #68 的 StreamingBudget 一样只记录不设门槛,须写明「不作为失败门禁」。
  • 跨平台改动必须等 Linux sdk-coverage 绿,本地 Windows 全绿不算完成。
  • 实现清单见规格 §10.1;本批票以 [Tnn] 前缀编号,阻塞边用 GitHub 原生依赖关系。

Activity

  1. wt159 commented on Nov 8, 2026

    @wt159
    OwnerAuthor

    Spec 完成(2026-11-08)

    doc/player-state-contract.md §10.1 的 C1–C6 已全部落地,执行票 #86–#92 逐票关闭并在各自 resolution comment 留完整依据。

    • 交付:integration branch implement/player-state-contract(9 提交)→ PR feat: 播放器状态与公开 API 契约落地(C1–C6 / #85–#92) #93 → master。
    • 验证:改动前基线 ctest -j4 14/14;审查修复后 14/14(59.6s),含坏输入四段与覆盖度。
    • 审查:一次 code-review,4 Major + 4 Minor 在一个修复提交里全部处理。
    • 回填:规格 §10.1 / §10.2 / §10.3 状态更新,新增 §10.4 实现落地记录(C1–C6 落点、务实取舍、已知判据缺口)。
    • 约束守住:七个控制入口仍 void,无新增错误码 / 状态机 / 状态值,既有容差数值、坏输入 55 例、14 个目标与 TIMEOUT 全部未动。

    遗留:契约漂移观测口径交后续 effort;C1 顺序与 C5 设备错误不跳轨缺端到端判据(原因见规格 §10.4)。

  2. added a commit that references this issue on Nov 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agent信息完备,agent 可直接开工

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions