一. 什么是恒星播放器插件?
恒星插件是基于恒星播放器提供的接口开发的各式各样的小程序。这些小程序的运行依赖恒星播放器,使用这些小程序你可以实现诸如多媒体文件管理,视频处理等等各种功能。
二. 在哪里找到各式各样的恒星插件?
尝试在百度,贴吧,博客,知乎等地方搜索“恒星播放器 插件”,有些酷酷的小伙伴可能会在这些地方分享自己开发的插件链接,将链接粘贴在恒星播放器插件管理页面中,即可体验这些各式各样的插件。
恒星播放器公开了插件开发的接口和教程,对开发感兴趣的小伙伴都可以开发自己的专属插件,然后上传python代码文件到github上,最后在各类社区或自媒体分享你的插件github地址链接,就可以让大家体验你的作品了。
三. 如何安装恒星插件?
按照如下图步骤,安装恒星播放器插件。
插件入口
插件管理
启用插件
四. 我也能开发恒星插件吗?
插件开发者交流QQ群:614038264
插件基础信息
插件部署目录
播放器 data目录 \pyplugin\ 插件目录
基础文件结构
基础文件,作为插件必须含有 main.py
和 plugin.prop
两个文件
- main.py # 入口文件
- plugin.prop # 插件描述文件
插件目录
插件基本代码展示
main.py 内容
# -*- coding: utf-8 -*-
import StellarPlayer
class Plugin(StellarPlayer.IStellarPlayerPlugin):
def __init__(self, player:StellarPlayer.IStellarPlayer):
super().__init__(player)
def handleRequest(self, method, args):
if hasattr(self.simple, f"on_{method}"):
getattr(self.simple, f"on_{method}")(args)
def start(self):
print("插件启动")
def stop(self):
super().stop()
print("插件停止")
def newPlugin(player:StellarPlayer.IStellarPlayer,*arg):
print("插件初始化")
return Plugin(player)
插件运行原理
插件启动过程
- 播放器启动
- 加载插件目录
main.py
- 播放器在Python主线程中执行
main.py
中的newPlugin
函数,执行初始化操作 - 播放器在独立线程中执行
newPlugin
函数返回的Plugin
对象的Start
方法
插件运行状态
StellarPlayer.exe # 播放器主进程 Pid: 1000 线程 100 – python.exe
demoA/main.py => PluginAObj.Start() # 插件A Python主线程 线程 101 – python.exe
demoB/main.py => PluginBObj.Start() # 插件B Python主线程
main.py 介绍
main.py 为插件的主入口文件
插件初始化函数
本函数触发时机
- 在插件管理器手动激活插件时
- 播放器启动且插件在激活状态
函数会被传入一个 IStellarPlayerPlugin
派生类实例,类定义请具体查看后面章节 newPlugin
入口函数
def newPlugin(player):
"""函数调用入口函数
参数
----------
player : StellarPlayer.IStellarPlayer
IStellarPlayer对象实例
返回:
player
"""
destroyPlugin
销毁函数
def destroyPlugin(plugin:StellarPlayer.IStellarPlayerPlugin)
"""函数调用销毁函数
参数 ----------
plugin : StellarPlayer.IStellarPlayerPlugin
IStellarPlayerPlugin实例对象
返回:
player
"""
注意事项
- 本方法在解释器主线程执行,只可执行一些初始化的逻辑,执行耗时操作会导致播放器卡顿
- 本函数播放器在整个生命周期中只会调用一次
plugin.prop 文件介绍
为插件的描述文件,以每一行为key=value的形式表现,编码为UTF-8
文件必选字段
name
标识插件名称description
插件描述
播放器内置对象
插件系统统一命名规范
- 页面名称:
pageName
- 控件唯一标识:
controlId
- 元素索引:
itemIndex
IStellarPlayerPlugin 类介绍
- 该类为所有Python插件的通用基类,在播放器Python运行环境中内置,无需引用任何类库
- 插件必须实现一个继承于
IStellarPlayerPlugin
的子类
IStellarPlayerPlugin 结构及功能
class IStellarPlayerPlugin:
def __init__(self, player:StellarPlayer.IStellarPlayer):
构造函数
super().__init__(player)
def handleRequest(self, method, args):
处理播放器事件的回调函数
参数
----------
method : 播放器动作
def start(self):
插件主逻辑启动方法,播放器将主动调用此方法启动插件的核心逻辑
此方法将在python独立线程中执行
def stop(self):
插件的停止方法,调用本方法可以停止播放器对插件的线程执行
子类实现此方法必须需要调用super().stop(),否则插件线程无法停止
def onClick(self,pageName,controlId):
控件对象的回调函数
参数
----------
pageName: 被点击的页面标识
controlId: 被点击的控件标识
def onListItemDoubleClick(self,pageName,controlId,itemIndex):
列表的某一项元素被双击时,该方法会被调用
参数
----------
pageName: 被双击的页面标识
controlId: 被双击的控件标识
itemIndex: 被双击的列表元素索引
def onListItemControlClick(
self,pageName,listControlId,itemIndex,itemControlId):
列表的某一项子元素控件被单击时,该方法被调用
参数
----------
pageName: 被点击的页面标识
listControlId: 列表标识符id
itemIndex: 列表item索引, 第一个元素索引为0,以此类推
itemControlId: 被点击的子元素id
StellarPlayer 类介绍
- 该类为所有Python插件的通用基类,在播放器Python运行环境中内置,无需引用任何类库
IStellarPlayer 类结构及功能
class IStellarPlayer:
def call(method, *args):
事件回调函数
参数
----------
method : 播放器动作
args: 播放器传入的参数数组,为可变参数
def doModal(pageName, width, height, title, controls:list):
调用播放器弹窗组件渲染
参数
----------
pageName : 对话框唯一ID,此ID是当前播放器进程唯一存在,不可弹出2个相同的ID的对话框
width: 窗口宽度 int
height: 窗口高度 int
title: 窗口标题 string
controls: 控件配置数组,包含浮窗中渲染的控件配置信息,具体请看 插件布局系统介绍 章节
def play(url):
播放器URL地址
参数
----------
url : 媒体资源的URL地址, http、磁力链、本地文件路径
def getControlValue(pageName, controlId):
获取pageId对话框中,controlId对应的控件ID
参数
----------
pageId: 对话框Id
controlId: 控件名称
插件UI布局控件
控件分类
输入框
- 用户输入文本和文字信息
- 代码标识:edit
{
'type':'edit',
'name':'编辑器文本'
}
复选框
- 在一组选项中任意选择合适的选项
- 代码标识: check
{
'type':'check',
'name':'复选框'
}
单选框
- 在一组选项中选择其中一个
- 代码标识: radio
{
'type':'radio',
'name':'单选框'
}
按钮
- 实现一个按钮功能
- 代码标识:button
{
'type': 'button',
'name': '按钮文本'
}
超链接
- 实现一个超链接
- 代码标识:link
{
'type': 'link',
'value': 'https://www.baidu.com',
'name': '链接文本'
}
文本
- 显示一段文本
- 代码标识:label
{
'type': 'label',
'name': '文本样本'
}
图片
- 显示一个图片
- 代码标识:image
{
'type': 'image',
'value': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg'
}
分割对象
- 实现一个空白控件
- 代码标识:space
{
'type': 'space'
}
分组控件
- 用于描述控件集合
- 代码标识:group
{
'type': 'group',
'dir': 'horizontal' // horizontal 水平排列,vertical 垂直排列
}
列表组件
- 代码标识: list
{
'type': 'list',
'itemheight': 100, // list每个元素的高度, 可选,默认30
'marginSize': 10 // list每个元素的间距大小,可选,默认1
'itemlayout': [
// 列表每一行元素的布局配置
],
'value': [] # 布局的数据
}
注意事项
- 行元素高度宽度由
itemheight
控制,布局时请确保行元素的高宽可以容下内部元素
网格组件
- 代码标识: grid
{
'type': 'grid',
'itemheight': 100, // list每个元素的高度, 可选,默认30
'marginSize': 10, // list每个元素的间距大小,可选,默认1
'itemwidth': 30, // 每个元素的宽度
'itemlayout': [
// 网格每一个元素布局的配置, 数组
],
'value': [] // 布局的数据
}
注意事项
- 网格元素高度宽度由
itemheight
和itemwidth
控制,布局时请确保行元素的高宽可以容下内部元素
控件属性
Width属性
- 可选属性,不配置默认值为自动适应宽度
值配置
- 比例值,使用浮点数,当前父容器宽度
- 绝对值,使用整数,单位为像素
一行多元素宽度算法
同一行中所有所有控件没有设定width属性
- 所有控件将根据窗口总宽度平均分配宽度
- 例:窗口宽100px,4个控件,每个控件自动宽度为25px
同一行中所有控件均设定了width属性
- 将按照实际配置宽度渲染
- 例:窗口宽100px,3个控件,每个控件均设置宽度为25px,三个控件靠左渲染,实际宽度75px
同一行中部分控件设定了width属性
- 设定宽度的控件按照设定宽度渲染
- 剩余未设定宽度的控件根据(窗口宽度 – 设定宽度控件宽度之和)平分剩余宽度
- 例:窗口宽100px,3个控件,2个控件设定宽度为25px,1个控件宽度未设置,实际渲染结果为 25px(设定宽度) + 25px(设定宽度) + 50px(未设定宽度)
height属性
- 可选属性,不配置默认值为自动适应高度
值配置
- 比例值,使用浮点数,当前父容器高度
- 绝对值,使用整数,单位为像素
value属性
- 可选属性,用于那些些需要设定内容、值的控件
- 字符串
textColor属性
- 可选属性
- 字符串:设置文本颜色,使用HEX表示法:#ff0000 表示红色
fontSize属性
- 可选属性
- 整数值:设置文本字体大小,单位为像素
clickable属性
- 可选属性
- 仅适用
label
,image
控件 - 布尔:用来表示该控件是否可点击
@click属性
值为点击回调方法名称
{
'type':'button',
'name':'Update',
'width':60,
'matchParent':True,
'@click':'on_update_click' # 点击回调方法,对应Plugin类的同名方法
}
控件布局
播放器当前使用简化布局方式,方便开发者快速定义UI布局
基本原理
为简化布局开发成本,恒星播放器当前使用简单的栅格式布局方式,以一个list列表对象为容器,列表每一个元素为一行,且可以嵌套
示例A,两个文本输入控件处于上下排列
controls = [
{'type':'edit', 'name':'用户名'},
{'type':'edit', 'name':'密码'}
]
示例B,两个文本输入控件在同一行排列
controls = [
[
{'type':'edit', 'name':'用户名'},
{'type':'edit', 'name':'密码'}
] # 行为列表,包含两个控件对象,两个控件宽度各占行的一半空间
]
示例C,
controls = [
[
{'type':'edit', 'name':'用户名'},
{'type':'edit', 'name':'密码'}
], # 第一行,双控件
{'type':'edit', 'name':'验证码'} # 第二行,单控件
]
列表、网格对象布局和赋值
功能简介
1. 列表/网格对象需要提供布局定义其元素的配置,使用 itemlayout 属性定义
2. 对列表/网格对象填充数据,需要使用 value 对象按照定义的布局格式进行填充
# 实例A
[
{
'type': 'list',
'itemheight': 100,
'itemwidth': 100,
'itemlayout': [ # 必须是数组
{
'type': 'image',
'name': 'example-photo'
'height': 100,
'width': 50
}
],
'value': [ # 渲染5行图片
{
# 这里example-photo对应layout中对象的name,每行唯一 'example-photo': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg'
},
{
'example-photo': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg'
},
{
'example-photo': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg'
},
{
'example-photo': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg'
},
{
'example-photo': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg'
},
]
}
]
# 实例B
[
{
'type': 'list',
'itemheight': 100,
'itemwidth': 100,
'itemlayout': [ # 一行含有一个图片和一个文本标记元素
{
'type': 'image',
'name': 'example-photo'
},
{
'type': 'label',
'name': 'example-label'
}
],
'value': [
{
# 这里example-photo对应layout中对象的name,每行唯一
'example-photo': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg',
'example-label' : '这是一行演示文本'
},
{
'example-photo': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg',
'example-label' : '这是一行演示文本'
},
{
'example-photo': 'https://wx1.sinaimg.cn/orj360/006wVUPtgy1gstem06e9sj30u018fgwy.jpg',
'example-label' : '这是一行演示文本'
}
]
}
]
插件日志目录
打开Windows文件管理器,在地址栏输入这个地址,即可打开日志目录
%APPDATA%\StellarPlayer\logs
- 默认播放器会拆分插件日志,格式为 Plugin-日期-时分.log
- 为了方便调试,可以在播放器安装目录中创建一个空白文件,名称为 single_log_flag,播放器会将所有插件日志合并到Plugin-.log一个文件中,方便调试开发
打印日志
直接使用python的print函数打印日志,打印内容会自动输出到日志文件中
插件代码重新加载
修改插件代码代码后,请在插件面板关闭并重启激活插件,播放器会重新加载插件代码并执行
参考文档
python文档编写指南
https://realpython.com/documenting-python-code/#docstring-formats
插件基础运行环境
Python 运行环境版本信息
Windows 64位 V3.8.10
Python 内置类库信息
打印已运行环境中安装的包及版本的号的代码
import pkg_resources
installed_packages = pkg_resources.working_set
installed_packages_list = sorted(["%s==%s" % (i.key, i.version)
for i in installed_packages])
print(installed_packages_list)
运行环境内置功能库及版本
# Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.
# 文档https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/beautifulsoup4==4.9.3
# 验证ssl证书的可信度 certifi==2021.5.30
# 文本编码库
# https://charset-normalizer.readthedocs.io/en/latest/charset-normalizer==2.0.3
# 域名解析库
# 文档https://pypi.org/project/idna/idna==3.2
# python包管理库pip==21.1.3
# http请求库
# 文档 https://docs.python-requests.org/zh_CN/latest/requests==2.26.0
# 安装工具setuptools==57.4.0
# CSS选择引擎
# 文档 https://pypi.org/project/soupsieve/soupsieve==2.2.1
# URL请求库
# 文档 https://urllib3.readthedocs.io/en/stable/urllib3==1.26.6
# Wheel安装包库
# 文档 https://pythonwheels.com/wheel==0