2021-12-22 14:26:57 +00:00
|
|
|
package client
|
2021-10-09 11:51:47 +00:00
|
|
|
|
|
|
|
import (
|
2021-11-14 09:06:24 +00:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2021-12-24 10:07:21 +00:00
|
|
|
|
2021-12-22 14:26:57 +00:00
|
|
|
"github.com/fhs/gompd/mpd"
|
|
|
|
|
2021-10-18 06:42:10 +00:00
|
|
|
"strings"
|
2021-10-09 11:51:47 +00:00
|
|
|
)
|
|
|
|
|
2021-11-16 12:33:36 +00:00
|
|
|
var (
|
2021-12-22 14:26:57 +00:00
|
|
|
CONN *mpd.Client
|
|
|
|
ArtistTree map[string]map[string]map[string]string
|
|
|
|
NotificationServer interface {
|
|
|
|
Send(string)
|
|
|
|
}
|
2021-11-16 12:33:36 +00:00
|
|
|
WHITE_AND_BOLD string = "[#ffffff::b]"
|
|
|
|
)
|
|
|
|
|
2021-12-22 14:26:57 +00:00
|
|
|
func SetConnection(c *mpd.Client) {
|
|
|
|
CONN = c
|
|
|
|
}
|
|
|
|
|
|
|
|
func SetNotificationServer(n interface{ Send(string) }) {
|
|
|
|
NotificationServer = n
|
|
|
|
}
|
|
|
|
|
|
|
|
func TogglePlayBack() error {
|
2021-11-13 06:02:00 +00:00
|
|
|
status, err := CONN.Status()
|
2021-10-17 16:12:02 +00:00
|
|
|
if status["state"] == "play" && err == nil {
|
2021-11-13 06:02:00 +00:00
|
|
|
CONN.Pause(true)
|
2021-10-17 16:12:02 +00:00
|
|
|
} else if status["state"] == "pause" && err == nil {
|
2021-11-13 06:02:00 +00:00
|
|
|
CONN.Play(-1)
|
2021-10-09 11:51:47 +00:00
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
2021-10-14 16:32:29 +00:00
|
|
|
|
2021-12-24 10:07:21 +00:00
|
|
|
// The GenerateContentSlice returns a slice of the content to be displayed on the Search View. The Slice is generated
|
|
|
|
// because the random nature of maps as they return values randomly hence the draw function keeps changing the order
|
|
|
|
// in which the results appear.
|
2021-11-16 09:47:50 +00:00
|
|
|
func GenerateContentSlice(selectedSuggestion string) ([]interface{}, error) {
|
|
|
|
var ContentSlice []interface{}
|
|
|
|
if strings.TrimRight(selectedSuggestion, " ") == "" {
|
2021-12-22 14:26:57 +00:00
|
|
|
NotificationServer.Send("Empty Search!")
|
2021-11-16 09:47:50 +00:00
|
|
|
return nil, errors.New("empty Search String Provided")
|
|
|
|
}
|
2021-12-22 14:26:57 +00:00
|
|
|
if _, ok := ArtistTree[selectedSuggestion]; ok {
|
2021-11-16 12:33:36 +00:00
|
|
|
ContentSlice = append(ContentSlice, WHITE_AND_BOLD+"Artists :")
|
2021-11-16 09:47:50 +00:00
|
|
|
ContentSlice = append(ContentSlice, selectedSuggestion)
|
2021-11-16 12:33:36 +00:00
|
|
|
ContentSlice = append(ContentSlice, WHITE_AND_BOLD+"Artist Albums :")
|
2021-12-22 14:26:57 +00:00
|
|
|
for albumName := range ArtistTree[selectedSuggestion] {
|
2021-11-16 09:47:50 +00:00
|
|
|
ContentSlice = append(ContentSlice, [2]string{albumName, selectedSuggestion})
|
|
|
|
}
|
2021-11-16 12:33:36 +00:00
|
|
|
ContentSlice = append(ContentSlice, WHITE_AND_BOLD+"Artist Tracks :")
|
2021-12-22 14:26:57 +00:00
|
|
|
for albumName, trackList := range ArtistTree[selectedSuggestion] {
|
2021-11-16 09:47:50 +00:00
|
|
|
for track := range trackList {
|
|
|
|
ContentSlice = append(ContentSlice, [3]string{track, selectedSuggestion, albumName})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-22 14:26:57 +00:00
|
|
|
if aMap := QueryArtistTreeForAlbums(ArtistTree, selectedSuggestion); len(aMap) != 0 {
|
2021-11-16 12:33:36 +00:00
|
|
|
ContentSlice = append(ContentSlice, WHITE_AND_BOLD+"Albums :")
|
2021-11-16 09:47:50 +00:00
|
|
|
for mSlice := range aMap {
|
|
|
|
ContentSlice = append(ContentSlice, mSlice)
|
|
|
|
}
|
2021-11-16 12:33:36 +00:00
|
|
|
ContentSlice = append(ContentSlice, WHITE_AND_BOLD+"Album Tracks :")
|
2021-11-16 09:47:50 +00:00
|
|
|
for a, pathSlice := range aMap {
|
|
|
|
for _, path := range pathSlice {
|
2021-11-17 09:36:18 +00:00
|
|
|
ContentSlice = append(ContentSlice, [3]string{path[0], a[1], a[0]})
|
2021-11-16 09:47:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-22 14:26:57 +00:00
|
|
|
if tMap := QueryArtistTreeForTracks(ArtistTree, selectedSuggestion); len(tMap) != 0 {
|
2021-11-16 12:33:36 +00:00
|
|
|
ContentSlice = append(ContentSlice, WHITE_AND_BOLD+"Tracks :")
|
2021-11-16 09:47:50 +00:00
|
|
|
for mSlice := range tMap {
|
|
|
|
ContentSlice = append(ContentSlice, mSlice)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ContentSlice, nil
|
|
|
|
}
|
|
|
|
|
2021-12-24 10:07:21 +00:00
|
|
|
// GenerateArtistTree Artist Tree is a map of Artist to their Album Map
|
|
|
|
// Album Tree is a map of the tracks in that particular album.
|
2021-11-14 09:06:24 +00:00
|
|
|
func GenerateArtistTree() (map[string]map[string]map[string]string, error) {
|
2021-12-22 14:26:57 +00:00
|
|
|
ArtistTree = make(map[string]map[string]map[string]string)
|
2021-11-14 09:06:24 +00:00
|
|
|
AllInfo, err := CONN.ListAllInfo("/")
|
|
|
|
if err == nil {
|
|
|
|
for _, i := range AllInfo {
|
|
|
|
if _, ArtistExists := ArtistTree[i["Artist"]]; !ArtistExists {
|
|
|
|
ArtistTree[i["Artist"]] = make(map[string]map[string]string)
|
|
|
|
}
|
|
|
|
if _, AlbumExists := ArtistTree[i["Artist"]][i["Album"]]; !AlbumExists {
|
|
|
|
ArtistTree[i["Artist"]][i["Album"]] = make(map[string]string)
|
|
|
|
}
|
|
|
|
if _, TitleExists := ArtistTree[i["Artist"]][i["Album"]][i["Title"]]; !TitleExists {
|
|
|
|
ArtistTree[i["Artist"]][i["Album"]][i["Title"]] = i["file"]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ArtistTree, nil
|
|
|
|
} else {
|
|
|
|
return nil, errors.New("Could Not Generate Artist Tree")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func PrintArtistTree(a map[string]map[string]map[string]string) {
|
|
|
|
for k, v := range a {
|
|
|
|
fmt.Println(k, " : ")
|
|
|
|
for k1, v1 := range v {
|
|
|
|
fmt.Println("\t|---", k1, " : ")
|
|
|
|
for k2 := range v1 {
|
|
|
|
fmt.Println("\t\t|---", k2)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-11-15 18:46:15 +00:00
|
|
|
|
2021-12-24 10:07:21 +00:00
|
|
|
// Adds All tracks from a specified album to a playlist
|
2021-11-16 12:09:44 +00:00
|
|
|
func AddAlbum(a map[string]map[string]map[string]string, alb string, artist string) {
|
|
|
|
for _, v := range a[artist][alb] {
|
|
|
|
err := CONN.Add(v)
|
|
|
|
if err != nil {
|
2021-12-22 14:26:57 +00:00
|
|
|
NotificationServer.Send("Could Not Add Song : " + v)
|
2021-11-15 18:46:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-22 14:26:57 +00:00
|
|
|
NotificationServer.Send("Album Added : " + alb)
|
2021-11-15 18:46:15 +00:00
|
|
|
}
|
|
|
|
|
2021-12-24 10:07:21 +00:00
|
|
|
// Adds All tracks from a specified artist to a playlist
|
2021-11-15 18:46:15 +00:00
|
|
|
func AddArtist(a map[string]map[string]map[string]string, artist string) {
|
|
|
|
if val, ok := a[artist]; ok {
|
|
|
|
for _, v := range val {
|
|
|
|
for _, path := range v {
|
2021-11-16 09:47:50 +00:00
|
|
|
err := CONN.Add(path)
|
|
|
|
if err != nil {
|
2021-12-22 14:26:57 +00:00
|
|
|
NotificationServer.Send("Could Not Add Song : " + path)
|
2021-11-16 09:47:50 +00:00
|
|
|
}
|
2021-11-15 18:46:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-22 14:26:57 +00:00
|
|
|
NotificationServer.Send("Artist Added : " + artist)
|
2021-11-15 18:46:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-24 10:07:21 +00:00
|
|
|
// Adds Specified Track to the Playlist
|
2021-11-16 14:59:46 +00:00
|
|
|
func AddTitle(a map[string]map[string]map[string]string, artist, alb, track string, addAndPlay bool) {
|
|
|
|
if addAndPlay {
|
|
|
|
id, err := CONN.AddId(a[artist][alb][track], -1)
|
|
|
|
CONN.PlayId(id)
|
|
|
|
if err != nil {
|
2021-12-22 14:26:57 +00:00
|
|
|
NotificationServer.Send("Could Not Add Track : " + track)
|
2021-11-16 14:59:46 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
err := CONN.Add(a[artist][alb][track])
|
|
|
|
if err != nil {
|
2021-12-22 14:26:57 +00:00
|
|
|
NotificationServer.Send("Could Not Add Track : " + track)
|
2021-11-16 14:59:46 +00:00
|
|
|
}
|
2021-11-16 09:47:50 +00:00
|
|
|
}
|
2021-12-22 14:26:57 +00:00
|
|
|
NotificationServer.Send("Track Added : " + track)
|
2021-11-16 09:47:50 +00:00
|
|
|
}
|
|
|
|
|
2021-12-22 14:26:57 +00:00
|
|
|
/* Querys the Artist Tree for a track and returns a TrackMap (i.e [3]string{artist, album, track} -> Path) which will help us
|
2021-11-16 09:47:50 +00:00
|
|
|
to add tracks to the playlist */
|
|
|
|
func QueryArtistTreeForTracks(a map[string]map[string]map[string]string, track string) map[[3]string]string {
|
2021-11-15 18:46:15 +00:00
|
|
|
TrackMap := make(map[[3]string]string)
|
|
|
|
for artistName, albumMap := range a {
|
2021-11-16 14:30:04 +00:00
|
|
|
for albumName, trackList := range albumMap {
|
2021-11-15 18:46:15 +00:00
|
|
|
for trackName, path := range trackList {
|
|
|
|
if trackName == track {
|
2021-11-16 14:30:04 +00:00
|
|
|
TrackMap[[3]string{trackName, artistName, albumName}] = path
|
2021-11-15 18:46:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TrackMap
|
|
|
|
}
|
2021-11-16 09:47:50 +00:00
|
|
|
|
2021-12-22 14:26:57 +00:00
|
|
|
/* Querys the Artist Tree for an album and returns a AlbumMap (i.e [3]string{artist, album } ->[]Path of songs in the album)
|
2021-11-16 09:47:50 +00:00
|
|
|
which will help us to add all album tracks to the playlist */
|
|
|
|
func QueryArtistTreeForAlbums(a map[string]map[string]map[string]string, album string) map[[2]string][][2]string {
|
|
|
|
AlbumMap := make(map[[2]string][][2]string)
|
|
|
|
for artistName, albumMap := range a {
|
|
|
|
for albumName, trackList := range albumMap {
|
|
|
|
if albumName == album {
|
|
|
|
var pathSlice [][2]string
|
|
|
|
for trackName, path := range trackList {
|
|
|
|
pathSlice = append(pathSlice, [2]string{trackName, path})
|
|
|
|
}
|
2021-11-17 09:36:18 +00:00
|
|
|
AlbumMap[[2]string{albumName, artistName}] = pathSlice
|
2021-11-16 09:47:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AlbumMap
|
|
|
|
}
|
2021-11-16 12:09:44 +00:00
|
|
|
|
2021-11-16 14:59:46 +00:00
|
|
|
func AddToPlaylist(a interface{}, addAndPlay bool) {
|
2021-11-16 12:09:44 +00:00
|
|
|
switch a.(type) {
|
|
|
|
case [3]string:
|
|
|
|
{
|
|
|
|
b := a.([3]string)
|
2021-12-22 14:26:57 +00:00
|
|
|
AddTitle(ArtistTree, b[1], b[2], b[0], addAndPlay)
|
2021-11-16 12:09:44 +00:00
|
|
|
}
|
|
|
|
case [2]string:
|
|
|
|
{
|
|
|
|
b := a.([2]string)
|
2021-12-22 14:26:57 +00:00
|
|
|
AddAlbum(ArtistTree, b[0], b[1])
|
2021-11-16 12:09:44 +00:00
|
|
|
}
|
|
|
|
case string:
|
|
|
|
{
|
|
|
|
b := a.(string)
|
2021-12-22 14:26:57 +00:00
|
|
|
AddArtist(ArtistTree, b)
|
2021-11-16 12:09:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|