Compare commits

...

5 commits

5 changed files with 43 additions and 28 deletions

View file

@ -17,10 +17,13 @@
"MusicBrainzIds": { "MusicBrainzIds": {
"properties": { "properties": {
"artist": { "artist": {
"description": "https://musicbrainz.org/doc/Artist", "description": "A MusicBrainz artist is pretty intuitively the artist who recorded the song. This particular ID refers to the individual recording's artist or artists, which may be distinct from the release artist below when a release contains recordings from many different artists. https://musicbrainz.org/doc/Artist",
"format": "uuid", "items": {
"format": "uuid",
"type": "string"
},
"title": "Artist", "title": "Artist",
"type": "string" "type": "array"
}, },
"recording": { "recording": {
"description": "A MusicBrainz recording represents audio from a specific performance. For example, if the same song was released as a studio recording and as a live performance, those two versions of the song are different recordings. The song itself is considered a \"work\", of which two recordings were made. However, recordings are not always associated with a work in the MusicBrainz database, and Picard won't load work IDs by default (you have to enable \"use track relationships\" in the options), so recording IDs are a much more reliable way to identify a particular song. https://musicbrainz.org/doc/Recording", "description": "A MusicBrainz recording represents audio from a specific performance. For example, if the same song was released as a studio recording and as a live performance, those two versions of the song are different recordings. The song itself is considered a \"work\", of which two recordings were made. However, recordings are not always associated with a work in the MusicBrainz database, and Picard won't load work IDs by default (you have to enable \"use track relationships\" in the options), so recording IDs are a much more reliable way to identify a particular song. https://musicbrainz.org/doc/Recording",
@ -30,15 +33,21 @@
}, },
"release": { "release": {
"description": "A MusicBrainz release roughly corresponds to an \"album\", and indeed is stored in a tag called MUSICBRAINZ_ALBUMID. The more general name is meant to encompass all the different ways music can be released. https://musicbrainz.org/doc/Release", "description": "A MusicBrainz release roughly corresponds to an \"album\", and indeed is stored in a tag called MUSICBRAINZ_ALBUMID. The more general name is meant to encompass all the different ways music can be released. https://musicbrainz.org/doc/Release",
"format": "uuid", "items": {
"format": "uuid",
"type": "string"
},
"title": "Release", "title": "Release",
"type": "string" "type": "array"
}, },
"release_artist": { "release_artist": {
"description": "Again, the release artist corresponds to an \"album artist\". These MBIDs refer to the same artists in the MusicBrainz database that individual recordings' artist MBIDs do.", "description": "Again, the release artist corresponds to an \"album artist\". These MBIDs refer to the same artists in the MusicBrainz database that individual recordings' artist MBIDs do.",
"format": "uuid", "items": {
"format": "uuid",
"type": "string"
},
"title": "Release Artist", "title": "Release Artist",
"type": "string" "type": "array"
}, },
"release_group": { "release_group": {
"description": "A MusicBrainz release group roughly corresponds to \"all the editions of a particular album\". For example, if the same album were released on CD, vinyl records, and as a digital download, then all of those would be different releases but share a release group. Note that MPD's support for this tag is relatively new (July 2023) and doesn't seem especially reliable, so it might be missing here even if your music has been tagged with it. Not sure why. https://musicbrainz.org/doc/Release_Group", "description": "A MusicBrainz release group roughly corresponds to \"all the editions of a particular album\". For example, if the same album were released on CD, vinyl records, and as a digital download, then all of those would be different releases but share a release group. Note that MPD's support for this tag is relatively new (July 2023) and doesn't seem especially reliable, so it might be missing here even if your music has been tagged with it. Not sure why. https://musicbrainz.org/doc/Release_Group",
@ -59,6 +68,11 @@
"type": "string" "type": "string"
} }
}, },
"required": [
"artist",
"release",
"release_artist"
],
"title": "MusicBrainzIds", "title": "MusicBrainzIds",
"type": "object" "type": "object"
}, },

View file

@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
from contextlib import suppress
from typing import Any, Generic, Optional, TypeVar from typing import Any, Generic, Optional, TypeVar
import ormsgpack
from aiocache import Cache from aiocache import Cache
from aiocache.serializers import BaseSerializer from aiocache.serializers import BaseSerializer
from pydantic.type_adapter import TypeAdapter from pydantic.type_adapter import TypeAdapter
@ -10,9 +10,6 @@ from yarl import URL
T = TypeVar("T") T = TypeVar("T")
with suppress(ImportError):
import ormsgpack
class OrmsgpackSerializer(BaseSerializer, Generic[T]): class OrmsgpackSerializer(BaseSerializer, Generic[T]):
DEFAULT_ENCODING = None DEFAULT_ENCODING = None

View file

@ -1,5 +1,6 @@
from typing import Literal, NotRequired, Protocol, TypedDict from typing import Literal, NotRequired, Protocol, TypedDict
from ..song.musicbrainz import MusicBrainzTags
from ..tools.types import MaybePlural from ..tools.types import MaybePlural
@ -48,7 +49,7 @@ class StatusResponse(TypedDict):
# optional. mpd-now-playable will work better if your music is properly # optional. mpd-now-playable will work better if your music is properly
# tagged, since then it can pass more information on to Now Playing, but it # tagged, since then it can pass more information on to Now Playing, but it
# should work fine with completely untagged music too. # should work fine with completely untagged music too.
class CurrentSongTags(TypedDict, total=False): class CurrentSongTags(MusicBrainzTags, total=False):
artist: MaybePlural[str] artist: MaybePlural[str]
albumartist: MaybePlural[str] albumartist: MaybePlural[str]
artistsort: MaybePlural[str] artistsort: MaybePlural[str]
@ -62,11 +63,6 @@ class CurrentSongTags(TypedDict, total=False):
disc: str disc: str
label: str label: str
genre: MaybePlural[str] genre: MaybePlural[str]
musicbrainz_albumid: str
musicbrainz_albumartistid: str
musicbrainz_releasetrackid: str
musicbrainz_artistid: str
musicbrainz_trackid: str
class CurrentSongResponse(CurrentSongTags): class CurrentSongResponse(CurrentSongTags):

View file

@ -34,7 +34,7 @@ class WebsocketsReceiver(Receiver):
async def start(self, player: Player) -> None: async def start(self, player: Player) -> None:
self.player = player self.player = player
await serve(self.handle, host=self.config.host, port=self.config.port) await serve(self.handle, host=self.config.host, port=self.config.port, reuse_port=True)
async def handle(self, conn: WebSocketServerProtocol) -> None: async def handle(self, conn: WebSocketServerProtocol) -> None:
self.connections.add(conn) self.connections.add(conn)

View file

@ -5,12 +5,16 @@ from uuid import UUID
from pydantic import Field from pydantic import Field
from ..tools.types import option_fmap from ..tools.types import MaybePlural, option_fmap, un_maybe_plural
option_uuid = partial(option_fmap, UUID) option_uuid = partial(option_fmap, UUID)
OptionUUID = Annotated[UUID | None, Field(default=None)] OptionUUID = Annotated[UUID | None, Field(default=None)]
def to_uuids(values: MaybePlural[str] | None) -> list[UUID]:
return [UUID(i) for i in un_maybe_plural(values)]
class MusicBrainzTags(TypedDict, total=False): class MusicBrainzTags(TypedDict, total=False):
""" """
The MusicBrainz tags mpd-now-playable expects and will load (all optional). The MusicBrainz tags mpd-now-playable expects and will load (all optional).
@ -24,11 +28,11 @@ class MusicBrainzTags(TypedDict, total=False):
#: MusicBrainz Track ID #: MusicBrainz Track ID
musicbrainz_releasetrackid: str musicbrainz_releasetrackid: str
#: MusicBrainz Artist ID #: MusicBrainz Artist ID
musicbrainz_artistid: str musicbrainz_artistid: MaybePlural[str]
#: MusicBrainz Release ID #: MusicBrainz Release ID
musicbrainz_albumid: str musicbrainz_albumid: MaybePlural[str]
#: MusicBrainz Release Artist ID #: MusicBrainz Release Artist ID
musicbrainz_albumartistid: str musicbrainz_albumartistid: MaybePlural[str]
#: MusicBrainz Release Group ID #: MusicBrainz Release Group ID
musicbrainz_releasegroupid: str musicbrainz_releasegroupid: str
#: MusicBrainz Work ID #: MusicBrainz Work ID
@ -63,19 +67,23 @@ class MusicBrainzIds:
#: https://musicbrainz.org/doc/Track #: https://musicbrainz.org/doc/Track
track: OptionUUID track: OptionUUID
#: A MusicBrainz artist is pretty intuitively the artist who recorded the
#: song. This particular ID refers to the individual recording's artist or
#: artists, which may be distinct from the release artist below when a
#: release contains recordings from many different artists.
#: https://musicbrainz.org/doc/Artist #: https://musicbrainz.org/doc/Artist
artist: OptionUUID artist: list[UUID]
#: A MusicBrainz release roughly corresponds to an "album", and indeed is #: A MusicBrainz release roughly corresponds to an "album", and indeed is
#: stored in a tag called MUSICBRAINZ_ALBUMID. The more general name is #: stored in a tag called MUSICBRAINZ_ALBUMID. The more general name is
#: meant to encompass all the different ways music can be released. #: meant to encompass all the different ways music can be released.
#: https://musicbrainz.org/doc/Release #: https://musicbrainz.org/doc/Release
release: OptionUUID release: list[UUID]
#: Again, the release artist corresponds to an "album artist". These MBIDs #: Again, the release artist corresponds to an "album artist". These MBIDs
#: refer to the same artists in the MusicBrainz database that individual #: refer to the same artists in the MusicBrainz database that individual
#: recordings' artist MBIDs do. #: recordings' artist MBIDs do.
release_artist: OptionUUID release_artist: list[UUID]
#: A MusicBrainz release group roughly corresponds to "all the editions of #: A MusicBrainz release group roughly corresponds to "all the editions of
#: a particular album". For example, if the same album were released on CD, #: a particular album". For example, if the same album were released on CD,
@ -92,8 +100,8 @@ def to_brainz(tags: MusicBrainzTags) -> MusicBrainzIds:
recording=option_uuid(tags.get("musicbrainz_trackid")), recording=option_uuid(tags.get("musicbrainz_trackid")),
work=option_uuid(tags.get("musicbrainz_workid")), work=option_uuid(tags.get("musicbrainz_workid")),
track=option_uuid(tags.get("musicbrainz_releasetrackid")), track=option_uuid(tags.get("musicbrainz_releasetrackid")),
artist=option_uuid(tags.get("musicbrainz_artistid")), artist=to_uuids(tags.get("musicbrainz_artistid")),
release=option_uuid(tags.get("musicbrainz_albumid")), release=to_uuids(tags.get("musicbrainz_albumid")),
release_artist=option_uuid(tags.get("musicbrainz_albumartistid")), release_artist=to_uuids(tags.get("musicbrainz_albumartistid")),
release_group=option_uuid(tags.get("musicbrainz_releasegroupid")), release_group=option_uuid(tags.get("musicbrainz_releasegroupid")),
) )