format
This commit is contained in:
parent
f32f606e56
commit
0bc8f50443
@ -3,7 +3,7 @@ repos:
|
|||||||
rev: v0.9.0 # Use the desired version of ruff
|
rev: v0.9.0 # Use the desired version of ruff
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
files: spotiplayer_pi/
|
args: ["--ignore=E711,E721"]
|
||||||
# args: ["--fix"] # Automatically apply fixes where possible
|
# args: ["--fix"] # Automatically apply fixes where possible
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
files: spotiplayer_pi/
|
args: ["--ignore=E711,E721"]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import requests
|
import requests
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
class Api:
|
class Api:
|
||||||
def __init__(self, refresh_token: str, base_64: str):
|
def __init__(self, refresh_token: str, base_64: str):
|
||||||
@ -13,11 +15,13 @@ class Api:
|
|||||||
"grant_type": "refresh_token",
|
"grant_type": "refresh_token",
|
||||||
"refresh_token": self.refresh_token,
|
"refresh_token": self.refresh_token,
|
||||||
}
|
}
|
||||||
req = requests.post(uri, data=data, headers={"Authorization": "Basic " + self.base_64}).json()
|
req = requests.post(
|
||||||
|
uri, data=data, headers={"Authorization": "Basic " + self.base_64}
|
||||||
|
).json()
|
||||||
self.access_token = req["access_token"]
|
self.access_token = req["access_token"]
|
||||||
self.header = {"Authorization": f"Bearer {self.access_token}"}
|
self.header = {"Authorization": f"Bearer {self.access_token}"}
|
||||||
return req["expires_in"]
|
return req["expires_in"]
|
||||||
|
|
||||||
def getPlaying(self):
|
def getPlaying(self):
|
||||||
url = "https://api.spotify.com/v1/me/player/currently-playing"
|
url = "https://api.spotify.com/v1/me/player/currently-playing"
|
||||||
req = requests.get(url, headers=self.header)
|
req = requests.get(url, headers=self.header)
|
||||||
@ -42,8 +46,7 @@ class Api:
|
|||||||
if img_urls:
|
if img_urls:
|
||||||
res["img_url"] = img_urls.pop()["url"]
|
res["img_url"] = img_urls.pop()["url"]
|
||||||
else:
|
else:
|
||||||
warnings.warn(f"{res['track']} - {res['artists']}\nAlbum art can't be found\n{img_urls}")
|
warnings.warn(
|
||||||
|
f"{res['track']} - {res['artists']}\nAlbum art can't be found\n{img_urls}"
|
||||||
|
)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,31 +27,40 @@
|
|||||||
# THE SOFTWARE.
|
# THE SOFTWARE.
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
import spidev
|
import spidev
|
||||||
import logging
|
import logging
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class RaspberryPi:
|
class RaspberryPi:
|
||||||
def __init__(self,spi_freq=40000000,rst=27,dc=25,bl=18,bl_freq=1000,i2c=None,i2c_freq=100000):
|
def __init__(
|
||||||
|
self,
|
||||||
|
spi_freq=40000000,
|
||||||
|
rst=27,
|
||||||
|
dc=25,
|
||||||
|
bl=18,
|
||||||
|
bl_freq=1000,
|
||||||
|
i2c=None,
|
||||||
|
i2c_freq=100000,
|
||||||
|
):
|
||||||
import RPi.GPIO
|
import RPi.GPIO
|
||||||
|
|
||||||
self.np = np
|
self.np = np
|
||||||
self.RST_PIN= rst
|
self.RST_PIN = rst
|
||||||
self.DC_PIN = dc
|
self.DC_PIN = dc
|
||||||
self.BL_PIN = bl
|
self.BL_PIN = bl
|
||||||
self.SPEED =spi_freq
|
self.SPEED = spi_freq
|
||||||
self.BL_freq=bl_freq
|
self.BL_freq = bl_freq
|
||||||
self.GPIO = RPi.GPIO
|
self.GPIO = RPi.GPIO
|
||||||
#self.GPIO.cleanup()
|
# self.GPIO.cleanup()
|
||||||
self.GPIO.setmode(self.GPIO.BCM)
|
self.GPIO.setmode(self.GPIO.BCM)
|
||||||
self.GPIO.setwarnings(False)
|
self.GPIO.setwarnings(False)
|
||||||
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
|
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
|
||||||
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
|
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
|
||||||
self.GPIO.setup(self.BL_PIN, self.GPIO.OUT)
|
self.GPIO.setup(self.BL_PIN, self.GPIO.OUT)
|
||||||
self.GPIO.output(self.BL_PIN, self.GPIO.HIGH)
|
self.GPIO.output(self.BL_PIN, self.GPIO.HIGH)
|
||||||
#Initialize SPI
|
# Initialize SPI
|
||||||
self.SPI = spidev.SpiDev()
|
self.SPI = spidev.SpiDev()
|
||||||
self.SPI.open(0, 0)
|
self.SPI.open(0, 0)
|
||||||
self.SPI.max_speed_hz = spi_freq
|
self.SPI.max_speed_hz = spi_freq
|
||||||
@ -67,28 +76,29 @@ class RaspberryPi:
|
|||||||
time.sleep(delaytime / 1000.0)
|
time.sleep(delaytime / 1000.0)
|
||||||
|
|
||||||
def spi_writebyte(self, data):
|
def spi_writebyte(self, data):
|
||||||
if self.SPI!=None :
|
if self.SPI != None:
|
||||||
self.SPI.writebytes(data)
|
self.SPI.writebytes(data)
|
||||||
|
|
||||||
def bl_DutyCycle(self, duty):
|
def bl_DutyCycle(self, duty):
|
||||||
self._pwm.ChangeDutyCycle(duty)
|
self._pwm.ChangeDutyCycle(duty)
|
||||||
|
|
||||||
def bl_Frequency(self,freq):
|
def bl_Frequency(self, freq):
|
||||||
self._pwm.ChangeFrequency(freq)
|
self._pwm.ChangeFrequency(freq)
|
||||||
|
|
||||||
def module_init(self):
|
def module_init(self):
|
||||||
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
|
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
|
||||||
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
|
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
|
||||||
self.GPIO.setup(self.BL_PIN, self.GPIO.OUT)
|
self.GPIO.setup(self.BL_PIN, self.GPIO.OUT)
|
||||||
self._pwm=self.GPIO.PWM(self.BL_PIN,self.BL_freq)
|
self._pwm = self.GPIO.PWM(self.BL_PIN, self.BL_freq)
|
||||||
self._pwm.start(100)
|
self._pwm.start(100)
|
||||||
if self.SPI!=None :
|
if self.SPI != None:
|
||||||
self.SPI.max_speed_hz = self.SPEED
|
self.SPI.max_speed_hz = self.SPEED
|
||||||
self.SPI.mode = 0b00
|
self.SPI.mode = 0b00
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def module_exit(self):
|
def module_exit(self):
|
||||||
logging.debug("spi end")
|
logging.debug("spi end")
|
||||||
if self.SPI!=None :
|
if self.SPI != None:
|
||||||
self.SPI.close()
|
self.SPI.close()
|
||||||
|
|
||||||
logging.debug("gpio cleanup...")
|
logging.debug("gpio cleanup...")
|
||||||
@ -97,15 +107,15 @@ class RaspberryPi:
|
|||||||
self._pwm.stop()
|
self._pwm.stop()
|
||||||
time.sleep(0.001)
|
time.sleep(0.001)
|
||||||
self.GPIO.output(self.BL_PIN, 1)
|
self.GPIO.output(self.BL_PIN, 1)
|
||||||
#self.GPIO.cleanup()
|
# self.GPIO.cleanup()
|
||||||
|
|
||||||
|
|
||||||
'''
|
"""
|
||||||
if os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):
|
if os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):
|
||||||
implementation = RaspberryPi()
|
implementation = RaspberryPi()
|
||||||
|
|
||||||
for func in [x for x in dir(implementation) if not x.startswith('_')]:
|
for func in [x for x in dir(implementation) if not x.startswith('_')]:
|
||||||
setattr(sys.modules[__name__], func, getattr(implementation, func))
|
setattr(sys.modules[__name__], func, getattr(implementation, func))
|
||||||
'''
|
"""
|
||||||
|
|
||||||
### END OF FILE ###
|
### END OF FILE ###
|
||||||
|
@ -3,9 +3,9 @@ import lcdconfig
|
|||||||
|
|
||||||
|
|
||||||
class LCD_2inch(lcdconfig.RaspberryPi):
|
class LCD_2inch(lcdconfig.RaspberryPi):
|
||||||
|
|
||||||
width = 240
|
width = 240
|
||||||
height = 320
|
height = 320
|
||||||
|
|
||||||
def command(self, cmd):
|
def command(self, cmd):
|
||||||
self.digital_write(self.DC_PIN, self.GPIO.LOW)
|
self.digital_write(self.DC_PIN, self.GPIO.LOW)
|
||||||
self.spi_writebyte([cmd])
|
self.spi_writebyte([cmd])
|
||||||
@ -13,13 +13,14 @@ class LCD_2inch(lcdconfig.RaspberryPi):
|
|||||||
def data(self, val):
|
def data(self, val):
|
||||||
self.digital_write(self.DC_PIN, self.GPIO.HIGH)
|
self.digital_write(self.DC_PIN, self.GPIO.HIGH)
|
||||||
self.spi_writebyte([val])
|
self.spi_writebyte([val])
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
"""Reset the display"""
|
"""Reset the display"""
|
||||||
self.GPIO.output(self.RST_PIN,self.GPIO.HIGH)
|
self.GPIO.output(self.RST_PIN, self.GPIO.HIGH)
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
self.GPIO.output(self.RST_PIN,self.GPIO.LOW)
|
self.GPIO.output(self.RST_PIN, self.GPIO.LOW)
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
self.GPIO.output(self.RST_PIN,self.GPIO.HIGH)
|
self.GPIO.output(self.RST_PIN, self.GPIO.HIGH)
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
def Init(self):
|
def Init(self):
|
||||||
@ -116,63 +117,74 @@ class LCD_2inch(lcdconfig.RaspberryPi):
|
|||||||
|
|
||||||
self.command(0x29)
|
self.command(0x29)
|
||||||
|
|
||||||
|
|
||||||
def SetWindows(self, Xstart, Ystart, Xend, Yend):
|
def SetWindows(self, Xstart, Ystart, Xend, Yend):
|
||||||
#set the X coordinates
|
# set the X coordinates
|
||||||
self.command(0x2A)
|
self.command(0x2A)
|
||||||
self.data(Xstart>>8) #Set the horizontal starting point to the high octet
|
self.data(Xstart >> 8) # Set the horizontal starting point to the high octet
|
||||||
self.data(Xstart & 0xff) #Set the horizontal starting point to the low octet
|
self.data(Xstart & 0xFF) # Set the horizontal starting point to the low octet
|
||||||
self.data(Xend>>8) #Set the horizontal end to the high octet
|
self.data(Xend >> 8) # Set the horizontal end to the high octet
|
||||||
self.data((Xend - 1) & 0xff)#Set the horizontal end to the low octet
|
self.data((Xend - 1) & 0xFF) # Set the horizontal end to the low octet
|
||||||
|
|
||||||
#set the Y coordinates
|
# set the Y coordinates
|
||||||
self.command(0x2B)
|
self.command(0x2B)
|
||||||
self.data(Ystart>>8)
|
self.data(Ystart >> 8)
|
||||||
self.data((Ystart & 0xff))
|
self.data((Ystart & 0xFF))
|
||||||
self.data(Yend>>8)
|
self.data(Yend >> 8)
|
||||||
self.data((Yend - 1) & 0xff )
|
self.data((Yend - 1) & 0xFF)
|
||||||
|
|
||||||
self.command(0x2C)
|
self.command(0x2C)
|
||||||
|
|
||||||
def ShowImage(self,Image,Xstart=0,Ystart=0):
|
def ShowImage(self, Image, Xstart=0, Ystart=0):
|
||||||
"""Set buffer to value of Python Imaging Library image."""
|
"""Set buffer to value of Python Imaging Library image."""
|
||||||
"""Write display buffer to physical display"""
|
"""Write display buffer to physical display"""
|
||||||
imwidth, imheight = Image.size
|
imwidth, imheight = Image.size
|
||||||
if imwidth == self.height and imheight == self.width:
|
if imwidth == self.height and imheight == self.width:
|
||||||
img = self.np.asarray(Image)
|
img = self.np.asarray(Image)
|
||||||
pix = self.np.zeros((self.width, self.height,2), dtype = self.np.uint8)
|
pix = self.np.zeros((self.width, self.height, 2), dtype=self.np.uint8)
|
||||||
#RGB888 >> RGB565
|
# RGB888 >> RGB565
|
||||||
pix[...,[0]] = self.np.add(self.np.bitwise_and(img[...,[0]],0xF8),self.np.right_shift(img[...,[1]],5))
|
pix[..., [0]] = self.np.add(
|
||||||
pix[...,[1]] = self.np.add(self.np.bitwise_and(self.np.left_shift(img[...,[1]],3),0xE0), self.np.right_shift(img[...,[2]],3))
|
self.np.bitwise_and(img[..., [0]], 0xF8),
|
||||||
|
self.np.right_shift(img[..., [1]], 5),
|
||||||
|
)
|
||||||
|
pix[..., [1]] = self.np.add(
|
||||||
|
self.np.bitwise_and(self.np.left_shift(img[..., [1]], 3), 0xE0),
|
||||||
|
self.np.right_shift(img[..., [2]], 3),
|
||||||
|
)
|
||||||
pix = pix.flatten().tolist()
|
pix = pix.flatten().tolist()
|
||||||
|
|
||||||
self.command(0x36)
|
self.command(0x36)
|
||||||
self.data(0x70)
|
self.data(0x70)
|
||||||
self.SetWindows ( 0, 0, self.height,self.width)
|
self.SetWindows(0, 0, self.height, self.width)
|
||||||
self.digital_write(self.DC_PIN,self.GPIO.HIGH)
|
self.digital_write(self.DC_PIN, self.GPIO.HIGH)
|
||||||
for i in range(0,len(pix),4096):
|
for i in range(0, len(pix), 4096):
|
||||||
self.spi_writebyte(pix[i:i+4096])
|
self.spi_writebyte(pix[i : i + 4096])
|
||||||
|
|
||||||
else :
|
else:
|
||||||
img = self.np.asarray(Image)
|
img = self.np.asarray(Image)
|
||||||
pix = self.np.zeros((imheight,imwidth , 2), dtype = self.np.uint8)
|
pix = self.np.zeros((imheight, imwidth, 2), dtype=self.np.uint8)
|
||||||
|
|
||||||
pix[...,[0]] = self.np.add(self.np.bitwise_and(img[...,[0]],0xF8),self.np.right_shift(img[...,[1]],5))
|
pix[..., [0]] = self.np.add(
|
||||||
pix[...,[1]] = self.np.add(self.np.bitwise_and(self.np.left_shift(img[...,[1]],3),0xE0), self.np.right_shift(img[...,[2]],3))
|
self.np.bitwise_and(img[..., [0]], 0xF8),
|
||||||
|
self.np.right_shift(img[..., [1]], 5),
|
||||||
|
)
|
||||||
|
pix[..., [1]] = self.np.add(
|
||||||
|
self.np.bitwise_and(self.np.left_shift(img[..., [1]], 3), 0xE0),
|
||||||
|
self.np.right_shift(img[..., [2]], 3),
|
||||||
|
)
|
||||||
|
|
||||||
pix = pix.flatten().tolist()
|
pix = pix.flatten().tolist()
|
||||||
|
|
||||||
self.command(0x36)
|
self.command(0x36)
|
||||||
self.data(0x00)
|
self.data(0x00)
|
||||||
self.SetWindows ( 0, 0, self.width, self.height)
|
self.SetWindows(0, 0, self.width, self.height)
|
||||||
self.digital_write(self.DC_PIN,self.GPIO.HIGH)
|
self.digital_write(self.DC_PIN, self.GPIO.HIGH)
|
||||||
for i in range(0,len(pix),4096):
|
for i in range(0, len(pix), 4096):
|
||||||
self.spi_writebyte(pix[i:i+4096])
|
self.spi_writebyte(pix[i : i + 4096])
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""Clear contents of image buffer"""
|
"""Clear contents of image buffer"""
|
||||||
_buffer = [0xff]*(self.width * self.height * 2)
|
_buffer = [0xFF] * (self.width * self.height * 2)
|
||||||
self.SetWindows ( 0, 0, self.height, self.width)
|
self.SetWindows(0, 0, self.height, self.width)
|
||||||
self.digital_write(self.DC_PIN,self.GPIO.HIGH)
|
self.digital_write(self.DC_PIN, self.GPIO.HIGH)
|
||||||
for i in range(0,len(_buffer),4096):
|
for i in range(0, len(_buffer), 4096):
|
||||||
self.spi_writebyte(_buffer[i:i+4096])
|
self.spi_writebyte(_buffer[i : i + 4096])
|
||||||
|
@ -27,7 +27,7 @@ def display_loop(api: Api, cfg: Dict):
|
|||||||
d.clear()
|
d.clear()
|
||||||
bg = Image.new("RGB", (d.height, d.width), (0, 0, 0))
|
bg = Image.new("RGB", (d.height, d.width), (0, 0, 0))
|
||||||
d.ShowImage(bg)
|
d.ShowImage(bg)
|
||||||
|
|
||||||
Font0 = ImageFont.truetype("Font/Font00.ttf", 14)
|
Font0 = ImageFont.truetype("Font/Font00.ttf", 14)
|
||||||
Font1 = ImageFont.truetype("Font/Font00.ttf", 18)
|
Font1 = ImageFont.truetype("Font/Font00.ttf", 18)
|
||||||
Font2 = ImageFont.truetype("Font/Font00.ttf", 36)
|
Font2 = ImageFont.truetype("Font/Font00.ttf", 36)
|
||||||
@ -45,7 +45,12 @@ def display_loop(api: Api, cfg: Dict):
|
|||||||
not_playing_img.paste(spoti_logo, (0, 10))
|
not_playing_img.paste(spoti_logo, (0, 10))
|
||||||
not_playing_img.paste(qr, (120, 40))
|
not_playing_img.paste(qr, (120, 40))
|
||||||
draw = ImageDraw.Draw(not_playing_img)
|
draw = ImageDraw.Draw(not_playing_img)
|
||||||
draw.text((124, 10), "Connect to speakers", font=Font1, fill=cfg["color_theme"]["text"])
|
draw.text(
|
||||||
|
(124, 10),
|
||||||
|
"Connect to speakers",
|
||||||
|
font=Font1,
|
||||||
|
fill=cfg["color_theme"]["text"],
|
||||||
|
)
|
||||||
del spoti_logo, qr, draw
|
del spoti_logo, qr, draw
|
||||||
|
|
||||||
last_api_call = 0
|
last_api_call = 0
|
||||||
@ -59,12 +64,12 @@ def display_loop(api: Api, cfg: Dict):
|
|||||||
if time.time() - last_auth_refresh >= auth_interval:
|
if time.time() - last_auth_refresh >= auth_interval:
|
||||||
auth_interval = api.refreshAuth() - 120
|
auth_interval = api.refreshAuth() - 120
|
||||||
last_auth_refresh = time.time()
|
last_auth_refresh = time.time()
|
||||||
print(f'Refreshed auth at {datetime.now().strftime("%d-%m %H:%M:%S")}')
|
print(f"Refreshed auth at {datetime.now().strftime('%d-%m %H:%M:%S')}")
|
||||||
|
|
||||||
if time.time() - last_api_call >= cfg["api_interval"]:
|
if time.time() - last_api_call >= cfg["api_interval"]:
|
||||||
data = api.getPlaying()
|
data = api.getPlaying()
|
||||||
last_api_call = time.time()
|
last_api_call = time.time()
|
||||||
|
|
||||||
if data == None:
|
if data == None:
|
||||||
warnings.warn("No data found")
|
warnings.warn("No data found")
|
||||||
d.ShowImage(error_img)
|
d.ShowImage(error_img)
|
||||||
@ -73,45 +78,85 @@ def display_loop(api: Api, cfg: Dict):
|
|||||||
draw = ImageDraw.Draw(not_playing_img)
|
draw = ImageDraw.Draw(not_playing_img)
|
||||||
current_time = datetime.now().time()
|
current_time = datetime.now().time()
|
||||||
draw.rectangle([(00, 120), (119, 170)], fill=(0, 0, 0))
|
draw.rectangle([(00, 120), (119, 170)], fill=(0, 0, 0))
|
||||||
draw.text((20, 120), f"{current_time.hour}:{current_time.minute:02d}", font=Font2, angle=0)
|
draw.text(
|
||||||
|
(20, 120),
|
||||||
|
f"{current_time.hour}:{current_time.minute:02d}",
|
||||||
|
font=Font2,
|
||||||
|
angle=0,
|
||||||
|
)
|
||||||
if current_mode != 0:
|
if current_mode != 0:
|
||||||
current_mode = 0
|
current_mode = 0
|
||||||
print("Standby mode")
|
print("Standby mode")
|
||||||
d.ShowImage(not_playing_img)
|
d.ShowImage(not_playing_img)
|
||||||
time.sleep(cfg["api_interval"])
|
time.sleep(cfg["api_interval"])
|
||||||
|
|
||||||
elif type(data) == dict:
|
elif type(data) == dict:
|
||||||
current_track = data["track"] + data["artists"][0] + data["album"]
|
current_track = data["track"] + data["artists"][0] + data["album"]
|
||||||
if current_track != last_track:
|
if current_track != last_track:
|
||||||
print('updating track')
|
print("updating track")
|
||||||
last_track = current_track
|
last_track = current_track
|
||||||
img = None
|
img = None
|
||||||
try:
|
try:
|
||||||
img = requests.get(data["img_url"], timeout=cfg["refresh_interval"]/2)
|
img = requests.get(
|
||||||
|
data["img_url"], timeout=cfg["refresh_interval"] / 2
|
||||||
|
)
|
||||||
img = Image.open(BytesIO(img.content))
|
img = Image.open(BytesIO(img.content))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
warnings.warn(f"Failed to fetch album cover at: {data['img_url']}\n{e}")
|
warnings.warn(
|
||||||
|
f"Failed to fetch album cover at: {data['img_url']}\n{e}"
|
||||||
|
)
|
||||||
if img == None:
|
if img == None:
|
||||||
img = unavailable_img
|
img = unavailable_img
|
||||||
img = img.resize((128, 128))
|
img = img.resize((128, 128))
|
||||||
bg = Image.new("RGB", (320, 240), cfg["color_theme"]["background"])
|
bg = Image.new("RGB", (320, 240), cfg["color_theme"]["background"])
|
||||||
bg.paste(img, (10, 30))
|
bg.paste(img, (10, 30))
|
||||||
draw = ImageDraw.Draw(bg)
|
draw = ImageDraw.Draw(bg)
|
||||||
draw.text((150, 40), "\n".join(textwrap.wrap(", ".join(data["artists"]), width=16)), font=Font1, fill=cfg["color_theme"]["text"])
|
draw.text(
|
||||||
draw.text((10, 160), "\n".join(textwrap.wrap(data["track"], width=32)), font=Font1, fill=cfg["color_theme"]["text"])
|
(150, 40),
|
||||||
|
"\n".join(textwrap.wrap(", ".join(data["artists"]), width=16)),
|
||||||
|
font=Font1,
|
||||||
|
fill=cfg["color_theme"]["text"],
|
||||||
|
)
|
||||||
|
draw.text(
|
||||||
|
(10, 160),
|
||||||
|
"\n".join(textwrap.wrap(data["track"], width=32)),
|
||||||
|
font=Font1,
|
||||||
|
fill=cfg["color_theme"]["text"],
|
||||||
|
)
|
||||||
|
|
||||||
w, h = bg.size
|
w, h = bg.size
|
||||||
w -= 92
|
w -= 92
|
||||||
progress_time = data["progress_ms"] + int((time.time() - last_api_call) * 1000)
|
progress_time = data["progress_ms"] + int(
|
||||||
progress= progress_time / data["duration_ms"]
|
(time.time() - last_api_call) * 1000
|
||||||
|
)
|
||||||
|
progress = progress_time / data["duration_ms"]
|
||||||
bar_width = int(w * progress)
|
bar_width = int(w * progress)
|
||||||
draw.rectangle([(8, h - 22), (w + 2, h - 8)], outline=cfg["color_theme"]["bar_outline"])
|
draw.rectangle(
|
||||||
draw.rectangle([(10, h - 20), (w, h - 10)], fill=cfg["color_theme"]["background"])
|
[(8, h - 22), (w + 2, h - 8)],
|
||||||
draw.rectangle([(10, h - 20), (bar_width, h - 10)], fill=cfg["color_theme"]["bar_inside"])
|
outline=cfg["color_theme"]["bar_outline"],
|
||||||
f_current_time = "{:02.0f}:{:02.0f}".format(*divmod(progress_time // 1000, 60))
|
)
|
||||||
f_total_time = "{:02d}:{:02d}".format(*divmod(data["duration_ms"]// 1000, 60))
|
draw.rectangle(
|
||||||
draw.rectangle([(234, 215), (310, 235)], fill=cfg["color_theme"]["background"])
|
[(10, h - 20), (w, h - 10)], fill=cfg["color_theme"]["background"]
|
||||||
draw.text((235, 215), f"{f_current_time}/{f_total_time}", font=Font0, fill=cfg["color_theme"]["text"])
|
)
|
||||||
|
draw.rectangle(
|
||||||
|
[(10, h - 20), (bar_width, h - 10)],
|
||||||
|
fill=cfg["color_theme"]["bar_inside"],
|
||||||
|
)
|
||||||
|
f_current_time = "{:02.0f}:{:02.0f}".format(
|
||||||
|
*divmod(progress_time // 1000, 60)
|
||||||
|
)
|
||||||
|
f_total_time = "{:02d}:{:02d}".format(
|
||||||
|
*divmod(data["duration_ms"] // 1000, 60)
|
||||||
|
)
|
||||||
|
draw.rectangle(
|
||||||
|
[(234, 215), (310, 235)], fill=cfg["color_theme"]["background"]
|
||||||
|
)
|
||||||
|
draw.text(
|
||||||
|
(235, 215),
|
||||||
|
f"{f_current_time}/{f_total_time}",
|
||||||
|
font=Font0,
|
||||||
|
fill=cfg["color_theme"]["text"],
|
||||||
|
)
|
||||||
d.ShowImage(bg)
|
d.ShowImage(bg)
|
||||||
time.sleep(cfg["refresh_interval"])
|
time.sleep(cfg["refresh_interval"])
|
||||||
|
|
||||||
@ -125,4 +170,3 @@ if __name__ == "__main__":
|
|||||||
cfg = parse_config()
|
cfg = parse_config()
|
||||||
api = Api(cfg["refresh_token"], cfg["base_64"])
|
api = Api(cfg["refresh_token"], cfg["base_64"])
|
||||||
display_loop(api, cfg)
|
display_loop(api, cfg)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user