Documentation
¶
Overview ¶
Package common contains types shared by client and server code.
Index ¶
Constants ¶
const ( // MaxRating is the maximum value for Song.Rating. MaxRating = 5 // VariousArtists is a Song.AlbumArtist value often used for albums // consisting of songs by multiple artists. VariousArtists = "Various Artists" )
Variables ¶
This section is empty.
Functions ¶
func ParseRangeHeader ¶
ParseRangeHeader parses an HTTP request Range header in the form "bytes=123-" or "bytes=123-456" and returns the inclusive start and ending offsets. The ending offset is -1 if it wasn't specified in the header, indicating the end of the file. Returns 0, -1, true (i.e. the whole file) if head is empty. Returns false if head was invalid or doesn't match the above forms.
Types ¶
type ImportResponse ¶
type ImportResponse struct {
// OrigFilenames maps from SHA1 to filename for songs that were already present in the
// database with different filenames.
OrigFilenames map[string]string `json:"origFilenames"`
}
ImportResponse is returned by the server in response to an /import call.
type Play ¶
type Play struct {
// StartTime is the time at which playback started.
StartTime time.Time `json:"t"`
// IPAddress is the IPv4 or IPv6 address of the client playing the song.
IPAddress string `datastore:"IpAddress" json:"ip"`
// ReportTime contains the time at which the play was reported.
// This field is unset for plays that were reported before the field
// was introduced in mid-September 2024.
ReportTime time.Time `json:"-"`
}
Play represents one playback of a Song.
type PlayDump ¶
type PlayDump struct {
// Song entity's key ID from Datastore.
SongID string `json:"songId"`
// Play information.
Play Play `json:"play"`
}
PlayDump is used when dumping data.
type PlayStats ¶
type PlayStats struct {
// Plays is the number of plays.
Plays int `json:"plays"`
// TotalSec is the total duration in seconds of played songs.
TotalSec float64 `json:"totalSec"`
// FirstPlays is the number of songs that were first played in the interval.
FirstPlays int `json:"firstPlays"`
// LastPlays is the number of songs that were last played in the interval.
LastPlays int `json:"lastPlays"`
}
PlayStats summarizes plays in a time interval.
type ReindexResponse ¶
type ReindexResponse struct {
// Scanned is the number of songs that were read.
Scanned int `json:"scanned"`
// Updated is the number of songs that were updated.
Updated int `json:"updated"`
// Cursor should be passed in the next /reindex call.
// An empty cursor indicates that reindexing is complete.
Cursor string `json:"cursor"`
}
ReindexResponse is returned by the server in response to a /reindex call.
type Song ¶
type Song struct {
// SHA1 is a hash of the audio portion of the file.
SHA1 string `datastore:"Sha1" json:"sha1,omitempty"`
// SongID is the Song entity's key ID from datastore.
// Only set in JSON objects returned by the server.
SongID string `datastore:"-" json:"songId,omitempty"`
// Filename is a relative path from the base of the music directory.
// Clients can pass this to the server's /song endpoint to download the
// song's music data.
Filename string `json:"filename,omitempty"`
// CoverFilename is a relative path from the base of the covers directory.
// Must be escaped for Cloud Storage when constructing CoverURL.
// Clients can pass this to the server's /cover endpoint to get a scaled
// copy of the cover.
CoverFilename string `datastore:",noindex" json:"coverFilename,omitempty"`
// Canonical versions used for display.
Artist string `datastore:",noindex" json:"artist"`
Title string `datastore:",noindex" json:"title"`
Album string `datastore:",noindex" json:"album"`
// AlbumArtist contains the album's artist if it isn't the same as Artist.
// This corresponds to the TPE2 ID3 tag, which may hold the performer name
// in the case of a classical album, or the remixer name in the case of an
// album consisting of songs remixed by a single artist.
AlbumArtist string `datastore:",noindex" json:"albumArtist,omitempty"`
// DiscSubtitle contains the disc's subtitle, if any.
DiscSubtitle string `json:"discSubtitle,omitempty"`
// AlbumID is an opaque ID uniquely identifying the album
// (generally, a MusicBrainz release ID taken from a "MusicBrainz Album Id" ID3v2 tag).
AlbumID string `datastore:"AlbumId" json:"albumId,omitempty"`
// RecordingID is an opaque ID uniquely identifying the recording (generally, the MusicBrainz ID
// corresponding to the MusicBrainz recording entity, taken from a UFID ID3v2 tag).
// This is used to find cover art if files corresponding to CoverID and AlbumID are not found.
// It is also used to find updated metadata for the song in MusicBrainz.
// TODO: Send this to the server?
RecordingID string `datastore:"-" json:"-"`
// Track is the song's track number, or 0 if unset.
Track int `json:"track"`
// Disc is the song's disc number, or 0 if unset.
Disc int `json:"disc"`
// Date is the date on which this song was recorded or released in UTC.
// It is used when listing songs or albums in chronological order.
// This is vaguely defined because the ID3v2 fields related to it are a mess:
// https://codeberg.org/derat/nup/issues/42
Date time.Time `json:"date,omitempty"`
// Length is the song's duration in seconds.
Length float64 `json:"length"`
// TrackGain is the song's dB gain adjustment independent of its album. More info:
// https://en.wikipedia.org/wiki/ReplayGain
// https://wiki.hydrogenaud.io/index.php?title=ReplayGain_specification
// https://productionadvice.co.uk/tidal-normalization-upgrade/
TrackGain float64 `datastore:",noindex" json:"trackGain"`
// AlbumGain is the song's dB gain adjustment relative to its album.
AlbumGain float64 `datastore:",noindex" json:"albumGain"`
// PeakAmp is the song's peak amplitude, with 1.0 representing the highest
// amplitude that can be played without clipping.
PeakAmp float64 `datastore:",noindex" json:"peakAmp"`
// Rating is the song's rating in the range [1, MaxRating], or 0 if unrated.
// The server should call SetRating to additionally update the RatingAtLeast* fields.
Rating int `json:"rating"`
// Plays contains the song's playback history.
// Only used for importing data -- in datastore, Play is a descendant of Song.
Plays []Play `datastore:"-" json:"plays,omitempty"`
// Tags contains tags assigned to the song by the user.
// Tags cannot start with '-' or contain '|' or whitespace characters.
Tags []string `json:"tags"`
}
Song represents an audio file and holds metadata and user-generated data.
When adding fields, the Clone and MetadataEquals methods must be updated.
func (*Song) Clean ¶
func (s *Song) Clean()
Clean sorts and removes duplicates from slice fields in s.
func (Song) MarshalJSON ¶
MarshalJSON uses a disgusting hack from https://stackoverflow.com/a/60567000 to omit "Date" fields that have the zero value.
func (*Song) MetadataEquals ¶
MetadataEquals returns true if s and o have identical metadata. User data (ratings, plays, tags) fields are not checked.
type Stats ¶
type Stats struct {
// Songs is the total number of songs in the database.
Songs int `json:"songs"`
// Plays is the total number of play reports in the database.
Plays int `json:"plays"`
// Albums is the total number of albums in the database.
// This is computed by counting distinct Song.AlbumID values.
Albums int `json:"albums"`
// TotalSec is the total duration in seconds of all songs.
TotalSec float64 `json:"totalSec"`
// Ratings maps from a rating in [1, 5] (or 0 for unrated) to number of songs with that rating.
Ratings map[int]int `json:"ratings"`
// SongDecades maps from the year at the beginning of a decade (e.g. 1990) to the number of
// songs in the database with a Date field in the decade. 0 is used for songs with unset dates.
SongDecades map[int]int `json:"songDecades"`
// Tags maps from tag to number of songs with that tag.
Tags map[string]int `json:"tags"`
// Years maps from year (e.g. 2020) to stats about plays in that year.
Years map[int]PlayStats `json:"years"`
// UpdateTime is the time at which these stats were generated.
UpdateTime *time.Time `json:"updateTime,omitempty"`
}
Stats summarizes information from the database.