Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions apps/audiobookshelf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Audiobookshelf Now Playing

Track currently playing audiobooks and podcasts from your [Audiobookshelf](https://www.audiobookshelf.org/) server on your Tronbyt / Tidbyt device.

## Features

- **Now Playing Display**: Shows current title, author, progress bar, and realistic time remaining (or elapsed / total).
- **Clean 1x & 2x Layouts**:
- **1x (64x32)**: Clean layout with title, author, progress bar, and dedicated right-aligned time remaining.
- **2x (128x64)**: High-resolution layout featuring chapter title, progress bar, percentage, and time remaining.
- **Configurable Listen Speed Factor**: Select your listening speed multiplier (`0.5x`, `0.75x`, `1.0x`, `1.25x`, `1.5x`, `1.75x`, `2.0x`, `2.5x`) to dynamically recalculate remaining listening time.
- **Aspect Ratio Detection**: Automatically detects square vs. rectangular book covers.
- **Stylized Fallback**: Procedurally renders a book cover if server covers are unavailable.
- **Customizable Appearance**: Multiple color themes, custom hex colors, progress bar styles, and scroll modes.

## Configuration Options

| Option | Type | Description | Default |
| --- | --- | --- | --- |
| `server_url` | Text | Host URL of your Audiobookshelf server | `http://localhost:13378` |
| `api_token` | Text (Secret) | User API token or Bearer token | — |
| `only_playing` | Toggle | Only display when an audiobook is actively playing | `false` |
| `listen_speed` | Dropdown | Listening speed multiplier (`0.5x` to `2.5x`) to recalculate realistic time remaining | `1.0` |
| `time_mode` | Dropdown | Time display format (`remaining`, `elapsed`, `total`) | `remaining` |
| `scroll_mode` | Dropdown | Title animation (`scroll`, `static`) | `scroll` |
| `bar_style` | Dropdown | Progress bar style (`standard`, `centered`) | `standard` |
| `color_scheme` | Dropdown | Accent color theme (ABS Gold, Teal, Green, etc., or Custom) | `gold` |
| `custom_color` | Text | Custom hex color code when `custom` color scheme is selected | `#f59e0b` |
80 changes: 69 additions & 11 deletions apps/audiobookshelf/audiobookshelf.star
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,32 @@ def parse_hex_color(val, default = ABS_GOLD):
return c
return default

def parse_speed(val, default = 1.0):
if not val:
return default
s = str(val).strip().lower()
if s.endswith("x"):
s = s[:-1].strip()
if not s:
return default
has_digit = False
dot_count = 0
for ch in s.elems():
if ch == ".":
dot_count += 1
if dot_count > 1:
return default
elif ch in "0123456789":
has_digit = True
else:
return default
if not has_digit:
return default
speed = float(s)
if speed <= 0.1 or speed > 10.0:
return default
return speed

def render_smart_text(text, font, color, max_width, scale, scroll_mode = "scroll"):
"""Renders text: static if scroll_mode is 'static' or text fits max_width, marquee if scrolling is enabled and overflows."""
if scroll_mode == "static":
Expand Down Expand Up @@ -337,7 +363,7 @@ def render_cover_fallback(scale, width, height, title, accent_color = ABS_GOLD):
),
)

def render_abs_view(scale, width, data, cover_bytes, font_title, font_tiny, cover_aspect = "square", bar_style = "standard", accent_color = ABS_GOLD, time_mode = "remaining", scroll_mode = "scroll"):
def render_abs_view(scale, width, data, cover_bytes, font_title, font_tiny, cover_aspect = "square", bar_style = "standard", accent_color = ABS_GOLD, time_mode = "remaining", scroll_mode = "scroll", listen_speed = 1.0):
if cover_aspect == "rectangular":
cover_width = 24 * scale
cover_height = 30 * scale
Expand All @@ -358,7 +384,8 @@ def render_abs_view(scale, width, data, cover_bytes, font_title, font_tiny, cove
progress_pct = int(data["progress"] * 100)

# Format time display cleanly for compact width
time_left = data["duration"] - data["current_time"]
raw_time_left = data["duration"] - data["current_time"]
time_left = int(raw_time_left / listen_speed) if listen_speed > 0 else raw_time_left
if time_mode == "elapsed":
time_display = format_time(data["current_time"], compact = True)
elif time_mode == "total":
Expand Down Expand Up @@ -427,15 +454,25 @@ def render_abs_view(scale, width, data, cover_bytes, font_title, font_tiny, cove

column_children.append(progress_bar)

bottom_row = render.Row(
expanded = True,
cross_align = "center",
main_align = "space_between",
children = [
render.Text("%d%%" % progress_pct, font = font_tiny, color = accent_color),
render.Text(time_display, font = font_tiny, color = MUTED),
],
)
if scale == 1:
bottom_row = render.Row(
expanded = True,
cross_align = "center",
main_align = "end",
children = [
render.Text(time_display, font = font_tiny, color = MUTED),
],
)
else:
bottom_row = render.Row(
expanded = True,
cross_align = "center",
main_align = "space_between",
children = [
render.Text("%d%%" % progress_pct, font = font_tiny, color = accent_color),
render.Text(time_display, font = font_tiny, color = MUTED),
],
)
column_children.append(bottom_row)

text_column = render.Column(
Expand Down Expand Up @@ -475,6 +512,9 @@ def main(config):
time_mode = config.str("time_mode", "remaining")
scroll_mode = config.str("scroll_mode", "scroll")

speed_setting = config.str("listen_speed", "") or config.str("read_speed", "") or config.str("playback_speed", "1.0")
listen_speed = parse_speed(speed_setting, default = 1.0)

if color_scheme == "custom":
accent_color = parse_hex_color(config.str("custom_color", "#f59e0b"), ABS_GOLD)
else:
Expand Down Expand Up @@ -530,6 +570,7 @@ def main(config):
accent_color = accent_color,
time_mode = time_mode,
scroll_mode = scroll_mode,
listen_speed = listen_speed,
)

delay = 40 // scale
Expand Down Expand Up @@ -626,5 +667,22 @@ def get_schema():
schema.Option(display = "Total Duration (3h56m)", value = "total"),
],
),
schema.Dropdown(
id = "listen_speed",
name = "Listen Speed",
desc = "Playback speed factor to recalculate realistic time remaining",
icon = "gauge",
default = "1.0",
options = [
schema.Option(display = "0.5x", value = "0.5"),
schema.Option(display = "0.75x", value = "0.75"),
schema.Option(display = "1.0x (Normal)", value = "1.0"),
schema.Option(display = "1.25x", value = "1.25"),
schema.Option(display = "1.5x", value = "1.5"),
schema.Option(display = "1.75x", value = "1.75"),
schema.Option(display = "2.0x", value = "2.0"),
schema.Option(display = "2.5x", value = "2.5"),
],
),
],
)
Binary file modified apps/audiobookshelf/audiobookshelf.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading