Merge pull request #17 from bartkl/main

Album art fetching from HTTP server
This commit is contained in:
GuardKenzie
2021-09-09 16:51:51 +00:00
committed by GitHub
4 changed files with 112 additions and 35 deletions

View File

@ -24,19 +24,22 @@ pip install miniplayer
The config file is located at `~/.config/miniplayer/config`. The example configuration file, [`config.example`](config.example), has all the default values. You will need to create the file yourself. The config file is located at `~/.config/miniplayer/config`. The example configuration file, [`config.example`](config.example), has all the default values. You will need to create the file yourself.
#### player #### player
* ***music_directory*:** The path to your music directory for extracting album art.
* ***font_width*:** The width of your font in pixels in the actual terminal. * ***font_width*:** The width of your font in pixels in the actual terminal.
* ***font_height*:** The height of your font in pixels in the actual terminal. * ***font_height*:** The height of your font in pixels in the actual terminal.
![font-example](https://github.com/GuardKenzie/miniplayer/blob/main/img/font.png?raw=true) ![font-example](https://github.com/GuardKenzie/miniplayer/blob/main/img/font.png?raw=true)
* ***image_method*:** The method to use for drawing album art. Available values are `pixcat` and `ueberzug`
If you are not using Kitty, try `ueberzug`.
* ***volume_step*:** The ammount (in percents) the volume will be adjusted on pressing the volume up and volume down keys. * ***volume_step*:** The ammount (in percents) the volume will be adjusted on pressing the volume up and volume down keys.
* ***album_art_only*:** Whether or not to only draw the album art and no other track info (`true/false`). * ***album_art_only*:** Whether or not to only draw the album art and no other track info (`true/false`).
* ***auto_close*:** Whether or not to automatically close the player once the mpd playlist has concluded (`true/false`). * ***auto_close*:** Whether or not to automatically close the player once the mpd playlist has concluded (`true/false`).
* ***show_playlist*:** Whether or not to show the playlist view. * ***show_playlist*:** Whether or not to show the playlist view.
#### art
* ***music_directory*:** The path to your music directory for extracting album art from the files.
* ***http_base_url*:** Base URL of webserver which serves the album art for your albums (takes precedence over `music_directory`). Useful for users of Android MPD clients _MAFA_ or _MPDroid_. For more information see [the MPDroid wiki](https://github.com/abarisain/dmix/wiki/Album-Art-on-your-LAN).
* ***http_cover_filenames*:** Space separated list of filenames to use in the call to the webserver to fetch the album art.
* ***image_method*:** The method to use for drawing album art. Available values are `pixcat` and `ueberzug`
If you are not using Kitty, try `ueberzug`.
#### mpd #### mpd
* ***host*:** The mpd host * ***host*:** The mpd host
@ -80,7 +83,7 @@ These keybinds can be changed by editing the config file. See the [`config.examp
## F.A.Q. ## F.A.Q.
- **Q:** Album art is not showing up. - **Q:** Album art is not showing up.
**A:** Make sure your `music_directory` is not quoted i.e. if your music directory is `~/My Music` then your config should look like `music_directory = ~/My Music`. **A:** If you're using `music_directory` for fetching your album art, make sure your it is not quoted i.e. if your music directory is `~/My Music` then your config should look like `music_directory = ~/My Music`.
If this does not work, try changing `image_method` from `pixcat` to `ueberzug` or vice versa. If this does not work, try changing `image_method` from `pixcat` to `ueberzug` or vice versa.
- **Q:** Album art is too big/too small. - **Q:** Album art is too big/too small.

View File

@ -1,6 +1,8 @@
#!/bin/python #!/bin/python
import curses import curses
import os import os
import posixpath
import requests
from mpd import MPDClient from mpd import MPDClient
import ffmpeg import ffmpeg
import pixcat import pixcat
@ -9,21 +11,25 @@ import configparser
import ueberzug.lib.v0 as ueberzug import ueberzug.lib.v0 as ueberzug
from PIL import Image, ImageDraw from PIL import Image, ImageDraw
# Get config # Get config
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(os.path.expanduser("~/.config/miniplayer/config")) config.read(os.path.expanduser("~/.config/miniplayer/config"))
if "player" not in config.sections(): if "player" not in config.sections():
config["player"] = {"music_directory": "~/Music", config["player"] = {"font_width": 11,
"font_width": 11,
"font_height": 24, "font_height": 24,
"image_method": "pixcat",
"album_art_only": False, "album_art_only": False,
"volume_step": 5, "volume_step": 5,
"auto_close": False, "auto_close": False,
"show_playlist": True, "show_playlist": True,
} }
if "art" not in config.sections():
config["art"] = {"music_directory": "~/Music",
"image_method": "pixcat",
}
if "mpd" not in config.sections(): if "mpd" not in config.sections():
config["mpd"] = {"host": "localhost", config["mpd"] = {"host": "localhost",
"port": "6600", "port": "6600",
@ -46,6 +52,23 @@ default_bindings = {">": "next_track",
if "keybindings" not in config.sections(): if "keybindings" not in config.sections():
config["keybindings"] = default_bindings config["keybindings"] = default_bindings
# Ensure compatibility with older configs
deprecated_field_notice = ("The config option `{field}` under the `player` "
"section is deprecated and will be removed in the "
"future. Use the config option `{field}` under the "
"`art` section instead.")
deprecated_fields_present = False
for field in ["music_directory", "image_method"]:
if config.has_option("player", field):
deprecated_fields_present = True
print(deprecated_field_notice.format(field=field))
if not config.has_option("art", field):
config["art"][field] = config["player"][field]
if deprecated_fields_present:
input("(Press <Enter> to continue) ...")
# Load configured keybindings # Load configured keybindings
keybindings = config["keybindings"] keybindings = config["keybindings"]
@ -59,6 +82,7 @@ for key, action in default_bindings.items():
keybindings[key] = action keybindings[key] = action
player_config = config["player"] player_config = config["player"]
art_config = config["art"]
mpd_config = config["mpd"] mpd_config = config["mpd"]
@ -71,17 +95,13 @@ IMAGERATIO = (player_config.getint("font_width", 11),
player_config.getint("font_height", 24) player_config.getint("font_height", 24)
) )
# Music directory
MUSICDIR = player_config.get("music_directory", "~/Music")
MUSICDIR = os.path.expanduser(MUSICDIR)
# MPD config # MPD config
MPDHOST = mpd_config.get("host", "localhost") MPDHOST = mpd_config.get("host", "localhost")
MPDPORT = mpd_config.getint("port", 6600) MPDPORT = mpd_config.getint("port", 6600)
MPDPASS = mpd_config.get("pass", False) MPDPASS = mpd_config.get("pass", False)
# What to use to draw images # What to use to draw images
IMAGEMETHOD = player_config.get("image_method", "pixcat") IMAGEMETHOD = art_config.get("image_method", "pixcat")
# Volume step # Volume step
VOLUMESTEP = player_config.getint("volume_step", 5) VOLUMESTEP = player_config.getint("volume_step", 5)
@ -141,6 +161,11 @@ class Player:
self.last_song = None self.last_song = None
# Album art HTTP server
if art_config.get("http_base_url"):
self.art_http_session = requests.Session()
# Album art only flag # Album art only flag
self.album_art_only = player_config.getboolean("album_art_only", False) self.album_art_only = player_config.getboolean("album_art_only", False)
@ -314,14 +339,57 @@ class Player:
self.screen_height, self.screen_width = window_height, window_width self.screen_height, self.screen_width = window_height, window_width
def getAlbumArt(self, song_file): def getAlbumArt(self, song_file):
"""
A function that fetches the album art and saves
it to self.album_art_loc
"""
http_base_url = art_config.get("http_base_url")
if http_base_url:
self._getAlbumArtFromHttpServer(http_base_url, song_file)
else:
self._getAlbumArtFromFile(song_file)
def _getAlbumArtFromHttpServer(self, base_url, song_file):
"""
A function that fetches the album art from the configured
HTTP server, and saves it to self.album_art_loc
"""
album = os.path.dirname(song_file)
for cover_filename in art_config.get("http_cover_filenames", "cover.jpg").split():
album_art_url = posixpath.join(base_url, album, cover_filename)
try:
album_art_resp = self.art_http_session.get(album_art_url)
except requests.RequestException:
# If any exception occurs, simply give up and show default art.
self.drawDefaultAlbumArt()
break
if album_art_resp.ok:
with open(self.album_art_loc, "wb") as f:
f.write(album_art_resp.content)
break
elif album_art_resp.status_code == 404:
continue
else:
self.drawDefaultAlbumArt()
def _getAlbumArtFromFile(self, song_file):
""" """
A function that extracts the album art from song_file and A function that extracts the album art from song_file and
saves it to self.album_art_loc saves it to self.album_art_loc
""" """
music_dir = os.path.expanduser(
art_config.get("music_directory", "~/Music"))
song_file_abs = os.path.join(MUSICDIR, song_file) song_file_abs = os.path.join(music_dir, song_file)
process = ( process = (
ffmpeg ffmpeg
@ -332,6 +400,10 @@ class Player:
try: try:
process.run(quiet=True, overwrite_output=True) process.run(quiet=True, overwrite_output=True)
except ffmpeg._run.Error: except ffmpeg._run.Error:
self.drawDefaultAlbumArt()
def drawDefaultAlbumArt(self):
foregroundCol = "#D8DEE9" foregroundCol = "#D8DEE9"
backgroundCol = "#262A33" backgroundCol = "#262A33"
@ -413,8 +485,6 @@ class Player:
self.selected_song = int(song["pos"]) self.selected_song = int(song["pos"])
self.album, self.artist, self.title = self.getSongInfo(song) self.album, self.artist, self.title = self.getSongInfo(song)
self.last_song = song
self.getAlbumArt(song["file"]) self.getAlbumArt(song["file"])
self.last_song = song self.last_song = song

View File

@ -1,13 +1,16 @@
[player] [player]
music_directory = ~/Music
font_width = 11 font_width = 11
font_height = 24 font_height = 24
image_method = pixcat
volume_step = 5 volume_step = 5
auto_close = false auto_close = false
album_art_only = false album_art_only = false
show_playlist = true show_playlist = true
[art]
image_method = pixcat
music_directory = ~/Music
# http_base_url = http://localhost:6667/cover-art
# http_cover_filenames = cover.jpg cover.png folder.jpg folder.png art.jpg art.png artwork.jpg artwork.png
[mpd] [mpd]
host = localhost host = localhost

View File

@ -1,6 +1,6 @@
[metadata] [metadata]
name = miniplayer name = miniplayer
version = 1.3.2 version = 1.4.0
description = An mpd client with album art and basic functionality. description = An mpd client with album art and basic functionality.
long_description = file: README.md long_description = file: README.md
long_description_content_type = text/markdown long_description_content_type = text/markdown
@ -22,5 +22,6 @@ install_requires =
ffmpeg-python ffmpeg-python
pixcat pixcat
pillow pillow
requests
ueberzug ueberzug