feat: 实现动态插件系统 (6阶段完成)

- 阶段1: 消息类型序列化 (Serialize/Deserialize, &'static str → String)
- 阶段2: FFI 边界类型 + Plugin SDK (plugin_abi, showen-plugin-sdk crate)
- 阶段3: PluginLoader + DynamicPlugin (libloading 动态加载 .so)
- 阶段4: 版本管理 + 错误策略 (VersionManager, PluginState, 自动回退)
- 阶段5: 远程仓库客户端 (HTTP 下载 + tar.gz 安装)
- 阶段6: 示例插件 + HTTP 管理 API + 全目录 README 文档

54/54 测试通过,0 warnings。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
showen
2026-03-13 03:38:08 +08:00
parent 5dcc1ad98e
commit 7135f28545
62 changed files with 3501 additions and 299 deletions

View File

@@ -48,7 +48,7 @@ impl VideoPlugin {
};
if let Err(error) = ctx.tx.send(Envelope {
from: self.id(),
from: self.id().to_string(),
to: Destination::Broadcast,
message: Message::PlayerStatus(status),
}) {
@@ -70,7 +70,7 @@ impl VideoPlugin {
}
if let Err(error) = ctx.tx.send(Envelope {
from: self.id(),
from: self.id().to_string(),
to: Destination::Broadcast,
message: Message::StateChanged {
old_state,
@@ -89,20 +89,20 @@ impl Default for VideoPlugin {
}
impl Plugin for VideoPlugin {
fn id(&self) -> &'static str {
fn id(&self) -> &str {
"video"
}
fn info(&self) -> PluginInfo {
PluginInfo {
name: "Video Player",
version: "0.2.0",
description: "视频播放引擎 (OpenCV)",
name: "Video Player".to_string(),
version: "0.2.0".to_string(),
description: "视频播放引擎 (OpenCV)".to_string(),
platform: Platform::Any,
}
}
fn dependencies(&self) -> Vec<&'static str> {
fn dependencies(&self) -> Vec<String> {
vec![]
}
@@ -130,9 +130,9 @@ impl Plugin for VideoPlugin {
self.worker = Some(handle);
ctx.tx.send(Envelope {
from: self.id(),
from: self.id().to_string(),
to: Destination::Manager,
message: Message::PluginReady(self.id()),
message: Message::PluginReady(self.id().to_string()),
})?;
self.publish_status();
@@ -150,8 +150,8 @@ impl Plugin for VideoPlugin {
// 恢复播放时重新获取防息屏锁
if let Some(ctx) = &self.ctx {
let _ = ctx.tx.send(Envelope {
from: self.id(),
to: Destination::Plugin("screen"),
from: self.id().to_string(),
to: Destination::Plugin("screen".to_string()),
message: Message::ScreenLockRequest(true),
});
}
@@ -161,8 +161,8 @@ impl Plugin for VideoPlugin {
// 暂停时释放防息屏锁
if let Some(ctx) = &self.ctx {
let _ = ctx.tx.send(Envelope {
from: self.id(),
to: Destination::Plugin("screen"),
from: self.id().to_string(),
to: Destination::Plugin("screen".to_string()),
message: Message::ScreenLockRequest(false),
});
}
@@ -324,7 +324,7 @@ fn publish_status_message(
status: PlayerStatusData,
) -> Result<()> {
tx.send(Envelope {
from: "video",
from: "video".to_string(),
to: Destination::Broadcast,
message: Message::PlayerStatus(status),
})?;
@@ -345,7 +345,7 @@ fn publish_state_changed(
}
tx.send(Envelope {
from: "video",
from: "video".to_string(),
to: Destination::Broadcast,
message: Message::StateChanged {
old_state,