Skip to content

feat: 插件系统新增控制类插件(control) - #52

Merged
imsyy merged 26 commits into
devfrom
feat/control-plugin-type
Jun 26, 2026
Merged

imsyy merged 26 commits into
devfrom
feat/control-plugin-type

Conversation

@imsyy

@imsyy imsyy commented Jun 25, 2026

Copy link
Copy Markdown
Member

概述

本 PR 为插件系统新增控制类插件(@type control)。在原有「音源插件」(解析播放地址)之外,插件现在可以:

  • 监听播放状态:曲目切换、歌词整体变化、当前歌词行变化、播放态变化(playing / paused / stopped);
  • 反向控制播放:play / pause / next / prev / seek / setVolume / getPosition;
  • 声明自己的设置项:switch / number / text / select,渲染到插件管理的设置弹窗,用户改动实时下发到插件。

与音源插件一致,每个控制插件运行在独立隔离进程中,崩溃 / 卡死自动恢复,互不影响。

与 #49 的关系(可用插件解决)

#49(ClassIsland 联动)把「订阅播放/歌词事件并 POST 到本地 HTTP 服务」的逻辑硬编码进主进程(新增 lyricsIsland.ts + 专属设置 / i18n / logger)。这正是控制类插件要解决的一类需求——这类「把播放状态推送到外部服务」的集成,现在可以写成一个控制插件,无需改动应用本体。

事实上,控制插件文档里的完整示例就是一个 ClassIsland 联动插件:订阅 trackChange / lyricChange / lineChange,按用户设置(端口 / 是否翻译 / 无翻译回退下一行)POST 到 http://127.0.0.1:50063/component/lyrics/lyrics/,与 #49 行为一致,但以插件形态分发,不进主仓库。

这样带来的好处:

  • 类似的第三方集成(ClassIsland、其他大屏 / 外设 / 状态上报)可由社区以插件形式维护,避免逐个 PR 往主进程塞场景化代码;
  • 用户按需安装,不增加默认包体与常驻开销。

因此建议 #49 改以控制插件形态提供(示例已在文档中给出),主仓库不再内置 ClassIsland 专属服务。

主要改动

插件运行时

  • 解析 @type 头部,插件类型以 PLUGIN_TYPES 清单为唯一来源;
  • 沙箱支持事件下发 / 反向控制 / 设置回流 / 控制类能力注册上报;
  • playbackBridge:聚合 nowPlaying 事件,仅在语义变化时推送给订阅插件(5Hz 的 position-sync 只在主进程消费,仅行索引 / 播放态变化才下发,避免高频 IPC 外泄);
  • playerControl:把「系统媒体 / HTTP / WS / 控制插件」四个外部播放控制入口收敛到一处;
  • hostCall 支持 player.*;新增 plugin:setSetting IPC 与预加载暴露。

界面

  • 插件管理按类型分区,控制插件的设置以弹窗表单呈现,样式对齐设置页。

修复(本轮 review 后定点修复)

  • 控制插件就绪时定向补发当前状态快照,修复「第二个控制插件中途启用拿不到初始状态」;
  • playStateChange 补回 stopped,与 paused 区分;
  • 主 → worker 投递增加 clone 失败兜底,避免异常冒泡进事件总线;
  • getPosition 明确为偶发查询用途(持续进度请读事件载荷里的 position)。

文档

  • 插件文档拆为 总览与架构 / 音源插件 / 控制插件 三篇,补全控制类 API、API 级别说明、LyricLine / PluginSettingItem 字段、音源插件的调用机制与 source key 约定,以及 ClassIsland 完整示例。

测试

  • pnpm typecheck 通过;
  • 改动文件 eslint / prettier 通过;
  • pnpm docs:build 通过。

imsyy and others added 25 commits June 25, 2026 14:45
Copilot AI review requested due to automatic review settings June 25, 2026 16:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

本 PR 为插件系统新增「控制类插件(@type control)」能力:主进程向控制插件扇出高层播放事件(曲目/歌词/行/播放态),并允许插件反向控制播放与声明可配置设置项;同时调整插件管理 UI 与文档结构,以支持按类型分区与控制插件配置弹窗。

Changes:

  • 插件契约与沙箱通信扩展:新增 control 类型、播放事件/反控 API、设置项 schema 与设置变更推送链路。
  • 主进程新增 playbackBridge 与 playerControl:惰性订阅 nowPlaying 并按订阅扇出事件,外部控制入口统一收敛。
  • 渲染端插件管理 UI 升级:按「音源/控制」分区展示,新增控制插件配置弹窗表单与设置写入。

Reviewed changes

Copilot reviewed 32 out of 33 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/stores/plugins.ts 插件列表按类型分组;启用逻辑区分 source 互斥与 control 可并行;新增 setSetting 写回。
src/i18n/locales/zh-CN.json 插件管理新增分区与配置弹窗副标题文案。
src/i18n/locales/en-US.json 同上(英文)。
src/components/settings/custom/PluginSettingsForm.vue 新增控制插件设置 schema 的表单渲染组件。
src/components/settings/custom/PluginManager.vue 插件管理页改为音源/控制分区 + 控制插件配置弹窗。
src/components/settings/custom/PluginCard.vue 抽卡片组件,统一状态展示/启停/卸载/(可选)配置入口。
shared/types/plugin.ts 扩展插件类型、控制事件载荷、设置项 schema、Host API(player/onSettingChange)与沙箱消息协议。
shared/types/nowPlaying.ts nowPlaying 快照/同步结构补充完整 state(区分 paused/stopped)。
shared/defaults/plugin-api.ts HOST_API_LEVEL 升级到 2。
electron/preload/index.ts 预加载新增 window.api.plugins.setSetting IPC 暴露。
electron/main/services/playerControl.ts 新增播放控制聚合入口,供 WS/REST/插件 hostCall 复用。
electron/main/services/nowPlaying.ts nowPlaying 增补 PlayerState 同步;订阅方法改为返回取消订阅函数。
electron/main/server/ws.ts WS 控制命令改走 playerControl。
electron/main/server/routes.ts REST 控制路由改走 playerControl。
electron/main/plugins/sandbox.worker.ts 沙箱侧注入 splayer.player、事件回调注册与 onSettingChange;上报 control 注册信息。
electron/main/plugins/sandbox.ts 主→worker 投递增加 clone 失败兜底;新增 event/settingsUpdate 下发方法。
electron/main/plugins/registry.ts registry 记录 control 注册信息与 per-plugin settingsValues;新增 setSetting;新增控制事件扇出。
electron/main/plugins/playbackBridge.ts 新增播放事件桥:从 nowPlaying 聚合语义变化并扇出给订阅的控制插件,支持就绪补发快照。
electron/main/plugins/loader.ts 解析 @type 并校验类型清单;对 control+低 apiLevel 给出告警。
electron/main/plugins/host.ts hostCall 新增 player.* 分发到 playerControl。
electron/main/ipc/plugin.ts 新增 plugin:setSetting IPC 处理。
electron/main/ipc/player.ts 引擎 stateChanged 透传完整 PlayerState 到 nowPlaying。
electron/main/core/index.ts 启动/退出时 init/dispose playbackBridge。
docs/streaming.md 文案微调(“网易云音源”→“在线音源”)。
docs/plugins/source.md 新增音源插件文档(工作原理、source key、示例、约定)。
docs/plugins/index.md 新增插件总览与架构文档(类型、API 级别、通用 API、约束)。
docs/plugins/control.md 新增控制插件文档(事件、反控、设置项、ClassIsland 示例)。
docs/plugins-usage.md 用户指南更新:补充控制插件并行启用与配置入口。
docs/plugins-development.md 删除旧“插件开发指南”(由新的三篇文档取代)。
docs/native.md 补充 taskbar-thumbnail 模块说明与别名列表更新。
docs/guide.md 更新插件文档链接指向新目录。
docs/.vitepress/config.ts 文档导航更新:插件开发改为多级菜单(总览/音源/控制)。
components.d.ts 自动注册声明更新:新增 PluginCard / PluginSettingsForm。

Comment on lines 354 to 359
onSourcesUpdate: (sources) => {
// 异步 lx.send('inited') / splayer.register 触发
if (rt.status.state !== "ready") return;
const merged = { ...rt.status.sources, ...sources };
this.setStatus(rt, { state: "ready", sources: merged });
},
Comment on lines +521 to +526
async setSetting(id: string, key: string, value: unknown): Promise<void> {
const rt = this.runtimes.get(id);
if (!rt) return;
const item = rt.settings.find((setting) => setting.key === key);
const sanitized = sanitizeSettingValue(item, value);
const all = {
Comment thread docs/plugins/control.md Resolved
Comment on lines +24 to +28
play: (): void =>
void getPlayer()
.play()
.catch(() => {}),
pause: (): void => getPlayer().pause(),
Comment on lines +133 to +137
if (rawType === "control" && apiLevel < 2) {
pluginLog.warn(
`插件 "${name}" 声明 type=control 但 apiLevel=${apiLevel}(需 >= 2),控制类功能将在运行时受限`,
);
}
@imsyy
imsyy merged commit 55c2f30 into dev Jun 26, 2026
6 checks passed
@imsyy
imsyy deleted the feat/control-plugin-type branch June 26, 2026 04:50
roarrabbit pushed a commit to roarrabbit/SPlayer-Next that referenced this pull request Aug 27, 2026
…n-type

feat: 插件系统新增控制类插件(control)
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.

2 participants