44 "encoding/json"
55 "fmt"
66 "net/url"
7+ "slices"
78 "strconv"
89
910 "github.com/navidrome/navidrome/plugins/pdk/go/metadata"
@@ -13,15 +14,13 @@ import (
1314// Configuration keys (must match manifest.json)
1415const (
1516 configAPIUrl = "apiUrl"
16- configTrackCount = "trackCount"
1717 configEliminateDuplicates = "eliminateDuplicates"
1818 configRadiusSimilarity = "radiusSimilarity"
1919)
2020
2121// Default values
2222const (
2323 defaultAPIUrl = "http://192.168.3.203:8000"
24- defaultTrackCount = 200
2524 defaultArtistSimilarCount = 10
2625 defaultEliminateDuplicates = true
2726 defaultRadiusSimilarity = true
@@ -81,17 +80,16 @@ func (p *audioMusePlugin) GetSimilarSongsByTrack(input metadata.SimilarSongsByTr
8180
8281 // Read configuration
8382 apiBaseURL := getConfigString (configAPIUrl , defaultAPIUrl )
84- trackCount := getConfigInt (configTrackCount , defaultTrackCount )
8583 eliminateDuplicates := getConfigBool (configEliminateDuplicates , defaultEliminateDuplicates )
8684 radiusSimilarity := getConfigBool (configRadiusSimilarity , defaultRadiusSimilarity )
8785
8886 pdk .Log (pdk .LogDebug , fmt .Sprintf ("[AudioMuse] Config - API URL: %s, TrackCount: %d, EliminateDuplicates: %v, RadiusSimilarity: %v" ,
89- apiBaseURL , trackCount , eliminateDuplicates , radiusSimilarity ))
87+ apiBaseURL , input . Count , eliminateDuplicates , radiusSimilarity ))
9088
9189 // Build the API URL with query parameters
9290 params := url.Values {}
9391 params .Set ("item_id" , input .ID )
94- params .Set ("n" , strconv .Itoa (trackCount ))
92+ params .Set ("n" , strconv .Itoa (int ( input . Count ) ))
9593 params .Set ("eliminate_duplicates" , strconv .FormatBool (eliminateDuplicates ))
9694 params .Set ("radius_similarity" , strconv .FormatBool (radiusSimilarity ))
9795
@@ -151,37 +149,72 @@ func (p *audioMusePlugin) GetSimilarSongsByArtist(input metadata.SimilarSongsByA
151149 return nil , err
152150 }
153151
154- // Collect unique song IDs preserving order
155- songIDs := make ([]string , 0 )
156152 seen := make (map [string ]bool )
157153
154+ // songSlices contains artist songs in alternating order: [baseArtist, relatedArtist1, baseArtist, relatedArtist2, ...]
155+ songSlices := [][]metadata.SongRef {}
156+
158157 for _ , a := range artists {
158+ var artist1Songs , artist2Songs []metadata.SongRef
159+
159160 for _ , cm := range a .ComponentMatches {
160161 for _ , s := range cm .Artist1RepresentativeSongs {
162+
161163 if s .ItemID == "" {
162164 continue
163165 }
164- if ! seen [s .ItemID ] {
165- seen [s .ItemID ] = true
166- songIDs = append (songIDs , s .ItemID )
166+ if seen [s .ItemID ] {
167+ continue
167168 }
169+
170+ seen [s .ItemID ] = true
171+ artist1Songs = append (artist1Songs , metadata.SongRef {ID : s .ItemID , Name : s .Title })
168172 }
173+
169174 for _ , s := range cm .Artist2RepresentativeSongs {
170175 if s .ItemID == "" {
171176 continue
172177 }
173- if ! seen [ s . ItemID ] {
174- seen [s .ItemID ] = true
175- songIDs = append ( songIDs , s . ItemID )
178+
179+ if seen [s .ItemID ] {
180+ continue
176181 }
182+
183+ seen [s .ItemID ] = true
184+ artist2Songs = append (artist2Songs , metadata.SongRef {ID : s .ItemID , Name : s .Title })
177185 }
178186 }
187+
188+ if len (artist1Songs ) > 0 {
189+ songSlices = append (songSlices , artist1Songs )
190+ }
191+ if len (artist2Songs ) > 0 {
192+ songSlices = append (songSlices , artist2Songs )
193+ }
179194 }
180195
181- // Build SongRef list (names not always available)
182- songs := make ([]metadata.SongRef , 0 , len (songIDs ))
183- for _ , id := range songIDs {
184- songs = append (songs , metadata.SongRef {ID : id })
196+ songs := make ([]metadata.SongRef , 0 , input .Count )
197+
198+ // get songs from our slices until we have enough or we ran out
199+ artistID := 0
200+ for len (songs ) < int (input .Count ) && len (songSlices ) > 0 {
201+ song := songSlices [artistID ][0 ] // take a song
202+ songs = append (songs , song )
203+
204+ songSlices [artistID ] = songSlices [artistID ][1 :] // remove it from the pool
205+
206+ if len (songSlices [artistID ]) == 0 {
207+ // this slice has no more songs, remove it
208+ songSlices = slices .Delete (songSlices , artistID , artistID + 1 )
209+ if len (songSlices ) == 0 {
210+ break
211+ }
212+ } else {
213+ // else, go to the next slice
214+ artistID ++
215+ }
216+
217+ artistID = artistID % len (songSlices ) // loop around if needed
185218 }
186219
187220 pdk .Log (pdk .LogInfo , fmt .Sprintf ("[AudioMuse] Returning %d artist-related songs to Navidrome" , len (songs )))
0 commit comments