subsonic: Implement getSong API endpoint

The getSong API endpoint is used by, e.g., the subsonic plugin to mopidy.
Signed-off-by: Toke Høiland-Jørgensen's avatarToke Høiland-Jørgensen <>
parent 8193782f
......@@ -130,6 +130,14 @@ class GetAlbumSerializer(serializers.Serializer):
return payload
class GetSongSerializer(serializers.Serializer):
def to_representation(self, track):
tf = track.files.all()
if not len(tf):
return {}
return get_track_data(track.album, track, tf[0])
def get_starred_tracks_data(favorites):
by_track_id = {f.track_id: f for f in favorites}
tracks = (
......@@ -147,6 +147,15 @@ class SubsonicViewSet(viewsets.GenericViewSet):
return response.Response(payload, status=200)
@list_route(methods=["get", "post"], url_name="get_song", url_path="getSong")
def get_song(self, request, *args, **kwargs):
track = kwargs.pop("obj")
data = serializers.GetSongSerializer(track).data
payload = {"song": data}
return response.Response(payload, status=200)
methods=["get", "post"], url_name="get_artist_info2", url_path="getArtistInfo2"
......@@ -140,6 +140,20 @@ def test_get_album(f, db, logged_in_api_client, factories):
assert == expected
@pytest.mark.parametrize("f", ["xml", "json"])
def test_get_song(f, db, logged_in_api_client, factories):
url = reverse("api:subsonic-get-song")
assert url.endswith("getSong") is True
artist = factories["music.Artist"]()
album = factories["music.Album"](artist=artist)
track = factories["music.Track"](album=album)
tf = factories["music.TrackFile"](track=track)
response = logged_in_api_client.get(url, {"f": f, "id":})
assert response.status_code == 200
assert == {"song": serializers.get_track_data(track.album, track, tf)}
@pytest.mark.parametrize("f", ["xml", "json"])
def test_stream(f, db, logged_in_api_client, factories, mocker):
url = reverse("api:subsonic-stream")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment