Compare commits
5 commits
21b7c28692
...
fda799e32e
Author | SHA1 | Date | |
---|---|---|---|
fda799e32e | |||
30e0829ff3 | |||
e2268c0c34 | |||
1e6dffcdcc | |||
86761bc420 |
5 changed files with 43 additions and 28 deletions
|
@ -17,11 +17,14 @@
|
||||||
"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",
|
||||||
|
"items": {
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"title": "Artist",
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"title": "Artist",
|
||||||
|
"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",
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
|
@ -30,16 +33,22 @@
|
||||||
},
|
},
|
||||||
"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",
|
||||||
|
"items": {
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"title": "Release",
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"title": "Release",
|
||||||
|
"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.",
|
||||||
|
"items": {
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"title": "Release Artist",
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"title": "Release Artist",
|
||||||
|
"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",
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
|
@ -59,6 +68,11 @@
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"required": [
|
||||||
|
"artist",
|
||||||
|
"release",
|
||||||
|
"release_artist"
|
||||||
|
],
|
||||||
"title": "MusicBrainzIds",
|
"title": "MusicBrainzIds",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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")),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue