恒星播放器插件系统

一. 什么是恒星播放器插件?

恒星插件是基于恒星播放器提供的接口开发的各式各样的小程序。这些小程序的运行依赖恒星播放器,使用这些小程序你可以实现诸如多媒体文件管理,视频处理等等各种功能。

二. 在哪里找到各式各样的恒星插件?

尝试在百度,贴吧,博客,知乎等地方搜索“恒星播放器 插件”,有些酷酷的小伙伴可能会在这些地方分享自己开发的插件链接,将链接粘贴在恒星播放器插件管理页面中,即可体验这些各式各样的插件。

恒星播放器公开了插件开发的接口和教程,对开发感兴趣的小伙伴都可以开发自己的专属插件,然后上传python代码文件到github上,最后在各类社区或自媒体分享你的插件github地址链接,就可以让大家体验你的作品了。

三. 如何安装恒星插件?

按照如下图步骤,安装恒星播放器插件。

恒星播放器插件系统插图
插件入口
恒星播放器插件系统插图1
插件管理
恒星播放器插件系统插图2
启用插件
恒星播放器插件系统插图3

四. 我也能开发恒星插件吗?

插件开发者交流QQ群:614038264

插件基础信息

插件部署目录

播放器 data目录 \pyplugin\ 插件目录

基础文件结构

基础文件,作为插件必须含有main.pyplugin.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) 

插件运行原理

插件启动过程

  1. 播放器启动
  2. 加载插件目录main.py
  3. 播放器在Python主线程中执行main.py中的newPlugin函数,执行初始化操作
  4. 播放器在独立线程中执行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': [] # 布局的数据 
}

注意事项

  1. 行元素高度宽度由itemheight控制,布局时请确保行元素的高宽可以容下内部元素

网格组件

  • 代码标识: grid
{     
    'type': 'grid',
    'itemheight': 100, // list每个元素的高度, 可选,默认30
    'marginSize': 10, // list每个元素的间距大小,可选,默认1
    'itemwidth': 30, // 每个元素的宽度
    'itemlayout': [ 
        // 网格每一个元素布局的配置, 数组              
    ],
    'value': [] // 布局的数据 
}

注意事项

  1. 网格元素高度宽度由itemheightitemwidth控制,布局时请确保行元素的高宽可以容下内部元素

控件属性

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属性

  • 可选属性
  • 仅适用labelimage控件
  • 布尔:用来表示该控件是否可点击

@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

发布者

头像

恒星播放器

官方号