added some api calls

This commit is contained in:
XenGi 2023-12-02 17:53:44 +01:00
parent 461f966800
commit 32291bccb8
Signed by: xengi
SSH key fingerprint: SHA256:FGp51kRvGOcWnTHiOI39ImwVO4A3fpvR30nPX3LpV7g
4 changed files with 247 additions and 24 deletions

3
Makefile Normal file
View file

@ -0,0 +1,3 @@
mpd:
mkdir -p /tmp/sanic/{music,playlists}
mpd --no-daemon ./mpd.conf

20
NOTES.md Normal file
View file

@ -0,0 +1,20 @@
# mpd commands
- [x] previous track
- [x] next track
- [x] stop
- [x] play/pause
- [x] set track progress
- [x] set volume
- [x] repeat queue
- [x] shuffle queue
- [ ] set fade
- [ ] add track to queue
- [ ] rm track from queue
- [ ] move track in queue
- [ ] clear queue
- [ ] list tracks in music db
- [ ] list playlists
- [ ] save playlist
- [ ] delete playlist

View file

@ -28,11 +28,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1694616124, "lastModified": 1699950847,
"narHash": "sha256-c49BVhQKw3XDRgt+y+uPAbArtgUlMXCET6VxEBmzHXE=", "narHash": "sha256-xN/yVtqHb7kimHA/WvQFrEG5WS38t0K+A/W+j/WhQWM=",
"owner": "tweag", "owner": "tweag",
"repo": "gomod2nix", "repo": "gomod2nix",
"rev": "f95720e89af6165c8c0aa77f180461fe786f3c21", "rev": "05c993c9a5bd55a629cd45ed49951557b7e9c61a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -43,11 +43,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1697915759, "lastModified": 1701237617,
"narHash": "sha256-WyMj5jGcecD+KC8gEs+wFth1J1wjisZf8kVZH13f1Zo=", "narHash": "sha256-Ryd8xpNDY9MJnBFDYhB37XSFIxCPVVVXAbInNPa95vs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "51d906d2341c9e866e48c2efcaac0f2d70bfd43e", "rev": "85306ef2470ba705c97ce72741d56e42d0264015",
"type": "github" "type": "github"
}, },
"original": { "original": {

214
server.go
View file

@ -1,13 +1,17 @@
package main package main
import ( import (
"fmt"
"github.com/fhs/gompd/v2/mpd"
"github.com/labstack/echo-contrib/echoprometheus" "github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware" "github.com/labstack/echo/v4/middleware"
"golang.org/x/net/websocket" "golang.org/x/net/websocket"
"log"
"net/http" "net/http"
"strconv"
"strings" "strings"
"time"
"github.com/labstack/echo/v4"
) )
func main() { func main() {
@ -25,6 +29,7 @@ func main() {
e.GET("/metrics", echoprometheus.NewHandler()) e.GET("/metrics", echoprometheus.NewHandler())
e.GET("/", func(c echo.Context) (err error) { e.GET("/", func(c echo.Context) (err error) {
// HTTP/2 Server Push
pusher, ok := c.Response().Writer.(http.Pusher) pusher, ok := c.Response().Writer.(http.Pusher)
if ok { if ok {
if err = pusher.Push("/style.css", nil); err != nil { if err = pusher.Push("/style.css", nil); err != nil {
@ -40,6 +45,17 @@ func main() {
return c.File("index.html") return c.File("index.html")
}) })
g := e.Group("/api")
g.GET("/previous_track", previousTrack)
g.GET("/next_track", nextTrack)
g.GET("/stop", stopPlayback)
g.GET("/play", resumePlayback)
g.GET("/pause", pausePlayback)
g.GET("/seek/:seconds", seek)
g.GET("/repeat", toggleRepeat)
g.GET("/random", toggleRandom)
g.GET("/volume/:level", setVolume)
e.GET("/ws", wsServe) e.GET("/ws", wsServe)
e.Logger.Fatal(e.StartTLS(":1323", "cert.pem", "key.pem")) e.Logger.Fatal(e.StartTLS(":1323", "cert.pem", "key.pem"))
@ -47,33 +63,217 @@ func main() {
} }
func wsServe(c echo.Context) error { func wsServe(c echo.Context) error {
fmt.Println("wsServe")
websocket.Handler(func(ws *websocket.Conn) { websocket.Handler(func(ws *websocket.Conn) {
defer ws.Close() defer ws.Close()
fmt.Println("handler")
for { for {
// Read // Read
msg := "" msg := ""
err := websocket.Message.Receive(ws, &msg) err := websocket.Message.Receive(ws, &msg)
if err != nil { if err != nil {
c.Logger().Error(err) c.Logger().Error(err)
} break
// Forward MPD communication } else {
if strings.HasPrefix(strings.ToUpper(msg), "MPD#") { if strings.HasPrefix(strings.ToUpper(msg), "MPD#") {
// Forward MPD communication
// TODO: forward request to mpd and response back to client // TODO: forward request to mpd and response back to client
err := websocket.Message.Send(ws, "MPD command received, processing... processing...") err := websocket.Message.Send(ws, "MPD command received, processing... processing...")
if err != nil { if err != nil {
c.Logger().Error(err) c.Logger().Error(err)
} }
}
} else if strings.HasPrefix(strings.ToUpper(msg), "YT#") {
// Download video link as audio file // Download video link as audio file
if strings.HasPrefix(strings.ToUpper(msg), "YT#") {
// TODO: implement yt-dlp integration // TODO: implement yt-dlp integration
err := websocket.Message.Send(ws, "YT-DLP command received, processing... processing...") err := websocket.Message.Send(ws, "YT-DLP command received, processing... processing...")
if err != nil { if err != nil {
c.Logger().Error(err) c.Logger().Error(err)
} }
} }
//fmt.Printf("%s\n", msg) }
//fmt.Println(msg)
} }
}).ServeHTTP(c.Response(), c.Request()) }).ServeHTTP(c.Response(), c.Request())
return nil return nil
} }
// API calls
func previousTrack(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
err = conn.Previous()
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}
func nextTrack(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
err = conn.Next()
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}
func stopPlayback(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
err = conn.Stop()
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}
func resumePlayback(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
err = conn.Pause(false)
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}
func pausePlayback(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
err = conn.Pause(true)
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}
func seek(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
seconds, err := strconv.Atoi(c.Param("seconds"))
if err != nil {
log.Fatalln(err)
}
if seconds < 0 {
return c.String(http.StatusBadRequest, "seconds must be positive integer")
}
err = conn.SeekCur(time.Duration(seconds)*time.Second, false)
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}
func toggleRepeat(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
status, err := conn.Status()
if err != nil {
log.Fatalln(err)
}
if status["repeat"] == "1" {
err = conn.Repeat(false)
} else {
err = conn.Repeat(true)
}
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}
func toggleRandom(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
status, err := conn.Status()
if err != nil {
log.Fatalln(err)
}
if status["toggleRandom"] == "1" {
err = conn.Random(false)
} else {
err = conn.Random(true)
}
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}
func setVolume(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
level, err := strconv.Atoi(c.Param("level"))
if err != nil {
log.Fatalln(err)
}
if level > 100 || level < 0 {
return c.String(http.StatusBadRequest, "Volume must be between 0 and 100")
}
err = conn.SetVolume(level)
if err != nil {
log.Fatalln(err)
}
return c.String(http.StatusNoContent, "")
}