Skip to content

feat: 播放器状态与公开 API 契约落地(C1–C6 / #85–#92) - #93

Merged
wt159 merged 9 commits into
masterfrom
implement/player-state-contract
Nov 8, 2026
Merged

wt159 merged 9 commits into
masterfrom
implement/player-state-contract

Conversation

@wt159

@wt159 wt159 commented Nov 8, 2026

Copy link
Copy Markdown
Owner

Spec: #85(由 wayfinder 地图 #75 折叠而成)。完整规格见 doc/player-state-contract.md §10,唯一 ADR 为 docs/adr/0004。
执行票 #86–#92 用 GitHub 原生阻塞边连成 task graph;本 PR 是它们共同的 integration branch。

做了什么

把 .workbuddy 无关、纯文档阶段定下的公开契约真正落到代码与判据上,不改任何公开签名、不新增错误码 / 状态机 / 状态值:

票 内容
#86 / T01 player.h 按规格 §10.2 落地五条回调注释;两个 mock 增加事件序列 / 位置值序列与辅助函数
#87 / T02 播放列表错误路径统一 onError → 状态;updatePlayState 以「最近发出的状态」去重(幂等、无相邻重复)
#88 / T03 reportPosition 统一 seek / 消费循环 / 切歌三个位置出口,用 floor + trackIndex + epoch 保证同曲单调、换曲归零、旧会话在途任务失效
#89 / T04 duration()==0 与超界 seek 的空操作判据(位置不回退、无新回调、无状态、无错误)
#90 / T05 播放列表错误路径补 ErrorAction::SkipTrack 检查,设备错误不再靠跳轨绕过;action 表锁口径
#91 / T06 曲目切换三连、重复命令幂等、状态序列无相邻重复的补强用例
#92 / T07 全量回归、一次 code-review、规格 §10 回填

code-review

独立审查提出 4 Major + 4 Minor,已在一个修复提交里全部处理:

  • Major:位置会话代际漏钳制(同曲两次会话)、状态去重键错误 + 无条件置 Stopped(autoSkip 闪 Stopped / 首播失败静默)、用例与目标路径错配、裸 sleep 与无声卡 flaky。
  • Minor:mock reset() 漏锁、三连用例计数窗口过宽、test_error.cpp 注释与判据不符、注释措辞。

验证

  • 本地 ctest -j4 14/14 全绿(含坏输入四段与覆盖度),59.6s,无假红。
  • 改动前基线同为 14/14;中途发现并修复过一次「stop 后重播位置被 floor 钳住」的回归。
  • 既有容差数值(max(1%,150ms)、≤50ms、每曲一次 duration 等)、坏输入 55 例 / 396 断言、覆盖度矩阵 15 行、14 个 sdk_* 目标、TIMEOUT、-j4 全部未动。
  • 未引入跨平台条件编译 / POSIX 头 / 路径 API;新增用例的临时目录带 pid。

已知限制

C1 的 error→state 顺序与 C5 的「设备错误不跳轨」缺端到端判据:现有接缝无法稳定注入「带状态变化的错误」,新增可注入接缝违反规格 §8「不新造接缝」。两条由生产链改动 + 代码审查 + 全量回归锁定,详见规格 §10.4。契约漂移的长期观测口径仍交后续 effort。

wt159 added 9 commits November 8, 2026 10:43
- sdk/include/soundbridge/player.h 按规格 §10.2 落地五条契约注释:单线程串行、marshal 归调用方、回调内禁发命令/禁析构/禁抛异常、callbacks 所有权与存活期、停机期静默。
- PlayerMocks.hpp 两个 mock 增加事件序列(六个回调按到达顺序留档)与 firstEvent/countEvents 辅助,供曲目三连、error→state、幂等等判据复用。
- 不改任何生产链行为与公开签名;既有断言数值一字不动。
- onMusicPlayListError 把 onError 提到 updatePlayState 之前,与解码错误路径一致;原因是错误、结果是状态。
- updatePlayState 相同值只跳过通知、不改查询值:落实「重复控制命令不重复发 onStateChanged / 状态序列无相邻重复」契约。
- skip 失败不再补发第二次状态(同步那次即为规格要求的「一次状态事件」)。
- 新增可判定用例:无曲目 play() 只发一次 onError、零状态回调,错误不进状态面。
- 新增 reportPosition 统一三个位置出口:seek / 换曲重置单调基准(合法回退),消费循环的二次 asyncRunTask 按曲目会话钳制乱序旧值;旧曲迟到任务在新曲会话里直接丢弃。
- 钳制只作用于事件通知,不回写 signalProperties.curPositionMs、不改 position() 查询口径,seek 精度判据不动。
- PlayerMocks.hpp 增加位置值序列;新增可判定用例:稳态单调、seek 合法回退不被吞掉、回退后新会话仍单调。
- 生产链行为已符合规格 §7,本票不改代码,只把「四条无变化」升级为可红可绿判据。
- 用例一:无曲目且 duration()==0 时 seek 不产生任何回调、位置保持 0、状态 Stopped、无 onError。
- 用例二:曲目已加载但目标超界(与 durationMs==0 && pos>0 同一条降级 return)同样为空操作;pos==0 例外不产生错误或状态变化。
- 不新增公开 API、错误码或 onError 上报;沿用既有交互测试分组与观察窗口惯例。
- _play() 从 Stopped 起步时把 m_positionFloor 归零:stop 后重播同一曲目不经过 putMusicPlayListCurBuf,上一轮的基准会把新会话的 0 附近位置全部当成乱序旧值丢弃。
- 既有「stop 后重播从头起算」判据因此恢复;暂停后恢复不重置(位置继续增长,不受影响)。
- onMusicPlayListError 与 handleDecodeError 一样要求 ErrorAction::SkipTrack 才自动跳轨;设备错误(StopPlayback)不再靠跳轨绕过。
- 不改 shouldAutoSkipOnError() 的 count<=1 / failures<count 门槛(两处共用),不重构播放列表逻辑。
- test_error.cpp 增加可判定的 action 表,钉住「必须上报清单」与「有码不承诺上报」三码的输入值。
- 曲目切换固定 onTrackChanged → onDurationChanged → onPositionChanged,duration 每曲一次且与 getter 一致。
- 重复 play / pause / stop 不额外发状态回调,状态序列无相邻重复。
- 只扩既有分组与记录器,不改任何既有断言数值;重入 / 所有权 / ABI 类仍只写注释与规格。
- M1 位置会话代际:新增 m_positionEpoch,seek / 换曲 / 停机重播递增,回投队列的旧任务整体失效;单靠 trackIndex 无法区分同曲的两次会话,旧值会把新基准重新抬高。
- M2 状态通知:去重键改用「最近真正发出去的事件」而非 m_state 初值(首播失败 / skip 失败仍通知一次);onMusicPlayListError 不再无条件先置 Stopped,只在「不跳轨 / 跳轨失败」时发,autoSkip 成功不闪 Stopped。
- M3/M4 判据:T04 超界用例先起播让 currentTask 存在,真正进入 pos > durationMs 分支;否定断言改用「必然上报的命令」作队列屏障,去掉裸 sleep;无声卡场景加 skipCase。
- m1 mock reset() 对 vector 的 clear 加锁;m2 三连用例把 duration 计数限定在首个 position 之前的窗口;m3 补齐 Resample* 两码的 action 断言并修正注释;m4 修正「不新造数值」措辞。
- 全量 ctest -j4 14/14 绿;既有容差数值、坏输入 55 例、14 个目标与 TIMEOUT 全部未动。
- §10.1 标注 /to-tickets → /implement-spec 链已于 2026-11-08 跑完(#85–#92、integration branch)。
- 新增 §10.4:C1–C6 逐项落点、code-review 4 Major + 4 Minor 的修复、务实取舍(同批文件 + 本机构建缓存,逐票串行提交)、C1/C5 端到端判据缺口的原因与后续触发条件。
- §10.2 标题改为已落地;§10.3 明确契约漂移观测口径仍未裁决且若记录须标「不作为失败门禁」。
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