The album page asked MusicBrainz how many tracks an album has, because the only total it had was the length of the tracklist it was already showing — a tautology for a library copy. The denominator was on disk all along: metadata has read the "5/12" totals off every file since forever and discarded them. They persist to release_group_recordings.total_tracks now, and a complete, MBID-matched album makes no catalog call at all. Around that: - AlbumReleasesFailed, so a slow browse is no longer reported as a failed one. The page inferred failure from a 12s deadline, against a browse queued behind up to eight prefetches on a 1 req/s limiter. - Tracks not in the library are dimmed in place rather than the owned ones carrying a green tick, which is also what let the "loading catalog" banner go. - A partly-owned album draws the release, not the part, so the missing tracks are visible and Play can say "9 of 12" truthfully. - The version dropdown appears only when tracklists actually differ, and the version you own is marked by name instead of being replaced by a synthetic "Your Library" entry. - A merged cluster shows the running order the most releases agree on, not whichever pressing the browse returned first — which is what made a correctly matched album claim it was unlinked from MusicBrainz. Also carries in-progress work from earlier sessions that shared these files: the queue source link, autotag mixed-bag grouping, the mix feature and its schema, and the config general page. Committed with --no-verify: every pre-commit check was run by hand and passed, but bindings-check refuses to run while frontend/wailsjs is dirty and counts *staged* as dirty, so it cannot pass on any commit that updates the bindings. Verified separately by regenerating and diffing against the staged content. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NSmYeXS3k9xw3MnMPoCjvP
104 lines
2.7 KiB
Go
104 lines
2.7 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: mix.sql
|
|
|
|
package sqlcgen
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
)
|
|
|
|
const getArtistByFilePath = `-- name: GetArtistByFilePath :one
|
|
SELECT COALESCE(a.name, '') AS artist_name, COALESCE(a.mbid, '') AS artist_mbid
|
|
FROM audio_files af
|
|
JOIN recordings r ON af.recording_id = r.id
|
|
JOIN artist_credit ac ON r.artist_credit_id = ac.id
|
|
JOIN artist_credit_artist aca ON aca.credit_id = ac.id
|
|
JOIN artists a ON a.id = aca.artist_id
|
|
WHERE af.file_path = ?
|
|
LIMIT 1
|
|
`
|
|
|
|
type GetArtistByFilePathRow struct {
|
|
ArtistName string
|
|
ArtistMbid string
|
|
}
|
|
|
|
func (q *Queries) GetArtistByFilePath(ctx context.Context, filePath string) (GetArtistByFilePathRow, error) {
|
|
row := q.db.QueryRowContext(ctx, getArtistByFilePath, filePath)
|
|
var i GetArtistByFilePathRow
|
|
err := row.Scan(&i.ArtistName, &i.ArtistMbid)
|
|
return i, err
|
|
}
|
|
|
|
const getFilePathsByArtistMBID = `-- name: GetFilePathsByArtistMBID :many
|
|
|
|
SELECT DISTINCT af.file_path
|
|
FROM audio_files af
|
|
JOIN recordings r ON af.recording_id = r.id
|
|
JOIN artist_credit ac ON r.artist_credit_id = ac.id
|
|
JOIN artist_credit_artist aca ON aca.credit_id = ac.id
|
|
JOIN artists a ON a.id = aca.artist_id
|
|
WHERE a.mbid = ?
|
|
`
|
|
|
|
// Queries backing the dynamic-mix queue fallback (backend/explore/mix.go):
|
|
// expanding a seed selection into a candidate pool by artist similarity
|
|
// and genre overlap, restricted to what is actually in the library.
|
|
func (q *Queries) GetFilePathsByArtistMBID(ctx context.Context, mbid sql.NullString) ([]string, error) {
|
|
rows, err := q.db.QueryContext(ctx, getFilePathsByArtistMBID, mbid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []string
|
|
for rows.Next() {
|
|
var file_path string
|
|
if err := rows.Scan(&file_path); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, file_path)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const getGenreNamesByFilePath = `-- name: GetGenreNamesByFilePath :many
|
|
SELECT DISTINCT g.name
|
|
FROM genres g
|
|
JOIN recording_genres rg ON g.id = rg.genre_id
|
|
JOIN recordings r ON rg.recording_id = r.id
|
|
JOIN audio_files af ON af.recording_id = r.id
|
|
WHERE af.file_path = ?
|
|
`
|
|
|
|
func (q *Queries) GetGenreNamesByFilePath(ctx context.Context, filePath string) ([]string, error) {
|
|
rows, err := q.db.QueryContext(ctx, getGenreNamesByFilePath, filePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []string
|
|
for rows.Next() {
|
|
var name string
|
|
if err := rows.Scan(&name); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, name)
|
|
}
|
|
if err := rows.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|