From f8df8b6b19e997ce1dd2490163d97fbf777a3820 Mon Sep 17 00:00:00 2001 From: Martin Weinelt <mweinelt@users.noreply.github.com> Date: Sat, 26 Dec 2020 22:18:28 +0100 Subject: [PATCH] Add album art support in the mpd component (#44527) * Add album art support in the mpd component Uses `readpicture` to retrieve embedded artwork and `albumart` to acquire cover art located in the media directory. As the mpd component supports multiple different implementations (think mopidy, PI MusicBox, etc.) we check for the availability of each command before using them. Tested against mpd 0.22.3, which includes support for both. * fixup! Add album art support in the mpd component --- homeassistant/components/mpd/media_player.py | 53 ++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/homeassistant/components/mpd/media_player.py b/homeassistant/components/mpd/media_player.py index 1e16675f7b6..1273b720dd8 100644 --- a/homeassistant/components/mpd/media_player.py +++ b/homeassistant/components/mpd/media_player.py @@ -1,5 +1,6 @@ """Support to interact with a Music Player Daemon.""" from datetime import timedelta +import hashlib import logging import os @@ -107,6 +108,7 @@ class MpdDevice(MediaPlayerEntity): self._muted_volume = 0 self._media_position_updated_at = None self._media_position = None + self._commands = None # set up MPD client self._client = MPDClient() @@ -163,6 +165,7 @@ class MpdDevice(MediaPlayerEntity): try: if not self._is_connected: await self._connect() + self._commands = list(await self._client.commands()) await self._fetch_status() except (mpd.ConnectionError, OSError, BrokenPipeError, ValueError) as error: @@ -252,6 +255,56 @@ class MpdDevice(MediaPlayerEntity): """Return the album of current playing media (Music track only).""" return self._currentsong.get("album") + @property + def media_image_hash(self): + """Hash value for media image.""" + file = self._currentsong.get("file") + if file: + return hashlib.sha256(file.encode("utf-8")).hexdigest()[:16] + + return None + + async def async_get_media_image(self): + """Fetch media image of current playing track.""" + file = self._currentsong.get("file") + if not file: + return None, None + + # not all MPD implementations and versions support the `albumart` and `fetchpicture` commands + can_albumart = "albumart" in self._commands + can_readpicture = "readpicture" in self._commands + + response = None + + # read artwork embedded into the media file + if can_readpicture: + try: + response = await self._client.readpicture(file) + except mpd.CommandError as error: + _LOGGER.warning( + "Retrieving artwork through `readpicture` command failed: %s", + error, + ) + + # read artwork contained in the media directory (cover.{jpg,png,tiff,bmp}) if none is embedded + if can_albumart and not response: + try: + response = await self._client.albumart(file) + except mpd.CommandError as error: + _LOGGER.warning( + "Retrieving artwork through `albumart` command failed: %s", + error, + ) + + if not response: + return None, None + + image = bytes(response.get("binary")) + mime = response.get( + "type", "image/png" + ) # readpicture has type, albumart does not + return (image, mime) + @property def volume_level(self): """Return the volume level.""" -- GitLab