Skip to content

Commit

Permalink
Expose year of recrodings for songs and albums
Browse files Browse the repository at this point in the history
  • Loading branch information
ironsmile committed Oct 19, 2024
1 parent 2e62cdf commit 16fa0e0
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 9 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ which would return an JSON array with tracks. Every object in the JSON represent
"rating": 5, // User rating in the [1-5] range.
"favourite": 1714834066, // Unix timestamp (seconds) when the track was added to favourites.
"bitrate": 1536000, // Bits per second of this song.
"size": 3303014 // Size of the track file in bytes.
"size": 3303014, // Size of the track file in bytes.
"year": 2004 // Year when this track has been included in the album.
},
{
"album" : "Battlefield Vietnam",
Expand All @@ -317,7 +318,7 @@ The most important thing here is the track ID at the `id` key. It can be used fo

Note that the track duration is in milliseconds.

_Optional properties_: Some properties of tracks are optional and may be omitted in the response when they are not set. They may not be set because no user has performed an action which sets them or the value may not be set in the track file's metadata. E.g. playing a song for the fist time will set its `plays` property to 1. The list of optional properties is: `plays`, `favourite`, `last_played`, `rating`, `bitrate`, `size`.
_Optional properties_: Some properties of tracks are optional and may be omitted in the response when they are not set. They may not be set because no user has performed an action which sets them or the value may not be set in the track file's metadata. E.g. playing a song for the fist time will set its `plays` property to 1. The list of optional properties is: `plays`, `favourite`, `last_played`, `rating`, `bitrate`, `size`, `year`.

### Browse

Expand Down Expand Up @@ -368,14 +369,15 @@ would result in value such as
```js
{
"album": "Battlefield Vietnam"
"artist": "Jefferson Airplane",
"artist": "Various Artists",
"album_id": 2,
"duration": 1953000, // In milliseconds.
"track_count": 12, // Number of tracks (songs) which this album has.
"plays": 2312, // Number of times a song from the album has been played.
"favourite": 1614834066, // Unix timestamp in seconds. When it was added to favourites.
"last_played": 1714834066, // Unix timestamp in seconds.
"rating": 5 // User rating in [1-5] range.
"rating": 5, // User rating in [1-5] range.
"year": 2004 // Four digit year of when this album has been released.
}
```

Expand Down Expand Up @@ -405,6 +407,7 @@ _order-by_: controls how the results would be ordered. **Defaults to `name` for
* `random` means that the list will be randomly ordered.
* `frequency` will order by the number of times tracks have been played. For album this is the number of times tracks in this album has been played. Only applicable when `by` is `album` or `song`.
* `recency` will order tracks or albums by when was the last time the song or the album was played. Only applicable when `by` is `album` or `song`.
* `year` will order tracks or albums by the year of their release. Only applicable when `by` is `album` or `song`.

_order_: controls if the order would ascending (with value `asc`) or descending (with value `desc`). **Defaults to `asc`**.

Expand Down
7 changes: 4 additions & 3 deletions src/library/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ type SearchResult struct {
Rating uint8 `json:"rating,omitempty"`

// Year is the four digit year at which this track was recorded.
//
// Not encoded in the JSON response the API for the moment.
Year int32 `json:"-"`
Year int32 `json:"year,omitempty"`

// Bitrate is measured in bits per second.
Bitrate uint64 `json:"bitrate,omitempty"`
Expand Down Expand Up @@ -132,6 +130,9 @@ type Album struct {
// Rating is the user rating given to this album. It will be a number
// in the [1-5] range or 0 if no rating was given.
Rating uint8 `json:"rating,omitempty"`

// Year is a four digit number for the year in which the album has been released.
Year int32 `json:"year,omitempty"`
}

// Favourites describes a set of favourite tracks, artists and albums.
Expand Down
14 changes: 13 additions & 1 deletion src/library/local_browse.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ func (lib *LocalLibrary) BrowseAlbums(args BrowseArgs) ([]Album, int) {
where = append(where, "als.favourite IS NOT NULL AND als.favourite != 0")
case OrderByYear:
orderBy = "tr.year " + order
where = append(where, "tr.year IS NOT NULL")
}

if len(where) > 0 {
Expand Down Expand Up @@ -225,6 +226,8 @@ func (lib *LocalLibrary) BrowseAlbums(args BrowseArgs) ([]Album, int) {
END AS artist_name,
COUNT(tr.id) as songCount,
SUM(tr.duration) as duration,
SUM(us.play_count) as plays,
MIN(tr.year) as year,
als.favourite,
als.user_rating
FROM
Expand Down Expand Up @@ -256,10 +259,12 @@ func (lib *LocalLibrary) BrowseAlbums(args BrowseArgs) ([]Album, int) {
res Album
fav sql.NullInt64
rating sql.NullInt16
plays sql.NullInt64
year sql.NullInt32
)
if err := rows.Scan(
&res.ID, &res.Name, &res.Artist, &res.SongCount,
&res.Duration, &fav, &rating,
&res.Duration, &plays, &year, &fav, &rating,
); err != nil {
return fmt.Errorf("scanning db failed: %w", err)
}
Expand All @@ -269,6 +274,12 @@ func (lib *LocalLibrary) BrowseAlbums(args BrowseArgs) ([]Album, int) {
if rating.Valid {
res.Rating = uint8(rating.Int16)
}
if plays.Valid {
res.Plays = plays.Int64
}
if year.Valid {
res.Year = year.Int32
}

output = append(output, res)
}
Expand Down Expand Up @@ -350,6 +361,7 @@ func (lib *LocalLibrary) BrowseTracks(args BrowseArgs) ([]TrackInfo, int) {
where = append(where, "us.favourite IS NOT NULL AND us.favourite != 0")
case OrderByYear:
orderBy = "t.year " + order
where = append(where, "t.year IS NOT NULL")
}

queryArgs = append(
Expand Down
6 changes: 6 additions & 0 deletions src/library/local_library.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ func (lib *LocalLibrary) GetAlbum(
END AS arist_name,
COUNT(tr.id) as album_songs,
SUM(tr.duration) as album_duration,
MIN(tr.year) as year,
SUM(us.play_count) as album_plays,
MAX(us.last_played) as last_played,
als.favourite,
Expand All @@ -579,12 +580,14 @@ func (lib *LocalLibrary) GetAlbum(
rating sql.NullInt16
plays sql.NullInt64
lastPlayed sql.NullInt64
year sql.NullInt32
)
err := row.Scan(
&res.Name,
&res.Artist,
&res.SongCount,
&res.Duration,
&year,
&plays,
&lastPlayed,
&fav,
Expand All @@ -608,6 +611,9 @@ func (lib *LocalLibrary) GetAlbum(
if lastPlayed.Valid {
res.LastPlayed = lastPlayed.Int64
}
if year.Valid {
res.Year = year.Int32
}

return nil
}
Expand Down
5 changes: 4 additions & 1 deletion src/webserver/handler_browse.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (bh BrowseHandler) browse(writer http.ResponseWriter, req *http.Request) er
return nil
}

possibleOrders := []string{"id", "name", "random", "frequency", "recency"}
possibleOrders := []string{"id", "name", "random", "frequency", "recency", "year"}
if orderBy != "" && !slices.Contains(possibleOrders, orderBy) {
bh.badRequest(writer,
fmt.Sprintf("Wrong 'order-by' parameter - '%s'. ", orderBy)+
Expand Down Expand Up @@ -139,6 +139,7 @@ func (bh BrowseHandler) browseArtists(
unsupportedBrowseBy := []library.BrowseOrderBy{
library.OrderByRecentlyPlayed,
library.OrderByFrequentlyPlayed,
library.OrderByYear,
}
if slices.Contains(unsupportedBrowseBy, browseArgs.OrderBy) {
return fmt.Errorf(
Expand Down Expand Up @@ -240,6 +241,8 @@ func getBrowseArgs(page, perPage int, orderBy, order string) library.BrowseArgs
browseArgs.OrderBy = library.OrderByFrequentlyPlayed
case "recency":
browseArgs.OrderBy = library.OrderByRecentlyPlayed
case "year":
browseArgs.OrderBy = library.OrderByYear
default:
browseArgs.OrderBy = library.OrderByName
}
Expand Down
2 changes: 2 additions & 0 deletions src/webserver/subsonic/xsd_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ func albumToChild(
Starred: toUnixTimeWithNull(album.Favourite),
UserRating: album.Rating,
PlayCount: album.Plays,
Year: int16(album.Year),
}

if artistID != 0 {
Expand Down Expand Up @@ -219,6 +220,7 @@ func dbAlbumToAlbumID3Entry(album library.Album) xsdAlbumID3 {
Duration: album.Duration / 1000,
Starred: toUnixTimeWithNull(album.Favourite),
PlayCount: album.Plays,
Year: int16(album.Year),
}
}

Expand Down

0 comments on commit 16fa0e0

Please sign in to comment.