Skip to content

Commit 376ae05

Browse files
author
Your Name
committed
release: v1.5.10 — Symfonium compat, popular tracks, MusicBrainz mirror support
- fix(subsonic): map #text to value in JSON responses for Symfonium (#126) - fix(subsonic): add getBookmarks.view empty stub for Symfonium (#126) - fix(artist): show 10 popular tracks instead of 5 (#91) - feat(musicbrainz): configurable base URL via MUSICBRAINZ_BASE_URL env var (#63)
1 parent 51c7617 commit 376ae05

File tree

8 files changed

+27
-9
lines changed

8 files changed

+27
-9
lines changed

.env.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ VERSION=latest
9191
# For split containers (docker-compose.yml), simply don't start the audio-analyzer-clap service.
9292
# DISABLE_CLAP=true
9393

94+
# ==============================================================================
95+
# OPTIONAL: MusicBrainz Configuration
96+
# ==============================================================================
97+
98+
# Custom MusicBrainz API base URL (default: https://musicbrainz.org/ws/2)
99+
# Useful for self-hosted MusicBrainz mirrors to avoid rate limiting
100+
# MUSICBRAINZ_BASE_URL=https://musicbrainz.org/ws/2
101+
94102
# ==============================================================================
95103
# OPTIONAL: Lidarr Webhook Configuration
96104
# ==============================================================================

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ All notable changes to Kima will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [1.5.9] - 2026-02-27
8+
## [1.5.10] - 2026-02-27
99

1010
### Added
1111

@@ -25,6 +25,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525
- **Enrichment pipeline: "Reset Vibe Embeddings" incomplete**: `reRunVibeEmbeddingsOnly()` reset `vibeAnalysisStatus` but did not delete existing `track_embeddings` rows, so the re-queue query (which uses LEFT JOIN) silently skipped tracks that already had embeddings. Now deletes all embeddings first for full regeneration.
2626
- **Feature detection: CLAP reported available when disabled**: When `DISABLE_CLAP=true` was set, `checkCLAP()` skipped the file-existence check but still fell through to heartbeat and data checks. If old embeddings existed in the database, it returned `true`, causing the vibe sweep to queue jobs that no CLAP worker would ever process. Now returns `false` immediately when disabled.
2727
- **docker-compose.server.yml healthcheck using removed tool**: Healthcheck used `wget` which is removed from the production image during security hardening. Changed to `node /app/healthcheck.js` to match docker-compose.prod.yml.
28+
- **#126 Subsonic JSON `getGenres.view` breaking Symfonium**: Genre responses used `#text` for the genre name in JSON output -- correct for XML but violates the Subsonic JSON convention which uses `value`. Symfonium's strict JSON parser rejected the response. Fixed `stripAttrPrefix()` to map `#text` to `value` in all JSON responses.
29+
- **#126 Subsonic `getBookmarks.view` not implemented**: Symfonium calls `getBookmarks.view` during sync and expects a valid response with a `bookmarks` key. The endpoint hit the catch-all "not implemented" handler, returning an error without the required key. Added an empty stub returning `{ bookmarks: {} }`.
30+
- **#91 Artist page only showing 5 popular tracks**: Frontend sliced popular tracks to 5 even though the backend returned 10. Now displays all 10.
31+
- **#63 MusicBrainz base URL hardcoded**: MusicBrainz API URL was hardcoded, preventing use of self-hosted mirrors. Now configurable via `MUSICBRAINZ_BASE_URL` environment variable (defaults to `https://musicbrainz.org/ws/2`).
2832

2933
## [1.5.8] - 2026-02-26
3034

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "kima-backend",
3-
"version": "1.5.9",
3+
"version": "1.5.10",
44
"description": "Kima backend API server",
55
"license": "GPL-3.0",
66
"repository": {

backend/src/routes/subsonic/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ subsonicRouter.all("/getOpenSubsonicExtensions.view", (req: Request, res: Respon
5858
});
5959
});
6060

61+
// Stubs for endpoints not yet fully implemented.
62+
// Return valid empty responses so strict clients (e.g. Symfonium) don't error.
63+
subsonicRouter.all("/getBookmarks.view", (req: Request, res: Response) => {
64+
subsonicOk(req, res, { bookmarks: {} });
65+
});
66+
6167
subsonicRouter.use(libraryRouter);
6268
subsonicRouter.use(playbackRouter);
6369
subsonicRouter.use(searchRouter);

backend/src/services/musicbrainz.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class MusicBrainzService {
88

99
constructor() {
1010
this.client = axios.create({
11-
baseURL: "https://musicbrainz.org/ws/2",
11+
baseURL: process.env.MUSICBRAINZ_BASE_URL || "https://musicbrainz.org/ws/2",
1212
timeout: 10000,
1313
headers: {
1414
"User-Agent":

backend/src/utils/subsonicResponse.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ function stripAttrPrefix(obj: unknown): unknown {
1919
if (Array.isArray(obj)) return obj.map(stripAttrPrefix);
2020
if (obj !== null && typeof obj === "object") {
2121
return Object.fromEntries(
22-
Object.entries(obj as Record<string, unknown>).map(([k, v]) => [
23-
k.startsWith("@_") ? k.slice(2) : k,
24-
stripAttrPrefix(v),
25-
])
22+
Object.entries(obj as Record<string, unknown>).map(([k, v]) => {
23+
const key = k === "#text" ? "value" : k.startsWith("@_") ? k.slice(2) : k;
24+
return [key, stripAttrPrefix(v)];
25+
})
2626
);
2727
}
2828
return obj;

frontend/features/artist/components/PopularTracks.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const PopularTracks: React.FC<PopularTracksProps> = ({
3636
<section>
3737
<SectionHeader color="tracks" title="Popular" />
3838
<div data-tv-section="tracks">
39-
{tracks.slice(0, 5).map((track, index) => {
39+
{tracks.slice(0, 10).map((track, index) => {
4040
const isPlaying = currentTrackId === track.id;
4141
const isPreviewPlaying =
4242
previewTrack === track.id && previewPlaying;

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "kima-frontend",
3-
"version": "1.5.9",
3+
"version": "1.5.10",
44
"description": "Kima web frontend",
55
"license": "GPL-3.0",
66
"repository": {

0 commit comments

Comments
 (0)