refactor(server): unify stream URL builders + MIME tables + cover-path helper
test-go / test (push) Successful in 28s
test-go / integration (push) Has been cancelled

Closes Scribe #614, #615, server half of #616 surfaced by the 2026-06-04 divergent-provider audit.

- streamURL helper now used everywhere /api/tracks/{id}/stream is built (was inline concat in playlists.go and cast_token.go); add streamURLWithExt for the .ext cast variant.

- audioContentType in media.go is the canonical file_format -> MIME lookup; mimeForFormat in cast_token.go is now a thin wrapper that overrides the unknown-format fallback to audio/mpeg (Sonos rejects octet-stream). Adds mpeg/vorbis/wave aliases. Subsonic's contentTypeForFormat stays frozen per docs.

- coverart.ResolveAlbumPath extracted; api and subsonic both delegate to it.
This commit is contained in:
2026-06-04 08:29:51 -04:00
parent edd198cdf5
commit 024493f2a7
6 changed files with 69 additions and 62 deletions
+24
View File
@@ -7,8 +7,11 @@
package coverart
import (
"context"
"os"
"path/filepath"
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
)
// SidecarNames is the lookup order for cover art living next to audio files.
@@ -33,3 +36,24 @@ func FindSidecar(albumDir string) string {
}
return ""
}
// ResolveAlbumPath returns the on-disk path to an album's cover image,
// preferring the explicit album.cover_art_path when set and the file
// exists, falling back to a sidecar (cover.jpg / folder.jpg) next to the
// first track in the album's directory. "" means no art was found.
//
// Shared by internal/api/media.go (browser endpoint) and
// internal/subsonic/stream.go (Subsonic endpoint); they were byte-identical
// duplicates before extraction.
func ResolveAlbumPath(ctx context.Context, q *dbq.Queries, album dbq.Album) string {
if album.CoverArtPath != nil && *album.CoverArtPath != "" {
if _, err := os.Stat(*album.CoverArtPath); err == nil {
return *album.CoverArtPath
}
}
tracks, err := q.ListTracksByAlbum(ctx, dbq.ListTracksByAlbumParams{AlbumID: album.ID})
if err != nil || len(tracks) == 0 {
return ""
}
return FindSidecar(filepath.Dir(tracks[0].FilePath))
}