sanic/mpd.go

455 lines
10 KiB
Go
Raw Normal View History

2023-12-10 21:33:54 +01:00
package main
import (
2024-04-06 18:57:43 +02:00
"fmt"
2023-12-10 21:33:54 +01:00
"github.com/fhs/gompd/v2/mpd"
"github.com/labstack/echo/v4"
"net/http"
"strconv"
"time"
)
// MPD API calls
2024-07-15 10:49:26 +02:00
// updateDb Updates the music database: find new files, remove deleted files, update modified files.
2023-12-29 16:55:06 +01:00
func updateDb(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-29 16:55:06 +01:00
}
defer conn.Close()
jobId, err := conn.Update("")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-29 16:55:06 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, fmt.Sprintf("Database update started with job id %d", jobId))
2023-12-29 16:55:06 +01:00
}
2024-07-15 10:49:26 +02:00
// previousTrack Plays previous song in the queue.
2023-12-10 21:33:54 +01:00
func previousTrack(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
err = conn.Previous()
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, "Playing previous track in queue")
2023-12-10 21:33:54 +01:00
}
2024-07-15 10:49:26 +02:00
// nextTrack Plays next song in the queue.
2023-12-10 21:33:54 +01:00
func nextTrack(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
err = conn.Next()
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, "PLaying next track in queue")
2023-12-10 21:33:54 +01:00
}
2024-07-15 10:49:26 +02:00
// stopPlayback Stops playing.
2023-12-10 21:33:54 +01:00
func stopPlayback(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
err = conn.Stop()
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, "Playback stopped")
2023-12-10 21:33:54 +01:00
}
2024-07-15 10:49:26 +02:00
// resumePlayback Begins playing the playlist or if paused resumes playback.
2023-12-10 21:33:54 +01:00
func resumePlayback(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
2023-12-30 15:02:13 +01:00
status, err := conn.Status()
2023-12-10 21:33:54 +01:00
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
}
if status["state"] == "stop" {
err := conn.Play(-1)
if err != nil {
c.Logger().Error(err)
}
} else {
err = conn.Pause(false)
if err != nil {
c.Logger().Error(err)
}
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, "Playback resumed")
2023-12-10 21:33:54 +01:00
}
2024-07-15 10:49:26 +02:00
// pausePlayback Pauses playback.
2023-12-10 21:33:54 +01:00
func pausePlayback(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
err = conn.Pause(true)
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, "Playback paused")
2023-12-10 21:33:54 +01:00
}
2024-07-15 10:49:26 +02:00
// seek Seeks to the position defined by seconds within the current song.
2023-12-10 21:33:54 +01:00
func seek(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
seconds, err := strconv.Atoi(c.Param("seconds"))
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
if seconds < 0 {
return c.String(http.StatusBadRequest, "seconds must be positive integer")
}
2024-04-06 18:57:43 +02:00
// TODO: Duration type seems to be used incorrectly
2023-12-10 21:33:54 +01:00
err = conn.SeekCur(time.Duration(seconds)*time.Second, false)
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, fmt.Sprintf("Seeked current track to %d seconds", seconds))
2023-12-10 21:33:54 +01:00
}
2024-07-15 10:49:26 +02:00
// toggleRepeat Toggles repeat state between 1 or 0.
2023-12-10 21:33:54 +01:00
func toggleRepeat(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
status, err := conn.Status()
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
var msg string
2023-12-10 21:33:54 +01:00
if status["repeat"] == "1" {
err = conn.Repeat(false)
2024-04-06 18:57:43 +02:00
msg = "Toggled Repeat mode to off"
2023-12-10 21:33:54 +01:00
} else {
err = conn.Repeat(true)
2024-04-06 18:57:43 +02:00
msg = "Toggled Repeat mode to on"
2023-12-10 21:33:54 +01:00
}
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, msg)
2023-12-10 21:33:54 +01:00
}
2024-07-15 10:49:26 +02:00
// toggleRandom Toggles random state between 1 or 0.
2023-12-10 21:33:54 +01:00
func toggleRandom(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
status, err := conn.Status()
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
var msg string
2023-12-30 15:02:13 +01:00
if status["random"] == "1" {
2023-12-10 21:33:54 +01:00
err = conn.Random(false)
2024-04-06 18:57:43 +02:00
msg = "Toggled Random mode to off"
2023-12-10 21:33:54 +01:00
} else {
err = conn.Random(true)
2024-04-06 18:57:43 +02:00
msg = "Toggled Random mode to on"
2023-12-10 21:33:54 +01:00
}
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, msg)
2023-12-10 21:33:54 +01:00
}
2024-07-15 10:49:26 +02:00
// setVolume Sets volume to level, the range of volume is 0-100.
2023-12-10 21:33:54 +01:00
func setVolume(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
defer conn.Close()
level, err := strconv.Atoi(c.Param("level"))
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
if level > 100 || level < 0 {
return c.String(http.StatusBadRequest, "Volume must be between 0 and 100")
}
err = conn.SetVolume(level)
if err != nil {
2023-12-30 15:02:13 +01:00
c.Logger().Error(err)
2023-12-10 21:33:54 +01:00
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, fmt.Sprintf("Set volume to %d", level))
2023-12-10 21:33:54 +01:00
}
2024-04-06 15:28:00 +02:00
// Queue
2024-07-15 10:49:26 +02:00
// deleteTrackFromQueue removed track with song_id from queue
2024-04-06 15:28:00 +02:00
func deleteTrackFromQueue(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
c.Logger().Error(err)
}
defer conn.Close()
songId, err := strconv.Atoi(c.Param("song_id"))
if err != nil {
c.Logger().Error(err)
}
err = conn.DeleteID(songId)
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
2024-04-06 18:57:43 +02:00
return c.String(http.StatusOK, fmt.Sprintf("Removed song %d from queue", songId))
}
2024-07-15 10:49:26 +02:00
// moveTrackInQueue moves song with song_id to the new place position in the queue.
2024-04-06 18:57:43 +02:00
func moveTrackInQueue(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
c.Logger().Error(err)
}
defer conn.Close()
songId, err := strconv.Atoi(c.Param("song_id"))
if err != nil {
c.Logger().Error(err)
}
position, err := strconv.Atoi(c.Param("position"))
if err != nil {
c.Logger().Error(err)
}
err = conn.MoveID(songId, position)
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
return c.String(http.StatusOK, fmt.Sprintf("Moved song %d to position %d", songId, position))
2024-04-06 15:28:00 +02:00
}
2024-04-16 23:37:48 +02:00
2024-07-15 10:49:26 +02:00
// attachPlaylist adds the playlist with the name playlist_name to the queue.
2024-04-18 14:28:02 +02:00
func attachPlaylist(c echo.Context) error {
2024-04-16 23:37:48 +02:00
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
c.Logger().Error(err)
}
defer conn.Close()
2024-04-18 14:28:02 +02:00
name := c.Param("playlist_name")
err = conn.PlaylistLoad(name, -1, -1)
2024-04-16 23:37:48 +02:00
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
2024-04-18 14:28:02 +02:00
return c.JSON(http.StatusOK, "")
2024-04-16 23:37:48 +02:00
}
2024-04-17 00:24:18 +02:00
2024-07-15 10:49:26 +02:00
// replaceQueue replaces the current queue with the playlist with the name playlist_name.
2024-04-18 14:28:02 +02:00
func replaceQueue(c echo.Context) error {
2024-04-17 00:24:18 +02:00
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
c.Logger().Error(err)
}
defer conn.Close()
2024-04-18 14:28:02 +02:00
name := c.Param("playlist_name")
2024-04-17 00:24:18 +02:00
2024-04-18 14:28:02 +02:00
err = conn.Clear()
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusInternalServerError, err.Error())
}
err = conn.PlaylistLoad(name, -1, -1)
2024-04-17 00:24:18 +02:00
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
2024-04-18 14:28:02 +02:00
return c.JSON(http.StatusOK, "")
2024-04-17 00:24:18 +02:00
}
2024-04-18 11:46:09 +02:00
2024-04-18 14:28:02 +02:00
// Playlists
2024-07-15 10:49:26 +02:00
// listPlaylists return a list of all stored playlists.
2024-04-18 14:28:02 +02:00
func listPlaylists(c echo.Context) error {
2024-04-18 11:46:09 +02:00
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
c.Logger().Error(err)
}
defer conn.Close()
2024-04-18 14:28:02 +02:00
playlists, err := conn.ListPlaylists()
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
2024-04-18 11:46:09 +02:00
2024-04-18 14:28:02 +02:00
return c.JSON(http.StatusOK, playlists)
}
2024-07-15 10:49:26 +02:00
// listPlaylist returns the contents of the playlist defined by name.
2024-04-18 14:28:02 +02:00
func listPlaylist(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
2024-04-18 11:46:09 +02:00
if err != nil {
c.Logger().Error(err)
}
2024-04-18 14:28:02 +02:00
defer conn.Close()
name := c.Param("name")
playlist, err := conn.PlaylistContents(name)
2024-04-18 11:46:09 +02:00
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
2024-04-18 14:28:02 +02:00
return c.JSON(http.StatusOK, playlist)
2024-04-18 11:46:09 +02:00
}
2024-04-18 12:12:52 +02:00
2024-07-15 10:49:26 +02:00
// deletePlaylist deletes the playlist defined by name.
2024-04-18 14:28:02 +02:00
func deletePlaylist(c echo.Context) error {
2024-04-18 12:12:52 +02:00
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
c.Logger().Error(err)
}
defer conn.Close()
2024-04-18 14:28:02 +02:00
name := c.Param("name")
2024-04-18 12:12:52 +02:00
2024-04-18 14:28:02 +02:00
err = conn.PlaylistRemove(name)
2024-04-18 12:12:52 +02:00
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
2024-04-29 00:14:39 +02:00
return c.String(http.StatusNoContent, "")
2024-04-18 12:12:52 +02:00
}
2024-04-18 15:06:12 +02:00
2024-07-15 10:49:26 +02:00
// savePlaylist saves the current queue to a playlist with the given name.
2024-04-18 15:06:12 +02:00
func savePlaylist(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
c.Logger().Error(err)
}
defer conn.Close()
name := c.Param("name")
err = conn.PlaylistSave(name)
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
2024-04-29 00:14:39 +02:00
return c.String(http.StatusCreated, "")
}
2024-07-15 10:49:26 +02:00
// searchDatabase search the database path given by pattern and returns all entries that contain the pattern either in their artist, album or title.
2024-04-29 00:14:39 +02:00
func searchDatabase(c echo.Context) error {
// Connect to MPD server
conn, err := mpd.Dial("tcp", "localhost:6600")
if err != nil {
c.Logger().Error(err)
}
defer conn.Close()
pattern := c.Param("pattern")
artistResult, err := conn.Search("artist", pattern)
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
albumResult, err := conn.Search("album", pattern)
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
titleResult, err := conn.Search("title", pattern)
if err != nil {
c.Logger().Error(err)
return c.String(http.StatusBadRequest, err.Error())
}
songs := append(append(artistResult, albumResult...), titleResult...)
// make list unique
uniqueList := make([]mpd.Attrs, 0, len(songs))
keep := make(map[string]bool)
for _, song := range songs {
if _, ok := keep[song["file"]]; !ok {
keep[song["file"]] = true
uniqueList = append(uniqueList, song)
}
}
return c.JSON(http.StatusOK, uniqueList)
2024-04-18 15:06:12 +02:00
}