🎉 Implement working Audio Mixer backend with Jack support
This commit is contained in:
297
api.go
Normal file
297
api.go
Normal file
@ -0,0 +1,297 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func initApi() {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
router := gin.Default()
|
||||
router.SetTrustedProxies(nil)
|
||||
|
||||
router.GET("/api/ports", func(c *gin.Context) {
|
||||
c.JSON(200, portConfig)
|
||||
})
|
||||
router.GET("/api/port", handleGetPort)
|
||||
router.POST("/api/ports", handleCreatePort)
|
||||
router.DELETE("/api/ports", handleDeletePort)
|
||||
|
||||
router.GET("/api/state", handleGetState)
|
||||
router.PUT("/api/state", handleSetState)
|
||||
|
||||
router.POST("/api/routes", handleCreateRoute)
|
||||
router.PUT("/api/routes", handleSetRoute)
|
||||
router.DELETE("/api/routes", handleDeleteRoute)
|
||||
|
||||
router.Run(fmt.Sprintf("%s:%d", config.Web.Bind, config.Web.Port))
|
||||
}
|
||||
|
||||
func handleGetPort(c *gin.Context) {
|
||||
id := c.Query("UUID")
|
||||
if id == "" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "`UUID` parameter missing!"})
|
||||
return
|
||||
}
|
||||
|
||||
port, portIndex, _ := findPort(id)
|
||||
if portIndex < 0 {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Port with provided UUID does not exist!"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, port)
|
||||
}
|
||||
|
||||
type CreatePortRequest struct {
|
||||
Name string
|
||||
Backend string
|
||||
Channels uint8
|
||||
Type string
|
||||
}
|
||||
|
||||
func handleCreatePort(c *gin.Context) {
|
||||
var body CreatePortRequest
|
||||
if err := c.BindJSON(&body); err != nil {
|
||||
c.JSON(500, gin.H{"success": false, "error": "Parsing request body failed!"})
|
||||
return
|
||||
}
|
||||
if body.Name == "" || body.Backend == "" || body.Channels == 0 || body.Type == "" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Required parameters missing!"})
|
||||
return
|
||||
}
|
||||
if body.Type != "input" && body.Type != "output" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "`Type` must either be `input` or `output`"})
|
||||
return
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
newPort := Port{
|
||||
UUID: id.String(),
|
||||
Name: body.Name,
|
||||
Properties: PortProperties{
|
||||
Backend: body.Backend,
|
||||
Channels: body.Channels,
|
||||
},
|
||||
State: PortState{
|
||||
Mute: false,
|
||||
Volume: 0,
|
||||
Balance: 0,
|
||||
},
|
||||
Route: []PortRoute{},
|
||||
}
|
||||
|
||||
if body.Type == "input" {
|
||||
registerPort(&newPort, "input")
|
||||
portConfig.Input = append(portConfig.Input, newPort)
|
||||
} else {
|
||||
registerPort(&newPort, "output")
|
||||
portConfig.Output = append(portConfig.Output, newPort)
|
||||
}
|
||||
saveConfig("ports", &portConfig)
|
||||
|
||||
c.JSON(200, gin.H{"success": true, "UUID": newPort.UUID})
|
||||
}
|
||||
|
||||
type DeletePortRequest struct {
|
||||
UUID string
|
||||
}
|
||||
|
||||
func handleDeletePort(c *gin.Context) {
|
||||
var body DeletePortRequest
|
||||
if err := c.BindJSON(&body); err != nil {
|
||||
c.JSON(500, gin.H{"success": false, "error": "Parsing request body failed!"})
|
||||
return
|
||||
}
|
||||
if body.UUID == "" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Required parameters missing!"})
|
||||
return
|
||||
}
|
||||
|
||||
port, portIndex, portType := findPort(body.UUID)
|
||||
if portIndex < 0 {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Port with provided UUID does not exist!"})
|
||||
return
|
||||
}
|
||||
|
||||
// Remove the port from the configuration
|
||||
if portType == "output" {
|
||||
portConfig.Output = append(portConfig.Output[:portIndex], portConfig.Output[portIndex+1:]...)
|
||||
} else {
|
||||
portConfig.Input = append(portConfig.Input[:portIndex], portConfig.Input[portIndex+1:]...)
|
||||
}
|
||||
|
||||
// Unregister port
|
||||
unregisterPort(port)
|
||||
|
||||
saveConfig("ports", &portConfig)
|
||||
}
|
||||
|
||||
func handleGetState(c *gin.Context) {
|
||||
id := c.Query("UUID")
|
||||
if id == "" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "`UUID` parameter missing!"})
|
||||
return
|
||||
}
|
||||
|
||||
port, portIndex, _ := findPort(id)
|
||||
if portIndex < 0 {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Port with provided UUID does not exist!"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, port.State)
|
||||
}
|
||||
|
||||
type SetPortRequest struct {
|
||||
Mute *bool
|
||||
Volume *float32
|
||||
Balance *float32
|
||||
}
|
||||
|
||||
func handleSetState(c *gin.Context) {
|
||||
var body SetPortRequest
|
||||
err := c.BindJSON(&body)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"success": false, "error": "Parsing request body failed!"})
|
||||
return
|
||||
}
|
||||
|
||||
id := c.Query("UUID")
|
||||
if id == "" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "`UUID` parameter missing!"})
|
||||
return
|
||||
}
|
||||
|
||||
port, portIndex, _ := findPort(id)
|
||||
if portIndex < 0 {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Port with provided UUID does not exist!"})
|
||||
return
|
||||
}
|
||||
|
||||
if body.Mute != nil {
|
||||
port.State.Mute = *body.Mute
|
||||
}
|
||||
if body.Volume != nil {
|
||||
port.State.Volume = *body.Volume
|
||||
}
|
||||
if body.Balance != nil {
|
||||
port.State.Balance = *body.Balance
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{"success": true, "state": port.State})
|
||||
saveConfig("ports", &portConfig)
|
||||
}
|
||||
|
||||
type CreateRouteRequest struct {
|
||||
To string
|
||||
}
|
||||
|
||||
func handleCreateRoute(c *gin.Context) {
|
||||
var body CreateRouteRequest
|
||||
err := c.BindJSON(&body)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"success": false, "error": "Parsing request body failed!"})
|
||||
return
|
||||
}
|
||||
|
||||
id := c.Query("UUID")
|
||||
if id == "" || body.To == "" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Required parameters missing!"})
|
||||
return
|
||||
}
|
||||
|
||||
from, fromIndex, fromType := findPort(id)
|
||||
_, toIndex, toType := findPort(body.To)
|
||||
if fromIndex < 0 || toIndex < 0 {
|
||||
c.JSON(400, gin.H{"success": false, "error": "One of `UUID` or `To` does not exist!"})
|
||||
return
|
||||
}
|
||||
if fromType != "input" || toType != "output" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "`UUID` needs to be an input and `To` an output port!"})
|
||||
return
|
||||
}
|
||||
|
||||
from.Route = append(from.Route, PortRoute{ToUUID: body.To, Mute: true, Volume: 0, Balance: 0})
|
||||
saveConfig("ports", &portConfig)
|
||||
|
||||
c.JSON(200, gin.H{"success": true})
|
||||
}
|
||||
|
||||
type SetRouteRequest struct {
|
||||
Mute *bool
|
||||
Volume *float32
|
||||
Balance *float32
|
||||
}
|
||||
|
||||
func handleSetRoute(c *gin.Context) {
|
||||
var body SetRouteRequest
|
||||
err := c.BindJSON(&body)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"success": false, "error": "Parsing request body failed!"})
|
||||
return
|
||||
}
|
||||
|
||||
fromId := c.Query("UUID")
|
||||
toId := c.Query("To")
|
||||
if fromId == "" || toId == "" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Required parameters missing!"})
|
||||
return
|
||||
}
|
||||
|
||||
from, fromIndex, _ := findPort(fromId)
|
||||
if fromIndex < 0 {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Port with provided UUID does not exist!"})
|
||||
return
|
||||
}
|
||||
for i, r := range from.Route {
|
||||
if r.ToUUID != toId {
|
||||
continue
|
||||
}
|
||||
|
||||
if body.Mute != nil {
|
||||
from.Route[i].Mute = *body.Mute
|
||||
}
|
||||
if body.Volume != nil {
|
||||
from.Route[i].Volume = *body.Volume
|
||||
}
|
||||
if body.Balance != nil {
|
||||
from.Route[i].Balance = *body.Balance
|
||||
}
|
||||
|
||||
saveConfig("ports", &portConfig)
|
||||
c.JSON(200, gin.H{"success": true})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{"success": false, "error": "No such route exists!"})
|
||||
}
|
||||
|
||||
func handleDeleteRoute(c *gin.Context) {
|
||||
fromId := c.Query("UUID")
|
||||
toId := c.Query("To")
|
||||
if fromId == "" || toId == "" {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Required parameters missing!"})
|
||||
return
|
||||
}
|
||||
|
||||
from, fromIndex, _ := findPort(fromId)
|
||||
if fromIndex < 0 {
|
||||
c.JSON(400, gin.H{"success": false, "error": "Port with provided UUID does not exist!"})
|
||||
return
|
||||
}
|
||||
for i, r := range from.Route {
|
||||
if r.ToUUID != toId {
|
||||
continue
|
||||
}
|
||||
|
||||
from.Route = append(from.Route[:i], from.Route[i+1:]...)
|
||||
saveConfig("ports", &portConfig)
|
||||
c.JSON(200, gin.H{"success": true})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, gin.H{"success": false, "error": "No such route exists!"})
|
||||
}
|
Reference in New Issue
Block a user