mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-09 14:03:42 +08:00
68 lines
3.1 KiB
Python
68 lines
3.1 KiB
Python
"""The Android Auto now-playing card; both live rendering and previews use this drawing."""
|
|
import time
|
|
|
|
import pyray as rl
|
|
|
|
from openpilot.starpilot.soloist.now_playing import elapsed_ms
|
|
from openpilot.starpilot.system.starport.projection_layout import NOW_PLAYING_SIZE, NOW_PLAYING_WIDGET
|
|
from openpilot.starpilot.ui.presentation import FontRole
|
|
|
|
ACCENT = rl.Color(199, 174, 247, 255)
|
|
INK = rl.Color(15, 13, 23, 255)
|
|
TEXT = rl.Color(245, 242, 252, 255)
|
|
MUTED = rl.Color(184, 178, 200, 255)
|
|
BUTTON_R = 30
|
|
|
|
|
|
def _play_pause(center: rl.Vector2, playing: bool) -> None:
|
|
"""An accent disc with the pause bars while playing, else the play triangle."""
|
|
rl.draw_circle_v(center, BUTTON_R, ACCENT)
|
|
if playing:
|
|
for dx in (-9, 3):
|
|
rl.draw_rectangle_rounded(rl.Rectangle(center.x + dx, center.y - 12, 6, 24), .5, 4, INK)
|
|
else:
|
|
rl.draw_triangle(rl.Vector2(center.x - 7, center.y - 13), rl.Vector2(center.x - 7, center.y + 13), rl.Vector2(center.x + 13, center.y), INK)
|
|
|
|
|
|
class NowPlayingWidget:
|
|
def __init__(self, fonts, clock=time.time): # noqa: TID251 epoch-ms track anchors
|
|
self.fonts = fonts
|
|
self.clock = clock
|
|
self.track = None
|
|
|
|
def _fit(self, text, role, size, width):
|
|
measured = self.fonts.measure(text, role, size)
|
|
return size * width / measured.width if measured.width > width else size
|
|
|
|
def render(self, state):
|
|
placed = state.customization['layouts']['large'].get(NOW_PLAYING_WIDGET)
|
|
track = self.track
|
|
if not placed or not placed['enabled'] or not track or state.alert.size != 'none':
|
|
return
|
|
rect = rl.Rectangle(placed['x'], placed['y'], *NOW_PLAYING_SIZE)
|
|
h = rect.height
|
|
background = rl.Color(15, 13, 23, round(235 * placed.get('opacity', 85) / 100))
|
|
playing = track['status'] == 'playing'
|
|
if not playing and placed.get('collapse'):
|
|
# Paused: just the play button, at whichever end of the card sits nearer the screen edge.
|
|
right = rect.x + rect.width / 2 > getattr(state, 'viewport_width', 0) / 2
|
|
button = rl.Rectangle(rect.x + rect.width - h if right else rect.x, rect.y, h, h)
|
|
rl.draw_rectangle_rounded(button, 1.0, 16, background)
|
|
_play_pause(rl.Vector2(button.x + h / 2, button.y + h / 2), False)
|
|
return
|
|
rl.draw_rectangle_rounded(rect, 1.0, 16, background)
|
|
_play_pause(rl.Vector2(rect.x + h / 2, rect.y + h / 2), playing)
|
|
left = rect.x + h + 4
|
|
width = rect.x + rect.width - h / 2 - left
|
|
rows = ((track['title'], FontRole.SEMI_BOLD, 30, 12, TEXT), (track['artist'] or track['album'], FontRole.NORMAL, 22, 46, MUTED))
|
|
for text, role, size, y, color in rows:
|
|
if text:
|
|
self.fonts.draw(text, role, self._fit(text, role, size, width), left, rect.y + y, color)
|
|
duration = track.get('durationMs')
|
|
if duration and track.get('position'):
|
|
bar = rl.Rectangle(left, rect.y + h - 16, width, 4)
|
|
rl.draw_rectangle_rounded(bar, 1.0, 4, rl.Color(255, 255, 255, 50))
|
|
done = min(1.0, elapsed_ms(track, self.clock() * 1000) / duration)
|
|
if done > 0:
|
|
rl.draw_rectangle_rounded(rl.Rectangle(bar.x, bar.y, max(bar.height, bar.width * done), bar.height), 1.0, 4, ACCENT)
|