Merge pull request #33 from xuanerwa/dev

 Feat: add `yinliang` plugin
This commit is contained in:
Aynakeya
2025-03-05 20:03:38 +08:00
committed by GitHub
3 changed files with 225 additions and 1 deletions

View File

@@ -555,6 +555,34 @@
"plugin.wshub.webinfo_text": {
"en": "Obs browser output",
"zh-CN": "OBS网页输出: "
},
"plugin.yinliang.title": {
"en": "Volume Control",
"zh-CN": "音量控制"
},
"plugin.yinliang.description": {
"en": "Control volume via danmaku",
"zh-CN": "通过弹幕控制音量"
},
"plugin.yinliang.admin_permission": {
"en": "Admin only",
"zh-CN": "仅房管可操作"
},
"plugin.yinliang.volume_up_cmd": {
"en": "Volume increase command",
"zh-CN": "音量增加命令"
},
"plugin.yinliang.volume_down_cmd": {
"en": "Volume decrease command",
"zh-CN": "音量减少命令"
},
"plugin.yinliang.volume_step": {
"en": "Adjustment step (%)",
"zh-CN": "每次音量调整 (%)"
},
"plugin.yinliang.max_volume": {
"en": "Maximum volume (%)",
"zh-CN": "最大音量限制 (%)"
}
}
}

View File

@@ -16,6 +16,7 @@ import (
"AynaLivePlayer/plugin/sourcelogin"
"AynaLivePlayer/plugin/textinfo"
"AynaLivePlayer/plugin/wshub"
"AynaLivePlayer/plugin/yinliang"
)
func Initialize() {
@@ -26,7 +27,7 @@ func Initialize() {
liveroom.Initialize()
plugins.Initialize()
plugins.LoadPlugins(
diange.NewDiange(), qiege.NewQiege(), sourcelogin.NewSourceLogin(),
diange.NewDiange(), qiege.NewQiege(), yinliang.NewYinliang(), sourcelogin.NewSourceLogin(),
textinfo.NewTextInfo(),
durationmgmt.NewMaxDuration(),
wshub.NewWsHub(),

195
plugin/yinliang/yinliang.go Normal file
View File

@@ -0,0 +1,195 @@
package yinliang
import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/global"
"AynaLivePlayer/gui"
"AynaLivePlayer/gui/component"
"AynaLivePlayer/gui/xfyne"
"AynaLivePlayer/pkg/config"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
"fmt"
"strconv"
"strings"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/data/binding"
"fyne.io/fyne/v2/widget"
)
type Yinliang struct {
config.BaseConfig
AdminPermission bool
VolumeUpCMD string
VolumeDownCMD string
VolumeStep float64
MaxVolume float64
currentVolume float64
panel fyne.CanvasObject
}
func NewYinliang() *Yinliang {
return &Yinliang{
AdminPermission: true,
VolumeUpCMD: "音量调大",
VolumeDownCMD: "音量调小",
VolumeStep: 5.0,
MaxVolume: 50.0,
currentVolume: 50.0,
}
}
func (y *Yinliang) Name() string {
return "Yinliang"
}
func (y *Yinliang) Enable() error {
config.LoadConfig(y)
// 配置校验
if y.VolumeStep > 25 {
y.VolumeStep = 25
} else if y.VolumeStep < 0 {
y.VolumeStep = 5
}
if y.MaxVolume > 100 {
y.MaxVolume = 100
} else if y.MaxVolume < 0 {
y.MaxVolume = 0
}
gui.AddConfigLayout(y)
global.EventManager.RegisterA(
events.LiveRoomMessageReceive,
"plugin.yinliang.message",
y.handleMessage)
global.EventManager.RegisterA(
events.PlayerVolumeChangeCmd,
"plugin.yinliang.volume_tracker",
func(e *event.Event) {
data := e.Data.(events.PlayerVolumeChangeCmdEvent)
y.currentVolume = data.Volume
})
return nil
}
func (y *Yinliang) Disable() error {
return nil
}
func (y *Yinliang) handleMessage(event *event.Event) {
message := event.Data.(events.LiveRoomMessageReceiveEvent).Message
cmd := strings.TrimSpace(message.Message)
if cmd != y.VolumeUpCMD && cmd != y.VolumeDownCMD {
return
}
if !y.AdminPermission || !message.User.Admin {
return
}
delta := y.VolumeStep
if cmd == y.VolumeDownCMD {
delta = -y.VolumeStep
}
newVolume := y.currentVolume + delta
if newVolume > y.MaxVolume {
newVolume = y.MaxVolume
} else if newVolume < 0 {
newVolume = 0
}
global.EventManager.CallA(
events.PlayerVolumeChangeCmd,
events.PlayerVolumeChangeCmdEvent{
Volume: newVolume,
})
}
func (y *Yinliang) Title() string {
return i18n.T("plugin.yinliang.title")
}
func (y *Yinliang) Description() string {
return i18n.T("plugin.yinliang.description")
}
// 在CreatePanel方法中修改控件创建方式
func (y *Yinliang) CreatePanel() fyne.CanvasObject {
if y.panel != nil {
return y.panel
}
permCheck := component.NewCheckOneWayBinding(
i18n.T("plugin.yinliang.admin_permission"),
&y.AdminPermission,
y.AdminPermission)
cmdConfig := container.NewGridWithColumns(2,
widget.NewLabel(i18n.T("plugin.yinliang.volume_up_cmd")),
xfyne.EntryDisableUndoRedo(widget.NewEntryWithData(binding.BindString(&y.VolumeUpCMD))),
widget.NewLabel(i18n.T("plugin.yinliang.volume_down_cmd")),
xfyne.EntryDisableUndoRedo(widget.NewEntryWithData(binding.BindString(&y.VolumeDownCMD))),
)
stepEntry := widget.NewEntryWithData(binding.FloatToStringWithFormat(binding.BindFloat(&y.VolumeStep), "%.1f"))
stepEntry.Validator = createFloatValidator(0, 25)
stepEntry.OnChanged = func(s string) {
if v, err := strconv.ParseFloat(s, 64); err == nil {
if v > 25 {
y.VolumeStep = 25
stepEntry.SetText("25")
} else if v < 0 {
y.VolumeStep = 5
stepEntry.SetText("5")
}
}
}
maxVolEntry := widget.NewEntryWithData(binding.FloatToStringWithFormat(binding.BindFloat(&y.MaxVolume), "%.1f"))
maxVolEntry.Validator = createFloatValidator(0, 100)
maxVolEntry.OnChanged = func(s string) {
if v, err := strconv.ParseFloat(s, 64); err == nil {
if v > 100 {
y.MaxVolume = 100
maxVolEntry.SetText("100")
} else if v < 0 {
y.MaxVolume = 0
maxVolEntry.SetText("0")
}
}
}
volumeControlConfig := container.NewGridWithColumns(2,
widget.NewLabel(i18n.T("plugin.yinliang.volume_step")),
xfyne.EntryDisableUndoRedo(stepEntry),
widget.NewLabel(i18n.T("plugin.yinliang.max_volume")),
xfyne.EntryDisableUndoRedo(maxVolEntry),
)
y.panel = container.NewVBox(
permCheck,
cmdConfig,
volumeControlConfig,
)
return y.panel
}
func createFloatValidator(min, max float64) func(string) error {
return func(s string) error {
v, err := strconv.ParseFloat(s, 64)
if err != nil {
return fmt.Errorf(i18n.T("validation.number_required"))
}
if v < min || v > max {
return fmt.Errorf(i18n.T("validation.range_error"))
}
return nil
}
}