Compare commits

..

10 Commits

Author SHA1 Message Date
347c87a154 fix date 2025-01-15 19:05:55 +01:00
9128e8ce87 add CPU temp to standby display 2025-01-13 23:47:46 +01:00
a9e3bfcf98 playlist fix 2025-01-12 04:08:05 +01:00
e3a1680c90 added systemd daemon file 2025-01-12 02:55:10 +01:00
7100dcea8b small layout update 2025-01-11 19:30:45 +01:00
a9ea1e4d2a update config 2025-01-11 19:29:02 +01:00
5bcaa84bfb update layout 2025-01-11 19:16:12 +01:00
3cc831ba72 update color scheme config & layout 2025-01-11 19:08:52 +01:00
0627a480f3 update layout 2025-01-11 19:04:17 +01:00
9765756d7b fix bar length on song switch 2025-01-11 18:57:23 +01:00
5 changed files with 64 additions and 31 deletions

14
spotiplayer.service Normal file
View File

@ -0,0 +1,14 @@
[Unit]
Description=Spotiplayer
After=network.target
[Service]
Type=simple
WorkingDirectory=/path/to/this/repository
ExecStart=/usr/bin/python3 -m spotiplayer_pi.main
Restart=on-failure
User=root
[Install]
WantedBy=multi-user.target

View File

@ -39,7 +39,7 @@ class Api:
return self._format_req(req.json())
def _format_req(self, r):
if not r["is_playing"]:
if not r["is_playing"] or r["currently_playing_type"] != "track":
return "not-playing"
item, album = r["item"], r["item"]["album"]
res = {

View File

@ -1,12 +1,11 @@
refresh_token: "AQBGNOL-iocPZ_zxtr_sNXx4BZRaxPmg2Ea0cJGorcEu2IW2wSnLdkYDJpVDOuQQHWIQ-LjuNpBcY9PurPtdfPoT5ljXnGpso9CqX6n2alBXaYc767oKya_52qxqWPE0o7k"
base_64: "ZTI5Mzg3NWI3YWQ5NDQzZDg1NDMxYzkwOTEyZTdiMWQ6MjlmNDEzZTJiOTRlNGU0NDlkOWRiYmU0NmM2OTY5MTY="
api_interval: 5 # (float) number of seconds in-between API requests
api_interval: 3 # (float) number of seconds in-between API requests
refresh_interval: 0.4 # (float) number of seconds in-between progress bar refreshes
# Set Color Theme
color_theme:
text: [253, 238, 216] # [R, G, B] All text components
bar_outline: [16, 81, 86] # [R, G, B] Bar in-fill
bar_inside: [148, 191, 136] # [R, G, B] Bar in-fill
text: [253, 238, 216] # [R, G, B] All text components and bar outline
bar_inside: [30, 215, 96] # [R, G, B] Bar in-fill
background: [13, 19, 33] # [R, G, B] Background

View File

@ -7,11 +7,28 @@ import warnings
from datetime import datetime
import yaml
from typing import Dict
import subprocess
from spotiplayer_pi.lib import LCD_2inch
from spotiplayer_pi.api import Api
def get_cpu_temp():
try:
result = subprocess.run(
["vcgencmd", "measure_temp"], capture_output=True, text=True, check=True
)
temp_str = result.stdout.strip()
temp_value = temp_str.split("=")[1].replace("'C", "")
return float(temp_value)
except subprocess.CalledProcessError as e:
warnings.warn(f"Error executing vcgencmd: {e}")
return "None"
except (IndexError, ValueError) as e:
warnings.warn(f"Error parsing temperature: {e}")
return "None"
def parse_config(path="spotiplayer_pi/config.yaml"):
with open(path, "r") as file:
data = yaml.safe_load(file)
@ -28,7 +45,7 @@ def display_loop(api: Api, cfg: Dict):
bg = Image.new("RGB", (d.height, d.width), (0, 0, 0))
d.ShowImage(bg)
Font0 = ImageFont.truetype("Font/GothamMedium.ttf", 13)
Font0 = ImageFont.truetype("Font/GothamBold.ttf", 14)
Font1 = ImageFont.truetype("Font/GothamMedium.ttf", 18)
Font1b = ImageFont.truetype("Font/GothamBold.ttf", 19)
Font2 = ImageFont.truetype("Font/GothamMedium.ttf", 20)
@ -52,7 +69,6 @@ def display_loop(api: Api, cfg: Dict):
"Connect to speakers",
font=Font2,
fill=(255, 255, 255),
# fill=cfg["color_theme"]["text"],
)
del spoti_logo, qr, draw
@ -78,22 +94,26 @@ def display_loop(api: Api, cfg: Dict):
elif data == "not-playing":
draw = ImageDraw.Draw(not_playing_img)
current_time = datetime.now().time()
draw.rectangle([(00, 120), (119, 170)], fill=(0, 0, 0))
current_time = datetime.now()
draw.rectangle([(00, 120), (119, 190)], fill=(0, 0, 0))
offset = 10 if current_time.hour < 9 else 0
draw.text(
(10 + offset, 120),
f"{current_time.hour}:{current_time.minute:02d}",
font=Font3,
fill=(255, 255, 255),
# fill=cfg["color_theme"]["text"],
)
draw.text(
(20, 152),
(25, 152),
current_time.strftime("%a %d"),
font=Font2,
fill=(255, 255, 255),
# fill=cfg["color_theme"]["text"],
)
draw.text(
(20, 175),
f"CPU: {get_cpu_temp():.2f}°",
font=Font0,
fill=(255, 255, 255),
)
if current_mode != 0:
current_mode = 0
@ -105,7 +125,7 @@ def display_loop(api: Api, cfg: Dict):
current_mode = 1
current_track = data["track"] + data["artists"][0] + data["album"]
if current_track != last_track:
print("updating track")
print(f"Updating track to : {data['track']} - {data['artists'][0]}")
last_track = current_track
img = None
try:
@ -124,7 +144,7 @@ def display_loop(api: Api, cfg: Dict):
bg.paste(img, (10, 30))
draw = ImageDraw.Draw(bg)
draw.text(
(145, 33),
(145, 34),
"\n".join(textwrap.wrap(", ".join(data["artists"]), width=16)),
font=Font1,
fill=cfg["color_theme"]["text"],
@ -137,41 +157,41 @@ def display_loop(api: Api, cfg: Dict):
)
w, h = bg.size
w -= 95
w -= 90
h += 4
progress_time = min(
data["duration_ms"],
data["progress_ms"] + int((time.time() - last_api_call) * 1000),
)
progress = min(1, progress_time / data["duration_ms"])
bar_width = int(w * progress)
bar_width = int((w - 10) * progress)
draw.rectangle(
[(7, h - 23), (w + 3, h - 7)],
# outline=cfg["color_theme"]["text"],
outline=cfg["color_theme"]["bar_outline"],
[(9, h - 23), (w + 3, h - 7)],
outline=cfg["color_theme"]["text"],
)
draw.rectangle(
[(10, h - 22), (w + 2, h - 8)],
outline=cfg["color_theme"]["text"],
)
draw.rectangle(
[(8, h - 22), (w + 2, h - 8)],
# outline=cfg["color_theme"]["text"],
outline=cfg["color_theme"]["bar_outline"],
[(12, h - 20), (w, h - 10)], fill=cfg["color_theme"]["background"]
)
draw.rectangle(
[(10, h - 20), (w, h - 10)], fill=cfg["color_theme"]["background"]
)
draw.rectangle(
[(10, h - 20), (bar_width, h - 10)],
[(12, h - 20), (12 + bar_width, h - 10)],
fill=cfg["color_theme"]["bar_inside"],
)
f_current_time = "{:02.0f}:{:02.0f}".format(
f_current_time = "{}:{:02.0f}".format(
*divmod(progress_time // 1000, 60)
)
f_total_time = "{:02d}:{:02d}".format(
f_total_time = "{}:{:02d}".format(
*divmod(data["duration_ms"] // 1000, 60)
)
draw.rectangle(
[(231, 215), (320, 235)], fill=cfg["color_theme"]["background"]
[(237, 218), (320, 238)], fill=cfg["color_theme"]["background"]
)
draw.text(
(232, 220),
(238, 223),
f"{f_current_time}/{f_total_time}",
font=Font0,
fill=cfg["color_theme"]["text"],

View File

@ -19,7 +19,7 @@ class TestApp(unittest.TestCase):
# Check color_theme structure
color_theme = self.cfg["color_theme"]
self.assertIsInstance(color_theme, dict)
for key in ["text", "bar_outline", "bar_inside", "background"]:
for key in ["text", "bar_inside", "background"]:
self.assertIn(key, color_theme)
self.assertIsInstance(color_theme[key], tuple)
self.assertEqual(len(color_theme[key]), 3)