// Copyright (c) 2026 Jeremy Baxter. // In-memory album and song database package musicindex import ( "cmp" "slices" "git.baxters.nz/jeremy/records/util" ) type Artist struct { Name string Albums map[string]Album Songs int Valid bool } type Album struct { Artist *Artist Name string HasCover bool CoverFile string TrackFiles []string Tarball string TarballSize int64 } var initialised = false var artists map[string]Artist var coverFileExtension string var defaultCoverFile string var mediaDir string var regenerateTarballs bool var trackFileExtension string func Init(path string, regenerate bool) { InitWith(path, regenerate, ".flac", "cover.jpg", ".jpg") } func InitWith(path string, regenerate bool, mediaExtension, coverFile, coverExtension string) { if initialised { return } mediaDir = path defaultCoverFile = coverFile regenerateTarballs = regenerate trackFileExtension = mediaExtension coverFileExtension = coverExtension assertAccessTo(mediaDir) indexArtists() initialised = true } func MediaDirectory() string { return mediaDir } func Artists() (l []string) { for k, v := range artists { util.Assert(k == v.Name) l = append(l, k) } slices.Sort(l) return } func ArtistExists(name string) bool { _, ok := artists[name] return ok } func FindArtist(name string) (a Artist) { if ArtistExists(name) { return artists[name] } a.Name = "Invalid artist" a.Valid = false return } func ArtistDirectory(name string) string { return mediaDir + "/" + name } func (a Album) RelativeDirectory() string { return a.Artist.Name + "/" + a.Name } func (a Album) Directory() string { return mediaDir + "/" + a.RelativeDirectory() } func (a Album) RelativeCoverPath() string { return a.RelativeDirectory() + "/" + a.CoverFile } func (a Album) CoverPath() string { return mediaDir + "/" + a.RelativeCoverPath() } func Albums() (albums []Album) { for _, artist := range Artists() { for _, album := range FindArtist(artist).Albums { albums = append(albums, album) } } slices.SortFunc(albums, func(a, b Album) int { return cmp.Compare(a.Name, b.Name) }) return }