package luaplugin import lua "github.com/yuin/gopher-lua" // registerControlAPI adds cliamp.player control methods (next, prev, play_pause, // stop, set_volume, set_speed, seek, toggle_mono, set_eq_band) to the cliamp table. // These are only functional if the plugin declared permissions = {"control"}. func registerControlAPI(L *lua.LState, cliamp *lua.LTable, ctrl *ControlProvider, p *Plugin, logger *pluginLogger) { playerTbl := L.GetField(cliamp, "player") tbl, ok := playerTbl.(*lua.LTable) if !ok { return } warned := false guard := func(name string) bool { if !p.perms[PermControl] { if !warned { logger.log(p.Name, "warn", "%s requires permissions = {\"control\"} — further warnings suppressed", name) warned = true } return false } return true } L.SetField(tbl, "next", L.NewFunction(func(L *lua.LState) int { if guard("next") { ctrl.Next() } return 0 })) L.SetField(tbl, "prev", L.NewFunction(func(L *lua.LState) int { if guard("prev") { ctrl.Prev() } return 0 })) L.SetField(tbl, "play_pause", L.NewFunction(func(L *lua.LState) int { if guard("play_pause") { ctrl.TogglePause() } return 0 })) L.SetField(tbl, "stop", L.NewFunction(func(L *lua.LState) int { if guard("stop") { ctrl.Stop() } return 0 })) L.SetField(tbl, "set_volume", L.NewFunction(func(L *lua.LState) int { if !guard("set_volume") { return 0 } db := float64(L.CheckNumber(1)) ctrl.SetVolume(max(min(db, 6), -30)) return 0 })) L.SetField(tbl, "set_speed", L.NewFunction(func(L *lua.LState) int { if !guard("set_speed") { return 0 } ratio := float64(L.CheckNumber(1)) ctrl.SetSpeed(max(min(ratio, 2.0), 0.25)) return 0 })) L.SetField(tbl, "seek", L.NewFunction(func(L *lua.LState) int { if !guard("seek") { return 0 } ctrl.Seek(float64(L.CheckNumber(1))) return 0 })) L.SetField(tbl, "toggle_mono", L.NewFunction(func(L *lua.LState) int { if guard("toggle_mono") { ctrl.ToggleMono() } return 0 })) // set_eq_preset("name") or set_eq_preset("name", {band1, band2, ..., band10}) L.SetField(tbl, "set_eq_preset", L.NewFunction(func(L *lua.LState) int { if !guard("set_eq_preset") { return 0 } name := L.CheckString(1) var bands *[10]float64 if tbl := L.OptTable(2, nil); tbl != nil { b := [10]float64{} for i := range 10 { v := tbl.RawGetInt(i + 1) if v == lua.LNil { // A partial table would silently zero the unset bands; // require all 10 so the caller's intent is explicit. L.ArgError(2, "eq bands table must contain all 10 values") return 0 } b[i] = max(min(float64(lua.LVAsNumber(v)), 12), -12) } bands = &b } ctrl.SetEQPreset(name, bands) return 0 })) L.SetField(tbl, "set_eq_band", L.NewFunction(func(L *lua.LState) int { if !guard("set_eq_band") { return 0 } band := L.CheckInt(1) - 1 // Lua 1-indexed → Go 0-indexed if band < 0 || band > 9 { L.ArgError(1, "band must be 1-10") return 0 } db := float64(L.CheckNumber(2)) ctrl.SetEQBand(band, max(min(db, 12), -12)) return 0 })) }