refactor!: rename somafm-tui to beefy-player
The app is now a general internet-radio player rather than a SomaFM client, so the package, console script, MPRIS identity, mpv namespaces, macOS tap names, XDG directories and docs all move to beefy-player. Environment variables are now BEEFY_* (the old SOMAFM_* spellings are still honoured) and an existing ~/.config/somafm-tui/config.json is migrated on first run, so favourites and volume survive the rename. The visible interface is untouched: same layout, same logo, same keys.
This commit is contained in:
1 parent
4bed90b489
commit
e30ca09627
44 files changed
+329
-192
No files matched your search
@@ -0,0 +1,107 @@
|
||||
"""Header: logo, clock and a live ticker."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
from rich.cells import cell_len
|
||||
from rich.console import Group, RenderableType
|
||||
from rich.text import Text
|
||||
from textual.widget import Widget
|
||||
|
||||
from .common import (
|
||||
SPECTRUM_STOPS,
|
||||
clock_time,
|
||||
date_label,
|
||||
gradient,
|
||||
marquee,
|
||||
state_glyph,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..app import BeefyPlayerApp
|
||||
|
||||
LOGO = (
|
||||
"▄▀▀▀ ▄▀▀▄ █▄ ▄█ ▄▀▀▄",
|
||||
"▀▀▀▄ █ █ █ █ █ █▀▀█",
|
||||
"▄▄▄▀ ▀▄▄▀ █ █ █ █",
|
||||
)
|
||||
|
||||
MIDDLE = ("SOMA FM RADIO", "LISTENER SUPPORTED", "SAN FRANCISCO")
|
||||
|
||||
|
||||
class HeaderBar(Widget):
|
||||
can_focus = False
|
||||
|
||||
def render(self) -> RenderableType:
|
||||
app = cast("BeefyPlayerApp", self.app)
|
||||
width = max(24, self.size.width)
|
||||
height = max(1, self.size.height)
|
||||
state = app.playing_state
|
||||
glyph, colour = state_glyph(state)
|
||||
|
||||
logo_width = max(cell_len(row) for row in LOGO)
|
||||
middle_width = max(cell_len(row) for row in MIDDLE)
|
||||
right = (clock_time(), date_label(), f"vol {app.volume}%")
|
||||
right_width = max(cell_len(item) for item in right)
|
||||
|
||||
show_middle = width >= logo_width + middle_width + 8
|
||||
show_right = width >= logo_width + right_width + 8
|
||||
if show_middle and show_right:
|
||||
show_middle = width >= logo_width + 4 + middle_width + 2 + right_width
|
||||
|
||||
lines: list[Text] = []
|
||||
for index, row in enumerate(LOGO):
|
||||
line = Text(no_wrap=True)
|
||||
for column, char in enumerate(row):
|
||||
position = (
|
||||
column / max(1, logo_width - 1) + index * 0.055
|
||||
) % 1.0
|
||||
line.append(
|
||||
char, style=f"bold {gradient(SPECTRUM_STOPS, position)}"
|
||||
)
|
||||
if show_middle:
|
||||
line.append(" " * 4)
|
||||
middle = MIDDLE[index]
|
||||
line.append(middle, style="dim")
|
||||
# Keep the right block on one column even though the middle
|
||||
# lines differ in length ("SOMA FM RADIO" is shorter than
|
||||
# "LISTENER SUPPORTED").
|
||||
line.append(" " * max(0, middle_width - cell_len(middle)))
|
||||
if show_right:
|
||||
used = logo_width
|
||||
if show_middle:
|
||||
used += 4 + middle_width
|
||||
# Right-align the block *and* every item inside it: the clock,
|
||||
# the date and the volume each keep their own length, so pad
|
||||
# the shortest ones instead of left-aligning the whole block.
|
||||
pad = max(1, width - used - right_width)
|
||||
item = right[index]
|
||||
line.append(" " * pad)
|
||||
line.append(" " * max(0, right_width - cell_len(item)))
|
||||
style = "bold" if index == 0 else "dim"
|
||||
line.append(item, style=style)
|
||||
lines.append(line)
|
||||
|
||||
if height >= 4:
|
||||
ticker = Text(no_wrap=True)
|
||||
prefix = f"{glyph} {state.upper():<8} "
|
||||
ticker.append(prefix, style=f"bold {colour}")
|
||||
station = app.current
|
||||
if app.notice:
|
||||
text = app.notice
|
||||
text_style = "italic yellow"
|
||||
elif station is not None:
|
||||
song = station.now_playing
|
||||
if song is not None:
|
||||
text = f"{station.title} · {song.display_artist} — {song.display_title}"
|
||||
else:
|
||||
text = f"{station.title} · {station.description}"
|
||||
text_style = ""
|
||||
else:
|
||||
text = "Pick a station — press enter to tune in"
|
||||
text_style = "italic dim"
|
||||
ticker.append(marquee(text, max(4, width - cell_len(prefix))), style=text_style)
|
||||
lines.append(ticker)
|
||||
|
||||
return Group(*lines[:height])
|
||||
Reference in new issue
Block a user