mmmpd/mmmpd

121 lines
2.8 KiB
Plaintext
Raw Normal View History

2021-08-07 23:55:50 +00:00
#!/usr/bin/env python3
2021-08-08 14:44:12 +00:00
import os
2021-08-07 23:55:50 +00:00
import sys
import subprocess
2021-08-07 23:55:50 +00:00
import datetime
import time
import logging
import mpd
2021-08-07 23:55:50 +00:00
2021-08-08 14:33:14 +00:00
NAME = "Mattermost MPD now playing status"
2021-08-08 14:15:40 +00:00
VERSION = "1.0.0"
2021-08-07 23:55:50 +00:00
### Config ########
EMOJI_PAUSED = "pause_button"
EMOJI_PLAYING = "musical_note"
###################
2021-08-08 14:44:12 +00:00
MPD_HOST = os.getenv("MPD_HOST", "localhost") # Host (for TCP) or socket path
MPD_PORT = os.getenv("MPD_PORT", "6600") # Ignored when not using TCP
2021-08-07 23:55:50 +00:00
2021-08-08 14:33:14 +00:00
LOGGER = logging.getLogger("mmmpd")
2021-08-07 23:55:50 +00:00
MPD_STATE_PLAY = "play"
MPD_STATE_PAUSE = "pause"
# Mattermost stuff {{{1
# ----------------
def set_status(emoji, text, expires_datetime):
LOGGER.info(f"Custom status expiring {expires_datetime or 'never'}: :{emoji}: {text}")
subprocess.run([
"mmcli", "customstatus",
"--until", expires_datetime.isoformat() if expires_datetime else "",
"--emoji", emoji,
"--", text
], check=True)
2021-08-07 23:55:50 +00:00
def clear_status():
LOGGER.info("Clearing status")
subprocess.run(["mmcli", "customstatus"], check=True)
2021-08-07 23:55:50 +00:00
# MPD stuff {{{1
# ---------
def song_string(song_info):
artist = song_info.get("artist") or "Unknown artist"
title = song_info.get("title") or "Unknown song"
return f"{artist} {title}"
def formatted_status(mpd_client):
2021-08-07 23:55:50 +00:00
status = mpd_client.status()
state = status.get("state")
LOGGER.debug(f"Player state: {state!r}")
if state not in (MPD_STATE_PLAY, MPD_STATE_PAUSE):
return None
2021-08-07 23:55:50 +00:00
song = mpd_client.currentsong()
song_str = song_string(song)
emoji = EMOJI_PAUSED if state == MPD_STATE_PAUSE else EMOJI_PLAYING
expire = None
elapsed = status.get("elapsed")
duration = status.get("duration")
if state == MPD_STATE_PLAY and elapsed is not None and duration:
2021-08-07 23:55:50 +00:00
now = datetime.datetime.now().astimezone()
try:
# 1 second extra to allow some time to set the new song without flickering status
expire = now + datetime.timedelta(seconds=1 + float(duration) - float(elapsed))
except ValueError as e:
LOGGER.error("Could not calculate expiry time", exc_info=e)
return (emoji, song_str, expire)
2021-08-07 23:55:50 +00:00
# Driving stuff {{{1
# -------------
def set_status_from_mpd(mpd_client):
status = formatted_status(mpd_client)
if status is None:
clear_status()
else:
emoji, song_str, expire = status
set_status(emoji, song_str, expire)
2021-08-07 23:55:50 +00:00
def loop(mpd_client, on_status_change):
while True:
2021-08-07 23:55:50 +00:00
mpd_client.idle("player")
LOGGER.debug("Got event from MPD")
on_status_change(mpd_client)
time.sleep(1)
2021-08-07 23:55:50 +00:00
def main(mpd_host, mpd_port):
if "-v" in sys.argv[1:]:
logging.basicConfig(level=logging.INFO)
LOGGER.info("Log level INFO")
elif "-vv" in sys.argv[1:]:
logging.basicConfig(level=logging.DEBUG)
LOGGER.info("Log level DEBUG")
mpd_client = mpd.MPDClient()
mpd_client.connect(mpd_host, port=mpd_port)
LOGGER.info("Connected")
set_status_from_mpd(mpd_client)
try:
loop(mpd_client, set_status_from_mpd)
finally:
clear_status()
if __name__ == "__main__":
main(MPD_HOST, MPD_PORT)