common

package
v0.0.0-...-fbcb358 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 11, 2026 License: BSD-3-Clause Imports: 10 Imported by: 0

Documentation

Overview

Package common contains types shared by client and server code.

Index

Constants

View Source
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 DiffSongs

func DiffSongs(a, b *Song) string

DiffSongs diffs a and b and returns a multiline string describing differences.

func ParseRangeHeader

func ParseRangeHeader(head string) (start, end int64, ok bool)

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.

func (*Play) Equal

func (p *Play) Equal(o *Play) bool

type PlayArray

type PlayArray []Play

func (PlayArray) Len

func (a PlayArray) Len() int

func (PlayArray) Less

func (a PlayArray) Less(i, j int) bool

func (PlayArray) Swap

func (a PlayArray) Swap(i, j int)

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) Clone

func (s *Song) Clone() *Song

Clone returns a deep copy of s.

func (*Song) Duration

func (s *Song) Duration() time.Duration

func (Song) MarshalJSON

func (s Song) MarshalJSON() ([]byte, error)

MarshalJSON uses a disgusting hack from https://stackoverflow.com/a/60567000 to omit "Date" fields that have the zero value.

func (*Song) MetadataEquals

func (s *Song) MetadataEquals(o *Song) bool

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.

Directories

Path Synopsis
Package cover contains cover-related constants and functions.
Package cover contains cover-related constants and functions.
Package strutil contains string-related utility functions.
Package strutil contains string-related utility functions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL