commit
a7dad655df
3 changed files with 90 additions and 10 deletions
17
poetry.lock
generated
17
poetry.lock
generated
|
@ -299,6 +299,21 @@ files = [
|
|||
{file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-mpd2"
|
||||
version = "3.1.0"
|
||||
description = "A Python MPD client library"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "python-mpd2-3.1.0.tar.gz", hash = "sha256:f33c2cdb0d6baa74a36724f38c1c4a099a7ce2c8ec4a2bb7192150a5855df476"},
|
||||
{file = "python_mpd2-3.1.0-py2.py3-none-any.whl", hash = "sha256:c4d44a54e88a675f7301fdb11a1bd31165a6f51a664dd41e8137e92f7b02ebfb"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
twisted = ["Twisted"]
|
||||
|
||||
[[package]]
|
||||
name = "rpi-gpio"
|
||||
version = "0.7.1"
|
||||
|
@ -354,4 +369,4 @@ files = [
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "5f10ea01a98ffb96107cc03228a3164fc600ce76ac56ed249700e5a581083f1e"
|
||||
content-hash = "b90de4dbcb9039b01369909dd0a6cf26b2346671b8907ccbbe5bbea6a06a6182"
|
||||
|
|
|
@ -10,6 +10,7 @@ python = "^3.9"
|
|||
spidev = "^3.6"
|
||||
mfrc522 = "^0.0.7"
|
||||
pydantic = "^1.10.7"
|
||||
python-mpd2 = "^3.1.0"
|
||||
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
|
|
|
@ -14,7 +14,7 @@ from dataclasses import dataclass
|
|||
from mfrc522.SimpleMFRC522 import SimpleMFRC522
|
||||
from pydantic import BaseModel
|
||||
from random import randrange
|
||||
|
||||
from mpd import MPDClient
|
||||
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
|
@ -79,6 +79,10 @@ class Renderer(ABC):
|
|||
def is_playing(self) -> bool:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def close(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class Player:
|
||||
reader: SimpleMFRC522
|
||||
|
@ -194,7 +198,7 @@ class Player:
|
|||
status_file.write(self.current_title.status.json(indent=2))
|
||||
self.current_title = None
|
||||
|
||||
def process(self):
|
||||
def process(self) -> None:
|
||||
tag_id: Optional[int] = self.read_burst()
|
||||
|
||||
# current_tag = self.current_title.tag_id if self.current_title else None
|
||||
|
@ -219,7 +223,7 @@ class Player:
|
|||
self.advance()
|
||||
self.start_playing()
|
||||
|
||||
def tag_detected(self, tag_id: int):
|
||||
def tag_detected(self, tag_id: int) -> None:
|
||||
log.info(f"tag detected: {tag_id:x}")
|
||||
cfg = self.get_title_config(tag_id)
|
||||
if not cfg:
|
||||
|
@ -243,11 +247,14 @@ class Player:
|
|||
):
|
||||
self.start_time = time.time()
|
||||
|
||||
def tag_removed(self):
|
||||
def tag_removed(self) -> None:
|
||||
if self.current_title is not None:
|
||||
log.info(f"tag removed: {self.current_title.tag_id:x}")
|
||||
self.stop_playing()
|
||||
|
||||
def close(self) -> None:
|
||||
self.renderer.close()
|
||||
|
||||
|
||||
class DebugRenderer(Renderer):
|
||||
def __init__(self) -> None:
|
||||
|
@ -275,16 +282,73 @@ class DebugRenderer(Renderer):
|
|||
def is_playing(self) -> bool:
|
||||
return (self.start != 0) and (self.get_time() - self.offset < 10)
|
||||
|
||||
def close(self) -> None:
|
||||
log.debug("DebugRenderer: close()")
|
||||
|
||||
|
||||
class MpdRenderer(Renderer):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.mpd = MPDClient() # type:ignore
|
||||
self.mpd.timeout = 10
|
||||
self.mpd.connect("/var/run/mpd/socket")
|
||||
self.mpd.clear()
|
||||
self.mpd.single(1)
|
||||
self.mpd.consume(1)
|
||||
|
||||
# self.start: int = 0
|
||||
# self.offset: int = 0
|
||||
|
||||
def get_tracks(self, path: str) -> list[str]:
|
||||
all_files = os.listdir(path)
|
||||
return sorted([f for f in all_files if (f.endswith(".mp3") or f.endswith(".flac"))])
|
||||
|
||||
def play(self, path: str, from_time: int) -> None:
|
||||
log.info(f"MpdRenderer: play({path}, {from_time})")
|
||||
self.mpd.clear()
|
||||
self.mpd.add(f"file://{path}")
|
||||
self.mpd.play()
|
||||
if from_time != 0:
|
||||
self.mpd.seekcur(from_time)
|
||||
# self.start = int(time.time())
|
||||
# self.offset = from_time
|
||||
|
||||
def get_time(self) -> int:
|
||||
# return int(time.time()) - self.start + self.offset
|
||||
return int(float(self.mpd.status()["elapsed"]))
|
||||
|
||||
def stop(self) -> None:
|
||||
log.info("MpdRenderer: stop()")
|
||||
self.mpd.stop()
|
||||
self.mpd.clear()
|
||||
# self.start = 0
|
||||
# self.offset = 0
|
||||
|
||||
def is_playing(self) -> bool:
|
||||
return self.mpd.status()["state"] == "play"
|
||||
# return (self.start != 0) and (self.get_time() - self.offset < 10)
|
||||
|
||||
def close(self) -> None:
|
||||
self.mpd.close()
|
||||
self.mpd.disconnect()
|
||||
|
||||
|
||||
def main(media_path: str, renderer_type: str) -> None:
|
||||
if renderer_type == "dummy":
|
||||
renderer = DebugRenderer()
|
||||
elif renderer_type == "mpd":
|
||||
renderer = MpdRenderer()
|
||||
else:
|
||||
renderer = DebugRenderer()
|
||||
player = Player(media_path=media_path, renderer=renderer)
|
||||
while True:
|
||||
player.process()
|
||||
time.sleep(1)
|
||||
log.info('sleepywaves ready.')
|
||||
try:
|
||||
while True:
|
||||
player.process()
|
||||
time.sleep(1)
|
||||
finally:
|
||||
player.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -302,8 +366,8 @@ if __name__ == "__main__":
|
|||
)
|
||||
parser.add_argument(
|
||||
"--renderer",
|
||||
choices=("dummy"),
|
||||
default="dummy",
|
||||
choices=("dummy", "mpd"),
|
||||
default="mpd",
|
||||
help="media renderer to use as backend",
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue