Compare commits

..

22 commits

Author SHA1 Message Date
coon 67c70d4db1 static: add custom style to range input control 2023-12-01 21:53:51 +01:00
coon 4e5e53d257 static: add shiny borders to bottom controls 2023-11-30 22:34:17 +01:00
coon 5a8f3aee35 static: adjust sanic logo 2023-11-30 22:33:32 +01:00
coon 65ae36dfae static: add gradient background for top controls 2023-11-30 22:33:17 +01:00
coon 9140707585 static: add table header gradient 2023-11-30 22:32:11 +01:00
coon 2f029dd7f6 static: comment out dashed debug boarder for div containers 2023-11-30 22:30:36 +01:00
coon 24df91e473 static: use different font 2023-11-30 00:13:20 +01:00
coon 34978ddb8d static: add playback arrow image + red highlight background color 2023-11-29 23:54:40 +01:00
coon da960cd34b static: some formatting on table entries 2023-11-29 23:52:03 +01:00
coon 41ff1e3592 static: add playback arrow to position row 2023-11-29 23:02:58 +01:00
coon 35512fc088 static: use "old school" way for alternate coloring of tables 2023-11-29 23:01:03 +01:00
coon e23bb0136a static: use different color for footer 2023-11-29 16:01:08 +01:00
coon 697d651feb static: use alternating colors on table 2023-11-29 16:00:37 +01:00
coon 54130889e9 static: make tables occupy whole width 2023-11-29 15:59:07 +01:00
coon e8d8e1ef24 static: fix broken css statement 2023-11-29 15:57:52 +01:00
coon 67c31634f4 static: add basic file tree view 2023-11-29 13:30:24 +01:00
coon 343e31afa3 w3c compliance stuff 2023-11-29 13:27:40 +01:00
coon a226054e21 static: add dummy track lists for queue and playlist tracklist 2023-11-28 10:49:13 +01:00
coon fe02f27585 static: index.html: add playlist_controls + playlist_tracklist div containers 2023-11-28 10:48:00 +01:00
coon 4ea297c4a1 static: work on basic layout + top controls 2023-11-27 20:51:38 +01:00
coon c17309cc43 static: add sanic logo image 2023-11-27 20:50:11 +01:00
coon 0be041b476 static: start of flexbox implementation 2023-11-27 02:07:30 +01:00
5 changed files with 26 additions and 250 deletions

View file

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

View file

@ -1,20 +0,0 @@
# 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": 1699950847, "lastModified": 1694616124,
"narHash": "sha256-xN/yVtqHb7kimHA/WvQFrEG5WS38t0K+A/W+j/WhQWM=", "narHash": "sha256-c49BVhQKw3XDRgt+y+uPAbArtgUlMXCET6VxEBmzHXE=",
"owner": "tweag", "owner": "tweag",
"repo": "gomod2nix", "repo": "gomod2nix",
"rev": "05c993c9a5bd55a629cd45ed49951557b7e9c61a", "rev": "f95720e89af6165c8c0aa77f180461fe786f3c21",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -43,11 +43,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1701237617, "lastModified": 1697915759,
"narHash": "sha256-Ryd8xpNDY9MJnBFDYhB37XSFIxCPVVVXAbInNPa95vs=", "narHash": "sha256-WyMj5jGcecD+KC8gEs+wFth1J1wjisZf8kVZH13f1Zo=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "85306ef2470ba705c97ce72741d56e42d0264015", "rev": "51d906d2341c9e866e48c2efcaac0f2d70bfd43e",
"type": "github" "type": "github"
}, },
"original": { "original": {

214
server.go
View file

@ -1,17 +1,13 @@
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() {
@ -29,7 +25,6 @@ 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 {
@ -45,17 +40,6 @@ 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"))
@ -63,217 +47,33 @@ 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 }
} else {
if strings.HasPrefix(strings.ToUpper(msg), "MPD#") {
// Forward MPD communication // Forward MPD communication
if strings.HasPrefix(strings.ToUpper(msg), "MPD#") {
// 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, "")
}

View file

@ -53,8 +53,8 @@ td {
} }
/* This is probably a better way to generate alternate coloring on tables. However, /* This is probably a better way to generate alternate coloring on tables. However,
background color for selected track is overwritten this way. Therefore the "old background color for selected track is overwritten this way. Therefore the old
school" way of alternate coloring is used for now. schoon way of alternate coloring is used for now.
table tr:nth-child(odd) td { table tr:nth-child(odd) td {
background:#1e1f1a; background:#1e1f1a;
@ -185,7 +185,6 @@ td.playing {
#playlist_controls { #playlist_controls {
background-color: #171812;; background-color: #171812;;
/* flex-grow: 1; */ /* flex-grow: 1; */
width: 20%; /* frickel? */ width: 20%; /* frickel? */
border-right: 4px ridge #3a506b; border-right: 4px ridge #3a506b;
} }