diff --git a/db/db.go b/db/db.go index bca5d61..50da986 100644 --- a/db/db.go +++ b/db/db.go @@ -264,14 +264,6 @@ func (t *Track) RelPath() string { ) } -func (t *Track) GenreStrings() []string { - strs := make([]string, 0, len(t.Genres)) - for _, genre := range t.Genres { - strs = append(strs, genre.Name) - } - return strs -} - type User struct { ID int `gorm:"primary_key"` CreatedAt time.Time diff --git a/server/ctrlsubsonic/spec/construct_by_folder.go b/server/ctrlsubsonic/spec/construct_by_folder.go index ec3bbb5..f1c7c20 100644 --- a/server/ctrlsubsonic/spec/construct_by_folder.go +++ b/server/ctrlsubsonic/spec/construct_by_folder.go @@ -2,7 +2,6 @@ package spec import ( "path/filepath" - "strings" "go.senan.xyz/gonic/db" ) @@ -69,7 +68,6 @@ func NewTCTrackByFolder(t *db.Track, parent *db.Album) *TrackChild { ), ParentID: parent.SID(), Duration: t.Length, - Genre: strings.Join(t.GenreStrings(), ", "), Year: parent.TagYear, Bitrate: t.Bitrate, IsDir: false, @@ -92,6 +90,12 @@ func NewTCTrackByFolder(t *db.Track, parent *db.Album) *TrackChild { if t.TrackRating != nil { trCh.UserRating = t.TrackRating.Rating } + if len(t.Genres) > 0 { + trCh.Genre = t.Genres[0].Name + } + for _, g := range t.Genres { + trCh.Genres = append(trCh.Genres, &GenreRef{Name: g.Name}) + } return trCh } diff --git a/server/ctrlsubsonic/spec/construct_by_tags.go b/server/ctrlsubsonic/spec/construct_by_tags.go index 974211e..01b9c6c 100644 --- a/server/ctrlsubsonic/spec/construct_by_tags.go +++ b/server/ctrlsubsonic/spec/construct_by_tags.go @@ -3,7 +3,6 @@ package spec import ( "path/filepath" "sort" - "strings" "go.senan.xyz/gonic/db" ) @@ -68,7 +67,6 @@ func NewTrackByTags(t *db.Track, album *db.Album) *TrackChild { ), Album: album.TagTitle, AlbumID: album.SID(), - Genre: strings.Join(t.GenreStrings(), ", "), Duration: t.Length, Bitrate: t.Bitrate, Type: "music", @@ -90,6 +88,12 @@ func NewTrackByTags(t *db.Track, album *db.Album) *TrackChild { }) ret.ArtistID = album.Artists[0].SID() } + if len(t.Genres) > 0 { + ret.Genre = t.Genres[0].Name + } + for _, g := range t.Genres { + ret.Genres = append(ret.Genres, &GenreRef{Name: g.Name}) + } return ret } diff --git a/server/ctrlsubsonic/spec/spec.go b/server/ctrlsubsonic/spec/spec.go index a2c6f06..3396490 100644 --- a/server/ctrlsubsonic/spec/spec.go +++ b/server/ctrlsubsonic/spec/spec.go @@ -45,27 +45,27 @@ type Response struct { MusicFolders *MusicFolders `xml:"musicFolders" json:"musicFolders,omitempty"` ScanStatus *ScanStatus `xml:"scanStatus" json:"scanStatus,omitempty"` Licence *Licence `xml:"license" json:"license,omitempty"` - SearchResultTwo *SearchResultTwo `xml:"searchResult2" json:"searchResult2,omitempty"` - SearchResultThree *SearchResultThree `xml:"searchResult3" json:"searchResult3,omitempty"` - User *User `xml:"user" json:"user,omitempty"` - Playlists *Playlists `xml:"playlists" json:"playlists,omitempty"` - Playlist *Playlist `xml:"playlist" json:"playlist,omitempty"` - ArtistInfo *ArtistInfo `xml:"artistInfo" json:"artistInfo,omitempty"` - ArtistInfoTwo *ArtistInfo `xml:"artistInfo2" json:"artistInfo2,omitempty"` - Genres *Genres `xml:"genres" json:"genres,omitempty"` - PlayQueue *PlayQueue `xml:"playQueue" json:"playQueue,omitempty"` - JukeboxStatus *JukeboxStatus `xml:"jukeboxStatus" json:"jukeboxStatus,omitempty"` - JukeboxPlaylist *JukeboxPlaylist `xml:"jukeboxPlaylist" json:"jukeboxPlaylist,omitempty"` - Podcasts *Podcasts `xml:"podcasts" json:"podcasts,omitempty"` - NewestPodcasts *NewestPodcasts `xml:"newestPodcasts" json:"newestPodcasts,omitempty"` - Bookmarks *Bookmarks `xml:"bookmarks" json:"bookmarks,omitempty"` - Starred *Starred `xml:"starred" json:"starred,omitempty"` - StarredTwo *StarredTwo `xml:"starred2" json:"starred2,omitempty"` - TopSongs *TopSongs `xml:"topSongs" json:"topSongs,omitempty"` - SimilarSongs *SimilarSongs `xml:"similarSongs" json:"similarSongs,omitempty"` - SimilarSongsTwo *SimilarSongsTwo `xml:"similarSongs2" json:"similarSongs2,omitempty"` - InternetRadioStations *InternetRadioStations `xml:"internetRadioStations" json:"internetRadioStations,omitempty"` - Lyrics *Lyrics `xml:"lyrics" json:"lyrics,omitempty"` + SearchResultTwo *SearchResultTwo `xml:"searchResult2" json:"searchResult2,omitempty"` + SearchResultThree *SearchResultThree `xml:"searchResult3" json:"searchResult3,omitempty"` + User *User `xml:"user" json:"user,omitempty"` + Playlists *Playlists `xml:"playlists" json:"playlists,omitempty"` + Playlist *Playlist `xml:"playlist" json:"playlist,omitempty"` + ArtistInfo *ArtistInfo `xml:"artistInfo" json:"artistInfo,omitempty"` + ArtistInfoTwo *ArtistInfo `xml:"artistInfo2" json:"artistInfo2,omitempty"` + Genres *Genres `xml:"genres" json:"genres,omitempty"` + PlayQueue *PlayQueue `xml:"playQueue" json:"playQueue,omitempty"` + JukeboxStatus *JukeboxStatus `xml:"jukeboxStatus" json:"jukeboxStatus,omitempty"` + JukeboxPlaylist *JukeboxPlaylist `xml:"jukeboxPlaylist" json:"jukeboxPlaylist,omitempty"` + Podcasts *Podcasts `xml:"podcasts" json:"podcasts,omitempty"` + NewestPodcasts *NewestPodcasts `xml:"newestPodcasts" json:"newestPodcasts,omitempty"` + Bookmarks *Bookmarks `xml:"bookmarks" json:"bookmarks,omitempty"` + Starred *Starred `xml:"starred" json:"starred,omitempty"` + StarredTwo *StarredTwo `xml:"starred2" json:"starred2,omitempty"` + TopSongs *TopSongs `xml:"topSongs" json:"topSongs,omitempty"` + SimilarSongs *SimilarSongs `xml:"similarSongs" json:"similarSongs,omitempty"` + SimilarSongsTwo *SimilarSongsTwo `xml:"similarSongs2" json:"similarSongs2,omitempty"` + InternetRadioStations *InternetRadioStations `xml:"internetRadioStations" json:"internetRadioStations,omitempty"` + Lyrics *Lyrics `xml:"lyrics" json:"lyrics,omitempty"` } func NewResponse() *Response { @@ -160,28 +160,29 @@ type TranscodeMeta struct { } type TrackChild struct { - ID *specid.ID `xml:"id,attr,omitempty" json:"id,omitempty"` - Album string `xml:"album,attr,omitempty" json:"album,omitempty"` - AlbumID *specid.ID `xml:"albumId,attr,omitempty" json:"albumId,omitempty"` - Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"` - ArtistID *specid.ID `xml:"artistId,attr,omitempty" json:"artistId,omitempty"` - Bitrate int `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"` - ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"` - CoverID *specid.ID `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"` - CreatedAt time.Time `xml:"created,attr,omitempty" json:"created,omitempty"` - Duration int `xml:"duration,attr,omitempty" json:"duration,omitempty"` - Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"` - IsDir bool `xml:"isDir,attr" json:"isDir"` - IsVideo bool `xml:"isVideo,attr" json:"isVideo"` - ParentID *specid.ID `xml:"parent,attr,omitempty" json:"parent,omitempty"` - Path string `xml:"path,attr,omitempty" json:"path,omitempty"` - Size int `xml:"size,attr,omitempty" json:"size,omitempty"` - Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"` - Title string `xml:"title,attr" json:"title"` - TrackNumber int `xml:"track,attr,omitempty" json:"track,omitempty"` - DiscNumber int `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"` - Type string `xml:"type,attr,omitempty" json:"type,omitempty"` - Year int `xml:"year,attr,omitempty" json:"year,omitempty"` + ID *specid.ID `xml:"id,attr,omitempty" json:"id,omitempty"` + Album string `xml:"album,attr,omitempty" json:"album,omitempty"` + AlbumID *specid.ID `xml:"albumId,attr,omitempty" json:"albumId,omitempty"` + Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"` + ArtistID *specid.ID `xml:"artistId,attr,omitempty" json:"artistId,omitempty"` + Bitrate int `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"` + ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"` + CoverID *specid.ID `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"` + CreatedAt time.Time `xml:"created,attr,omitempty" json:"created,omitempty"` + Duration int `xml:"duration,attr,omitempty" json:"duration,omitempty"` + Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"` + Genres []*GenreRef `xml:"genres,omitempty" json:"genres,omitempty"` + IsDir bool `xml:"isDir,attr" json:"isDir"` + IsVideo bool `xml:"isVideo,attr" json:"isVideo"` + ParentID *specid.ID `xml:"parent,attr,omitempty" json:"parent,omitempty"` + Path string `xml:"path,attr,omitempty" json:"path,omitempty"` + Size int `xml:"size,attr,omitempty" json:"size,omitempty"` + Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"` + Title string `xml:"title,attr" json:"title"` + TrackNumber int `xml:"track,attr,omitempty" json:"track,omitempty"` + DiscNumber int `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"` + Type string `xml:"type,attr,omitempty" json:"type,omitempty"` + Year int `xml:"year,attr,omitempty" json:"year,omitempty"` // star / rating Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"` UserRating int `xml:"userRating,attr,omitempty" json:"userRating,omitempty"` diff --git a/server/ctrlsubsonic/testdata/test_search_three_q_tra b/server/ctrlsubsonic/testdata/test_search_three_q_tra index d804c73..5ac9afe 100644 --- a/server/ctrlsubsonic/testdata/test_search_three_q_tra +++ b/server/ctrlsubsonic/testdata/test_search_three_q_tra @@ -19,6 +19,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-3", @@ -42,6 +43,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-3", @@ -65,6 +67,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-3", @@ -88,6 +91,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-4", @@ -111,6 +115,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-4", @@ -134,6 +139,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-4", @@ -157,6 +163,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-5", @@ -180,6 +187,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-5", @@ -203,6 +211,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-5", @@ -226,6 +235,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-7", @@ -249,6 +259,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-7", @@ -272,6 +283,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-7", @@ -295,6 +307,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-8", @@ -318,6 +331,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-8", @@ -341,6 +355,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-8", @@ -364,6 +379,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-9", @@ -387,6 +403,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-9", @@ -410,6 +427,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-9", @@ -433,6 +451,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-11", @@ -456,6 +475,7 @@ "created": "2019-11-30T00:00:00Z", "duration": 100, "genre": "Unknown Genre", + "genres": [{ "name": "Unknown Genre" }], "isDir": false, "isVideo": false, "parent": "al-11",