diff --git a/server/subsonic/browsing.go b/server/subsonic/browsing.go
index 53323db60..7c75c7427 100644
--- a/server/subsonic/browsing.go
+++ b/server/subsonic/browsing.go
@@ -423,6 +423,7 @@ func (api *Router) buildAlbum(ctx context.Context, album *model.Album, mfs model
}
dir.Year = int32(album.MaxYear)
dir.Genre = album.Genre
+ dir.Genres = itemGenresFromGenres(album.Genres)
dir.UserRating = int32(album.Rating)
if !album.CreatedAt.IsZero() {
dir.Created = &album.CreatedAt
@@ -430,6 +431,7 @@ func (api *Router) buildAlbum(ctx context.Context, album *model.Album, mfs model
if album.Starred {
dir.Starred = &album.StarredAt
}
+ dir.MusicBrainzId = album.MbzAlbumID
dir.Song = childrenFromMediaFiles(ctx, mfs)
return dir
}
diff --git a/server/subsonic/helpers.go b/server/subsonic/helpers.go
index f7b13d10a..dd500c60c 100644
--- a/server/subsonic/helpers.go
+++ b/server/subsonic/helpers.go
@@ -110,6 +110,7 @@ func toArtistID3(r *http.Request, a model.Artist) responses.ArtistID3 {
CoverArt: a.CoverArtID().String(),
ArtistImageUrl: public.ImageURL(r, a.CoverArtID(), 600),
UserRating: int32(a.Rating),
+ MusicBrainzId: a.MbzArtistID,
}
if a.Starred {
artist.Starred = &a.StarredAt
@@ -151,6 +152,7 @@ func childFromMediaFile(ctx context.Context, mf model.MediaFile) responses.Child
child.Year = int32(mf.Year)
child.Artist = mf.Artist
child.Genre = mf.Genre
+ child.Genres = itemGenresFromGenres(mf.Genres)
child.Track = int32(mf.TrackNumber)
child.Duration = int32(mf.Duration)
child.Size = mf.Size
@@ -184,6 +186,8 @@ func childFromMediaFile(ctx context.Context, mf model.MediaFile) responses.Child
child.TranscodedContentType = mime.TypeByExtension("." + format)
}
child.BookmarkPosition = mf.BookmarkPosition
+ child.Comment = mf.Comment
+ child.Bpm = int32(mf.Bpm)
return child
}
@@ -217,6 +221,7 @@ func childFromAlbum(_ context.Context, al model.Album) responses.Child {
child.Artist = al.AlbumArtist
child.Year = int32(al.MaxYear)
child.Genre = al.Genre
+ child.Genres = itemGenresFromGenres(al.Genres)
child.CoverArt = al.CoverArtID().String()
child.Created = &al.CreatedAt
child.Parent = al.AlbumArtistID
@@ -241,3 +246,11 @@ func childrenFromAlbums(ctx context.Context, als model.Albums) []responses.Child
}
return children
}
+
+func itemGenresFromGenres(genres model.Genres) []responses.ItemGenre {
+ itemGenres := make([]responses.ItemGenre, len(genres))
+ for i, g := range genres {
+ itemGenres[i] = responses.ItemGenre{Name: g.Name}
+ }
+ return itemGenres
+}
diff --git a/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .JSON b/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .JSON
index 40c691954..e0e812900 100644
--- a/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"albumList":{"album":[{"id":"1","isDir":false,"title":"title","isVideo":false}]}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"albumList":{"album":[{"id":"1","isDir":false,"title":"title","genres":[],"isVideo":false,"bpm":0,"comment":""}]}}
diff --git a/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .XML b/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .XML
index e4f61a704..d6d09ace3 100644
--- a/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses AlbumList with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .JSON
index 602279801..8eb6dd66f 100644
--- a/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"bookmarks":{"bookmark":[{"entry":{"id":"1","isDir":false,"title":"title","isVideo":false},"position":123,"username":"user2","comment":"a comment","created":"0001-01-01T00:00:00Z","changed":"0001-01-01T00:00:00Z"}]}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"bookmarks":{"bookmark":[{"entry":{"id":"1","isDir":false,"title":"title","genres":[],"isVideo":false,"bpm":0,"comment":""},"position":123,"username":"user2","comment":"a comment","created":"0001-01-01T00:00:00Z","changed":"0001-01-01T00:00:00Z"}]}}
diff --git a/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .XML b/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .XML
index 080d4fc48..ba1c967d1 100644
--- a/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses Bookmarks with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON
index 0444d8e7c..8e1cf0d29 100644
--- a/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"directory":{"child":[{"id":"1","isDir":true,"title":"title","album":"album","artist":"artist","track":1,"year":1985,"genre":"Rock","coverArt":"1","size":8421341,"contentType":"audio/flac","suffix":"flac","starred":"2016-03-02T20:30:00Z","transcodedContentType":"audio/mpeg","transcodedSuffix":"mp3","duration":146,"bitRate":320,"isVideo":false}],"id":"1","name":"N"}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"directory":{"child":[{"id":"1","isDir":true,"title":"title","album":"album","artist":"artist","track":1,"year":1985,"genre":"Rock","genres":[],"coverArt":"1","size":8421341,"contentType":"audio/flac","suffix":"flac","starred":"2016-03-02T20:30:00Z","transcodedContentType":"audio/mpeg","transcodedSuffix":"mp3","duration":146,"bitRate":320,"isVideo":false,"bpm":0,"comment":""}],"id":"1","name":"N"}}
diff --git a/server/subsonic/responses/.snapshots/Responses Child with data should match .XML b/server/subsonic/responses/.snapshots/Responses Child with data should match .XML
index 1ce29024f..07d28bb5e 100644
--- a/server/subsonic/responses/.snapshots/Responses Child with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses Child with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/.snapshots/Responses Directory with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Directory with data should match .JSON
index 7b3f7de85..7cb1c7403 100644
--- a/server/subsonic/responses/.snapshots/Responses Directory with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses Directory with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"directory":{"child":[{"id":"1","isDir":false,"title":"title","isVideo":false}],"id":"1","name":"N"}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"directory":{"child":[{"id":"1","isDir":false,"title":"title","genres":[],"isVideo":false,"bpm":0,"comment":""}],"id":"1","name":"N"}}
diff --git a/server/subsonic/responses/.snapshots/Responses Directory with data should match .XML b/server/subsonic/responses/.snapshots/Responses Directory with data should match .XML
index b11f3fce6..fb87a2d97 100644
--- a/server/subsonic/responses/.snapshots/Responses Directory with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses Directory with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .JSON b/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .JSON
index 2603112b5..b9dba55c9 100644
--- a/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"playQueue":{"entry":[{"id":"1","isDir":false,"title":"title","isVideo":false}],"current":"111","position":243,"username":"user1","changed":"0001-01-01T00:00:00Z","changedBy":"a_client"}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"playQueue":{"entry":[{"id":"1","isDir":false,"title":"title","genres":[],"isVideo":false,"bpm":0,"comment":""}],"current":"111","position":243,"username":"user1","changed":"0001-01-01T00:00:00Z","changedBy":"a_client"}}
diff --git a/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .XML b/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .XML
index d96030df5..defcd4f58 100644
--- a/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses PlayQueue with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/.snapshots/Responses Shares with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Shares with data should match .JSON
index e35b2729b..0eac71e08 100644
--- a/server/subsonic/responses/.snapshots/Responses Shares with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses Shares with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"shares":{"share":[{"entry":[{"id":"1","isDir":false,"title":"title","album":"album","artist":"artist","duration":120,"isVideo":false},{"id":"2","isDir":false,"title":"title 2","album":"album","artist":"artist","duration":300,"isVideo":false}],"id":"ABC123","url":"http://localhost/p/ABC123","description":"Check it out!","username":"deluan","created":"0001-01-01T00:00:00Z","expires":"0001-01-01T00:00:00Z","lastVisited":"0001-01-01T00:00:00Z","visitCount":2}]}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"shares":{"share":[{"entry":[{"id":"1","isDir":false,"title":"title","album":"album","artist":"artist","genres":[],"duration":120,"isVideo":false,"bpm":0,"comment":""},{"id":"2","isDir":false,"title":"title 2","album":"album","artist":"artist","genres":[],"duration":300,"isVideo":false,"bpm":0,"comment":""}],"id":"ABC123","url":"http://localhost/p/ABC123","description":"Check it out!","username":"deluan","created":"0001-01-01T00:00:00Z","expires":"0001-01-01T00:00:00Z","lastVisited":"0001-01-01T00:00:00Z","visitCount":2}]}}
diff --git a/server/subsonic/responses/.snapshots/Responses Shares with data should match .XML b/server/subsonic/responses/.snapshots/Responses Shares with data should match .XML
index 4fa5cda16..9a628c66b 100644
--- a/server/subsonic/responses/.snapshots/Responses Shares with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses Shares with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .JSON b/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .JSON
index 1a09565e5..a67febe7f 100644
--- a/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"similarSongs":{"song":[{"id":"1","isDir":false,"title":"title","isVideo":false}]}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"similarSongs":{"song":[{"id":"1","isDir":false,"title":"title","genres":[],"isVideo":false,"bpm":0,"comment":""}]}}
diff --git a/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .XML b/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .XML
index f0a2e0163..39429cbea 100644
--- a/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses SimilarSongs with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .JSON b/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .JSON
index 2236dc35b..7887668a2 100644
--- a/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"similarSongs2":{"song":[{"id":"1","isDir":false,"title":"title","isVideo":false}]}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"similarSongs2":{"song":[{"id":"1","isDir":false,"title":"title","genres":[],"isVideo":false,"bpm":0,"comment":""}]}}
diff --git a/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .XML b/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .XML
index 090a59d73..1140d0985 100644
--- a/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses SimilarSongs2 with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .JSON b/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .JSON
index 889707ae2..6e5ea0992 100644
--- a/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .JSON
+++ b/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .JSON
@@ -1 +1 @@
-{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"topSongs":{"song":[{"id":"1","isDir":false,"title":"title","isVideo":false}]}}
+{"status":"ok","version":"1.8.0","type":"navidrome","serverVersion":"v0.0.0","openSubsonic":true,"topSongs":{"song":[{"id":"1","isDir":false,"title":"title","genres":[],"isVideo":false,"bpm":0,"comment":""}]}}
diff --git a/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .XML b/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .XML
index bda5a0a60..34c8b82ef 100644
--- a/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .XML
+++ b/server/subsonic/responses/.snapshots/Responses TopSongs with data should match .XML
@@ -1 +1 @@
-
+
diff --git a/server/subsonic/responses/responses.go b/server/subsonic/responses/responses.go
index 495b7b2b0..8b48add8d 100644
--- a/server/subsonic/responses/responses.go
+++ b/server/subsonic/responses/responses.go
@@ -1,6 +1,7 @@
package responses
import (
+ "encoding/json"
"encoding/xml"
"time"
)
@@ -106,42 +107,59 @@ type Indexes struct {
}
type Child struct {
- Id string `xml:"id,attr" json:"id"`
- Parent string `xml:"parent,attr,omitempty" json:"parent,omitempty"`
- IsDir bool `xml:"isDir,attr" json:"isDir"`
- Title string `xml:"title,attr,omitempty" json:"title,omitempty"`
- Name string `xml:"name,attr,omitempty" json:"name,omitempty"`
- Album string `xml:"album,attr,omitempty" json:"album,omitempty"`
- Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
- Track int32 `xml:"track,attr,omitempty" json:"track,omitempty"`
- Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
- Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
- CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
- Size int64 `xml:"size,attr,omitempty" json:"size,omitempty"`
- ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"`
- Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"`
- Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
- TranscodedContentType string `xml:"transcodedContentType,attr,omitempty" json:"transcodedContentType,omitempty"`
- TranscodedSuffix string `xml:"transcodedSuffix,attr,omitempty" json:"transcodedSuffix,omitempty"`
- Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"`
- BitRate int32 `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"`
- Path string `xml:"path,attr,omitempty" json:"path,omitempty"`
- PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
- Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"`
- DiscNumber int32 `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"`
- Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
- AlbumId string `xml:"albumId,attr,omitempty" json:"albumId,omitempty"`
- ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
- Type string `xml:"type,attr,omitempty" json:"type,omitempty"`
- UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"`
- SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
- IsVideo bool `xml:"isVideo,attr" json:"isVideo"`
- BookmarkPosition int64 `xml:"bookmarkPosition,attr,omitempty" json:"bookmarkPosition,omitempty"`
+ Id string `xml:"id,attr" json:"id"`
+ Parent string `xml:"parent,attr,omitempty" json:"parent,omitempty"`
+ IsDir bool `xml:"isDir,attr" json:"isDir"`
+ Title string `xml:"title,attr,omitempty" json:"title,omitempty"`
+ Name string `xml:"name,attr,omitempty" json:"name,omitempty"`
+ Album string `xml:"album,attr,omitempty" json:"album,omitempty"`
+ Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
+ Track int32 `xml:"track,attr,omitempty" json:"track,omitempty"`
+ Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
+ Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
+ Genres []ItemGenre `xml:"genres" json:"genres"`
+ CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
+ Size int64 `xml:"size,attr,omitempty" json:"size,omitempty"`
+ ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"`
+ Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"`
+ Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
+ TranscodedContentType string `xml:"transcodedContentType,attr,omitempty" json:"transcodedContentType,omitempty"`
+ TranscodedSuffix string `xml:"transcodedSuffix,attr,omitempty" json:"transcodedSuffix,omitempty"`
+ Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"`
+ BitRate int32 `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"`
+ Path string `xml:"path,attr,omitempty" json:"path,omitempty"`
+ PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
+ Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"`
+ DiscNumber int32 `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"`
+ Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
+ AlbumId string `xml:"albumId,attr,omitempty" json:"albumId,omitempty"`
+ ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
+ Type string `xml:"type,attr,omitempty" json:"type,omitempty"`
+ UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"`
+ SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
+ IsVideo bool `xml:"isVideo,attr" json:"isVideo"`
+ BookmarkPosition int64 `xml:"bookmarkPosition,attr,omitempty" json:"bookmarkPosition,omitempty"`
+ Bpm int32 `xml:"bpm,attr" json:"bpm"`
+ Comment string `xml:"comment,attr" json:"comment"`
/*
*/
}
+func (c Child) MarshalJSON() ([]byte, error) {
+ // ensure fields that need custom default values are set properly
+ type Alias Child
+ a := struct {
+ Alias
+ }{
+ Alias: (Alias)(c),
+ }
+ if a.Genres == nil {
+ a.Genres = make([]ItemGenre, 0)
+ }
+ return json.Marshal(a)
+}
+
type Songs struct {
Songs []Child `xml:"song" json:"song,omitempty"`
}
@@ -180,23 +198,40 @@ type ArtistID3 struct {
Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"`
ArtistImageUrl string `xml:"artistImageUrl,attr,omitempty" json:"artistImageUrl,omitempty"`
+ MusicBrainzId string `xml:"musicBrainzId,attr,omitempty" json:"musicBrainzId,omitempty"`
}
type AlbumID3 struct {
- Id string `xml:"id,attr" json:"id"`
- Name string `xml:"name,attr" json:"name"`
- Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
- ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
- CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
- SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
- Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"`
- PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
- Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"`
- Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
- Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
- UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"`
- Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
- Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
+ Id string `xml:"id,attr" json:"id"`
+ Name string `xml:"name,attr" json:"name"`
+ Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"`
+ ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"`
+ CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"`
+ SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"`
+ Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"`
+ PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"`
+ Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"`
+ Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"`
+ Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"`
+ UserRating int32 `xml:"userRating,attr" json:"userRating"`
+ Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"`
+ Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"`
+ Genres []ItemGenre `xml:"genres" json:"genres"`
+ MusicBrainzId string `xml:"musicBrainzId,attr" json:"musicBrainzId"`
+}
+
+func (a AlbumID3) MarshalJSON() ([]byte, error) {
+ // ensure fields that need custom default values are set properly
+ type Alias AlbumID3
+ x := struct {
+ Alias
+ }{
+ Alias: (Alias)(a),
+ }
+ if x.Genres == nil {
+ x.Genres = make([]ItemGenre, 0)
+ }
+ return json.Marshal(x)
}
type ArtistWithAlbumsID3 struct {
@@ -418,3 +453,8 @@ type JukeboxPlaylist struct {
Entry []Child `xml:"entry,omitempty" json:"entry,omitempty"`
}
type OpenSubsonicExtensions struct{}
+
+// OpenSubsonic response type for multi-valued genres list
+type ItemGenre struct {
+ Name string `xml:"name,attr" json:"name"`
+}