Compare commits

..

No commits in common. "dc037a0a4b3d15b9e80384b2d843694c7b8aefef" and "fd7866ed14e9c59d69a959202b05906fc0e322ee" have entirely different histories.

13 changed files with 33 additions and 310 deletions

112
pdm.lock
View file

@ -5,7 +5,7 @@
groups = ["default", "all", "dev"]
strategy = ["cross_platform"]
lock_version = "4.4.1"
content_hash = "sha256:828f8051de2c2a04cede8130abf86764edb38f0428cd1d52dd797bff43452afe"
content_hash = "sha256:2b4fba8ca6883f5a1de28a420870d566efa031d62f9057c59095a25a0e51d36e"
[[package]]
name = "aiocache"
@ -54,22 +54,6 @@ files = [
{file = "aiomcache-0.8.2.tar.gz", hash = "sha256:43b220d7f499a32a71871c4f457116eb23460fa216e69c1d32b81e3209e51359"},
]
[[package]]
name = "apischema"
version = "0.18.1"
requires_python = ">=3.7"
summary = "JSON (de)serialization, GraphQL and JSON schema generation using Python typing."
files = [
{file = "apischema-0.18.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:220aa56974f765dc100e875c66c688ff57bad3ae48d0aeaee4fb1ec90c5cd0fd"},
{file = "apischema-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:653492010d22acdcbe2240f0ceb3ca59de1b6d34640895e03fda15f944e216d8"},
{file = "apischema-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56a8acc8da59cf7a1052b5aec71d2f8ed6137b54aa1492709acb2c47f0547107"},
{file = "apischema-0.18.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d466ccc31cbc95b381037ed5b9e82e034f921eb28f8057263aefc2817678036f"},
{file = "apischema-0.18.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b005d5a4baba32eccec5bb0fbd616f9fd26b6a5fb4f15e9a8bb53a948adade0"},
{file = "apischema-0.18.1-cp312-cp312-win32.whl", hash = "sha256:bd06fc6a52d461bd6540409cb25c1d51aae23b22fcd10b1fb002a3f7f1f15d0f"},
{file = "apischema-0.18.1-cp312-cp312-win_amd64.whl", hash = "sha256:429f13d9e35379bf8187c41a3c05562f8149358128382a90e415c63db528d6a2"},
{file = "apischema-0.18.1.tar.gz", hash = "sha256:355dc4dea7389f5b25f5326c26f06eebee8107efda7e82db8f09ee122cdf0c98"},
]
[[package]]
name = "attrs"
version = "23.2.0"
@ -80,41 +64,6 @@ files = [
{file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
]
[[package]]
name = "idna"
version = "3.7"
requires_python = ">=3.5"
summary = "Internationalized Domain Names in Applications (IDNA)"
files = [
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
]
[[package]]
name = "multidict"
version = "6.0.5"
requires_python = ">=3.7"
summary = "multidict implementation"
files = [
{file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"},
{file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"},
{file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"},
{file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"},
{file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"},
{file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"},
{file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"},
{file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"},
{file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"},
]
[[package]]
name = "mypy"
version = "1.10.0"
@ -266,26 +215,6 @@ files = [
{file = "python_mpd2-3.1.1-py2.py3-none-any.whl", hash = "sha256:86bf1100a0b135959d74a9a7a58cf0515bf30bb54eb25ae6fb8e175e50300fc3"},
]
[[package]]
name = "pytomlpp"
version = "1.0.13"
summary = "A python wrapper for toml++"
files = [
{file = "pytomlpp-1.0.13-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4710c72456c10a90e58084174312abef8f9652b0f91c240c008903c1bd99814d"},
{file = "pytomlpp-1.0.13-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b59acc12339a992404289ab7294f28ba06c7df3c2562e81d316a0e744ab4103b"},
{file = "pytomlpp-1.0.13-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:252e31a5e013a74b898784f4ffb8aa8068e136b910ad11f2af1ee8a5700e6e1e"},
{file = "pytomlpp-1.0.13-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:09e716c0f462d15f2334cecc736957777dd30f8a5bfa5cf8150679da7577d2fd"},
{file = "pytomlpp-1.0.13-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:19dbded2995370e802105fa6dce54ed60f79e58b4eb35fee7ef33f1fb5958f6c"},
{file = "pytomlpp-1.0.13-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f87f6c958309e4c2358b778902c80bd33611d1c392f1abe2c226e3a62909ca4"},
{file = "pytomlpp-1.0.13-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e285aca948b419301fdda1927723287ef28482752782c44c9ee8c57eae7a1dc8"},
{file = "pytomlpp-1.0.13-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:aad6ae19c056ea62a43fec82427ad4675b5c773dc255c4bdcf6da659cd7edff6"},
{file = "pytomlpp-1.0.13-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0e0b34b7a132856567714342e9a622f7be0b4c9bac561a6252f0f85626c1aa4b"},
{file = "pytomlpp-1.0.13-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac06ca7683f5a2737b3888ea1e38d6968abb24fab703bc7ceccbe589d5420e0c"},
{file = "pytomlpp-1.0.13-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35225c1d9d674df87b4682f04af97856049351c38822455b78258248d9309363"},
{file = "pytomlpp-1.0.13-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:dbc9208ac58ea2a9d5ebb77e69d54d146744007f4a704a3f4e56d9881d41ee1c"},
{file = "pytomlpp-1.0.13.tar.gz", hash = "sha256:a0bd639a8f624d1bdf5b3ea94363ca23dbfef38ab7b5b9348881a84afab434ad"},
]
[[package]]
name = "redis"
version = "5.0.4"
@ -330,42 +259,3 @@ files = [
{file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"},
{file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"},
]
[[package]]
name = "xdg-base-dirs"
version = "6.0.1"
requires_python = ">=3.10,<4.0"
summary = "Variables defined by the XDG Base Directory Specification"
files = [
{file = "xdg_base_dirs-6.0.1-py3-none-any.whl", hash = "sha256:63f6ebc1721ced2e86c340856e004ef829501a30a37e17079c52cfaf0e1741b9"},
{file = "xdg_base_dirs-6.0.1.tar.gz", hash = "sha256:b4c8f4ba72d1286018b25eea374ec6fbf4fddda3d4137edf50de95de53e195a6"},
]
[[package]]
name = "yarl"
version = "1.9.4"
requires_python = ">=3.7"
summary = "Yet another URL library"
dependencies = [
"idna>=2.0",
"multidict>=4.0",
]
files = [
{file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"},
{file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"},
{file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"},
{file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"},
{file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"},
{file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"},
{file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"},
{file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"},
{file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"},
]

View file

@ -10,10 +10,6 @@ dependencies = [
"attrs>=23.1.0",
"pyobjc-framework-MediaPlayer>=10.0",
"python-mpd2>=3.1.0",
"xdg-base-dirs>=6.0.1",
"pytomlpp>=1.0.13",
"apischema>=0.18.1",
"yarl>=1.9.4",
]
readme = "README.md"
@ -52,8 +48,6 @@ check = {composite = ['lint', 'typecheck']}
[tool.pdm.version]
source = "scm"
write_to = 'mpd_now_playable/__version__.py'
write_template = "__version__ = '{}'"
[build-system]
requires = ["pdm-backend"]

View file

@ -1 +0,0 @@
__version__ = '0.0.1'

View file

@ -2,10 +2,10 @@ from __future__ import annotations
from contextlib import suppress
from typing import Any, Optional, TypeVar
from urllib.parse import parse_qsl, urlparse
from aiocache import Cache
from aiocache.serializers import BaseSerializer, PickleSerializer
from yarl import URL
T = TypeVar("T")
@ -28,23 +28,24 @@ class OrmsgpackSerializer(BaseSerializer):
return ormsgpack.unpackb(value)
def make_cache(url: URL, namespace: str = "") -> Cache[T]:
backend = Cache.get_scheme_class(url.scheme)
def make_cache(url: str, namespace: str = "") -> Cache[T]:
parsed_url = urlparse(url)
backend = Cache.get_scheme_class(parsed_url.scheme)
if backend == Cache.MEMORY:
return Cache(backend)
kwargs: dict[str, Any] = dict(url.query)
kwargs: dict[str, Any] = dict(parse_qsl(parsed_url.query))
if url.path:
kwargs.update(backend.parse_uri_path(url.path))
if parsed_url.path:
kwargs.update(backend.parse_uri_path(parsed_url.path))
if url.host:
kwargs["endpoint"] = url.host
if parsed_url.hostname:
kwargs["endpoint"] = parsed_url.hostname
if url.port:
kwargs["port"] = url.port
if parsed_url.port:
kwargs["port"] = parsed_url.port
if url.password:
kwargs["password"] = url.password
if parsed_url.password:
kwargs["password"] = parsed_url.password
namespace = ":".join(s for s in [kwargs.pop("namespace", ""), namespace] if s)

View file

@ -1,19 +1,23 @@
import asyncio
from os import environ
from corefoundationasyncio import CoreFoundationEventLoop
from .__version__ import __version__
from .cocoa.now_playing import CocoaNowPlaying
from .config.load import loadConfig
from .mpd.listener import MpdStateListener
async def listen() -> None:
print(f"mpd-now-playable v{__version__}")
config = loadConfig()
listener = MpdStateListener(config.cache)
port = int(environ.get("MPD_PORT", "6600"))
host = environ.get("MPD_HOST", "localhost")
password = environ.get("MPD_PASSWORD")
cache = environ.get("MPD_NOW_PLAYABLE_CACHE")
if password is None and "@" in host:
password, host = host.split("@", maxsplit=1)
listener = MpdStateListener(cache)
now_playing = CocoaNowPlaying(listener)
await listener.start(config.mpd)
await listener.start(host=host, port=port, password=password)
await listener.loop(now_playing)

View file

@ -1,44 +0,0 @@
{
"$id": "https://cdn.00dani.me/m/schemata/mpd-now-playable/config-v1.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"definitions": {
"URL": {
"format": "uri",
"type": "string"
}
},
"properties": {
"$schema": {
"$ref": "#/definitions/URL"
},
"cache": {
"$ref": "#/definitions/URL"
},
"mpd": {
"additionalProperties": false,
"default": {
"host": "127.0.0.1",
"port": 6600
},
"properties": {
"host": {
"default": "127.0.0.1",
"format": "hostname",
"type": "string"
},
"password": {
"type": "string"
},
"port": {
"default": 6600,
"maximum": 65535,
"minimum": 1,
"type": "integer"
}
},
"type": "object"
}
},
"type": "object"
}

View file

@ -1,28 +0,0 @@
from dataclasses import field
from typing import NewType, Optional, TypeVar
from apischema import schema
from apischema.conversions import deserializer
from apischema.metadata import none_as_undefined
from yarl import URL
__all__ = ("Host", "Port", "optional")
T = TypeVar("T")
Host = NewType("Host", str)
schema(format="hostname")(Host)
Port = NewType("Port", int)
schema(min=1, max=65535)(Port)
schema(format="uri")(URL)
def optional() -> Optional[T]:
return field(default=None, metadata=none_as_undefined)
@deserializer
def from_yarl(url: str) -> URL:
return URL(url)

View file

@ -1,34 +0,0 @@
from os import environ
from apischema import deserialize
from pytomlpp import load
from xdg_base_dirs import xdg_config_home
from .model import Config
__all__ = "loadConfig"
def loadConfigFromFile() -> Config:
path = xdg_config_home() / "mpd-now-playable" / "config.toml"
data = load(path)
print(f"Loaded your configuration from {path}")
return deserialize(Config, data)
def loadConfigFromEnv() -> Config:
port = int(environ["MPD_PORT"]) if "MPD_PORT" in environ else None
host = environ.get("MPD_HOST")
password = environ.get("MPD_PASSWORD")
cache = environ.get("MPD_NOW_PLAYABLE_CACHE")
if password is None and host is not None and "@" in host:
password, host = host.split("@", maxsplit=1)
data = {"cache": cache, "mpd": {"port": port, "host": host, "password": password}}
return deserialize(Config, data)
def loadConfig() -> Config:
try:
return loadConfigFromFile()
except FileNotFoundError:
return loadConfigFromEnv()

View file

@ -1,26 +0,0 @@
from dataclasses import dataclass, field
from typing import Optional
from apischema import alias
from yarl import URL
from .fields import Host, Port, optional
__all__ = ("MpdConfig", "Config")
@dataclass(frozen=True)
class MpdConfig:
password: Optional[str] = optional()
host: Host = Host("127.0.0.1")
port: Port = Port(6600)
@dataclass(frozen=True)
class Config:
schema: URL = field(
default=URL("https://cdn.00dani.me/m/schemata/mpd-now-playable/config-v1.json"),
metadata=alias("$schema"),
)
cache: Optional[URL] = optional()
mpd: MpdConfig = field(default_factory=MpdConfig)

View file

@ -1,28 +0,0 @@
from json import dump
from pathlib import Path
from pprint import pp
from typing import Any, Mapping
from apischema.json_schema import JsonSchemaVersion, deserialization_schema
from .model import Config
def generate() -> Mapping[str, Any]:
return deserialization_schema(Config, version=JsonSchemaVersion.DRAFT_7)
def write() -> None:
schema = dict(generate())
schema["$id"] = Config.schema.human_repr()
schema_file = Path(__file__).parent / Config.schema.name
print(f"Writing this schema to {schema_file}")
pp(schema)
with open(schema_file, "w") as fp:
dump(schema, fp, indent="\t", sort_keys=True)
fp.write("\n")
if __name__ == "__main__":
write()

View file

@ -2,8 +2,6 @@ from __future__ import annotations
from typing import TypedDict
from yarl import URL
from ..async_tools import run_background_task
from ..cache import Cache, make_cache
from .types import CurrentSongResponse, MpdStateHandler
@ -25,15 +23,12 @@ def calc_track_key(song: CurrentSongResponse) -> str:
return song["file"]
MEMORY = URL("memory://")
class MpdArtworkCache:
mpd: MpdStateHandler
album_cache: Cache[ArtCacheEntry]
track_cache: Cache[ArtCacheEntry]
def __init__(self, mpd: MpdStateHandler, cache_url: URL = MEMORY):
def __init__(self, mpd: MpdStateHandler, cache_url: str = "memory://"):
self.mpd = mpd
self.album_cache = make_cache(cache_url, "album")
self.track_cache = make_cache(cache_url, "track")

View file

@ -4,9 +4,7 @@ from uuid import UUID
from mpd.asyncio import MPDClient
from mpd.base import CommandError
from yarl import URL
from ..config.model import MpdConfig
from ..player import Player
from ..song import PlaybackState, Song, SongListener
from ..type_tools import convert_if_exists
@ -46,18 +44,20 @@ class MpdStateListener(Player):
art_cache: MpdArtworkCache
idle_count = 0
def __init__(self, cache: URL | None = None) -> None:
def __init__(self, cache: str | None = None) -> None:
self.client = MPDClient()
self.art_cache = (
MpdArtworkCache(self, cache) if cache else MpdArtworkCache(self)
)
async def start(self, conf: MpdConfig) -> None:
print(f"Connecting to MPD server {conf.host}:{conf.port}...")
await self.client.connect(conf.host, conf.port)
if conf.password is not None:
async def start(
self, host: str = "localhost", port: int = 6600, password: str | None = None
) -> None:
print(f"Connecting to MPD server {host}:{port}...")
await self.client.connect(host, port)
if password is not None:
print("Authorising to MPD with your password...")
await self.client.password(conf.password)
await self.client.password(password)
print(f"Connected to MPD v{self.client.mpd_version}")
async def refresh(self) -> None: