Skip to content

Latest commit

 

History

69 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ScrollMPRIS

Rust 2024 D-Bus Async Runtime AUR version License: GPL-3.0

A fast, async, pure Rust scrolling MPRIS module for Waybar powered by zbus 5 and tokio.


✨ Features

  • Pure Rust Async D-Bus (zbus 5): Zero C library dependencies (libdbus-1 not required).
  • 100% Event-Driven (Zero IPC Polling): Pure signal-driven architecture with zero background polling loops and complete silence while idle or paused.
  • Adaptive Playback Calibration: Transient position calibration automatically compensates for streaming buffer delays (e.g., Spotify, browser MPRIS extensions), Bluetooth latency, and seek jitter across all media players—locking into sample-accurate sync within ~1.2s before self-disarming for zero ongoing D-Bus polling overhead.
  • Dual-Tier Player Discovery: Prefers playerctld for recency-ordered player prioritization, with an intelligent, priority-ranked fallback (Playing > Paused > Stopped) via standard D-Bus discovery. Idle or stopped players (such as mpd or inactive browser tabs) will never shadow an actively playing player.
  • Real-Time Lifecycle & Cross-Player Handoff: 100% event-driven, instant UI response to player startup, exit, and playback handoff via D-Bus NameOwnerChanged, broker-level PropertiesChanged match rules, and optional playerctld signals. Works completely standalone without requiring playerctld.
  • Multi-Artist & Album Support: Formats collaborating/featured artists (xesam:artist joined with commas) and album metadata.
  • Sub-Second Rate-Adjusted Timers: Timer precision is decoupled from the scrolling speed, delivering responsive progress updates dynamically adjusted by playback rate.
  • Pure Token-Driven Layout: 100% template-controlled output. Place brand icons, state glyphs, timers, and metadata anywhere.
  • Field-Aware Inline Scrolling: Scroll individual fields independently (e.g. {title:20:marquee} | {artist:12:bounce}).
  • Industry-Standard Scrolling Modes: marquee (continuous ticker), restart (loop with hold), and bounce (pendulum back & forth).
  • TOML Configuration File: Persistent declarative settings at ~/.config/ScrollMPRIS/config.toml with automatic XDG resolution.
  • Freeze on Pause: Option to freeze the ticker and snap text back to the start when music is paused.
  • Ultra-Lightweight Runtime: Optimized single-threaded Tokio execution with negligible CPU and memory footprint.

⚡ Quick Start (Waybar)

1. Add to Waybar Config (~/.config/waybar/config)

"custom/ScrollMPRIS": {
    "return-type": "json",
    "exec": "ScrollMPRIS",
    "escape": true,
    "on-click": "playerctl play-pause",
    "on-scroll-up": "playerctl next",
    "on-scroll-down": "playerctl previous"
}

Tip

Both ScrollMPRIS and scrollmpris can be used interchangeably in your configuration or terminal.

2. Add to Waybar Module Bar

Include "custom/ScrollMPRIS" in your modules-left, modules-center, or modules-right.


⚙️ Configuration File (config.toml)

ScrollMPRIS automatically reads ~/.config/ScrollMPRIS/config.toml (or ~/.config/scrollmpris/config.toml).

Generate Default Configuration

Generate a fully commented TOML configuration file with one command:

mkdir -p ~/.config/ScrollMPRIS
ScrollMPRIS --generate-config > ~/.config/ScrollMPRIS/config.toml

Example config.toml

# General settings
speed = 50                              # 0 (1000ms delay) to 100 (100ms delay)
width = 40                              # Default max character width for scrolling text
scroll_mode = "marquee"                 # Default mode: "marquee", "restart", or "bounce"
format = "{player_icon} {status_icon} {title:20:marquee} | {artist:12:bounce} [{position}/{length}]"
format_stopped = ""                     # Output when stopped ("" to auto-hide from Waybar)
tooltip_format = "{player_icon} {status_icon} {title} - {artist} | {album}"
blocked = ["firefox", "chromium"]       # Ignore audio from specific players
freeze_on_pause = true                  # Pause ticker and reset to start when paused

# Status glyphs for playback states
[icons.status]
playing = ""
paused = ""
stopped = ""

# Player-specific brand icons (fallback icon is "404")
[icons.players]
spotify = ""
vlc = "󰕼"
firefox = "󰈹"
mpv = ""
chrome = ""
edge = "󰇩"
telegramdesktop = ""
tauon = ""
"404" = ""

Tip

Any CLI argument passed directly in Waybar or terminal (such as ScrollMPRIS --speed 80) dynamically overrides config.toml.


🏷️ Supported Format Tokens

ScrollMPRIS is 100% token-driven: you control exactly where each element appears.

Category Token Aliases Description Example Output
Icons {player_icon} {app_icon} Player brand glyph (Spotify), 󰕼 (VLC), 󰈹 (Firefox)
{status_icon} {play_icon}, {state_icon} Playback status glyph (Playing), (Paused)
{icon} Combined {player_icon} {status_icon}  
Timers {position} {elapsed} Current playback elapsed time 01:23
{remaining} {countdown} Remaining track countdown 02:45
{length} {duration} Total track duration 04:08
Metadata {title} Track title Blinding Lights
{artist} Track artist(s) (comma-joined) The Weeknd
{album} Track album name After Hours
{player} Clean player service name spotify
{status} Raw playback status Playing / Paused

🔄 Field-Aware Scrolling & Modifiers

Scroll individual metadata fields independently while keeping other elements static:

1. Inline Field Modifiers: {field:width} / {field:mode} / {field:width:mode}

  • {title:20}: Scrolls {title} within 20 characters (using default mode); {artist} stays fixed.
  • {title:bounce}: Scrolls {title} with bounce animation using the global width.
  • {title:20:bounce}: Scrolls {title} within 20 characters using bounce animation.
  • {title:15:marquee} | {artist:10:bounce}: Title and artist scroll independently with separate widths and animation styles!

2. Block Scrolling: [scroll]...[/scroll] / [scroll:width] / [scroll:width:mode]

  • [scroll]{title} - {artist}[/scroll]: Scrolls the combined title and artist block using global width.
  • [scroll:25]{title} - {artist}[/scroll] | {album}: Scrolls the combined block within 25 characters, leaving album fixed.
  • [scroll:25:bounce]{title} - {artist}[/scroll]: Scrolls the combined block within 25 characters using bounce animation.

3. Whole-String Scrolling (Default Fallback)

  • If no inline modifiers are present (e.g. format = "{player_icon} {status_icon} {title} - {artist}"), the entire formatted output scrolls up to width characters.

Note

Width Priority & Behavior:

  • Override Priority: Token-specific widths (such as {title:20}) always override the global width setting for that field.
  • Combined Module Width: With multiple independent tokens (e.g. {title:20} - {artist:20}), the total rendered length will be the sum of the active field widths plus separators ($\approx 43$ characters).
  • Smart Threshold: If a song title/artist is shorter than its limit (e.g. 10 chars vs {title:20}), it displays statically without wasting space or adding extra padding.

🎬 Scrolling Modes

Mode Description
marquee (default) Seamless circular continuous ticker loop with separator padding.
restart Smooth left-to-right scroll, holds at the end, and snaps back to start.
bounce Scrolls to the end, holds, reverses direction back to start, holds, and repeats.

🛠️ Command-Line Options

Option Description Example
-c, --config <path> Path to custom TOML configuration file -c ~/my-config.toml
--generate-config Output default configuration TOML to stdout and exit ScrollMPRIS --generate-config
-s, --speed <0-100> Scroll speed (0: slow=1000ms delay, 100: fast=100ms delay) -s 50
-w, --width <number> Maximum character width for scrolling text -w 40
-b, --blocked <list> Block specific players (comma-separated, case-insensitive) -b edge,firefox,mpv
--scroll <mode> Default scrolling behavior: marquee, restart, or bounce --scroll marquee
--format <string> Output format template when playing or paused --format '{player_icon} {title:20} - {artist}'
--format-stopped <string> Output format template when stopped (default: "" to auto-hide) --format-stopped '{status_icon} No Media'
--tooltip-format <string> Tooltip format (resolves all fields un-scrolled on hover) --tooltip-format '{title} - {artist} | {album}'
--icon-format <string> Override player brand icons via JSON mapping --icon-format '{"404": "", "spotify": ""}'
--freeze Pause scrolling and reset text to start when paused --freeze

💡 Configuration Recipes & Examples

1. Default Clean Ticker

ScrollMPRIS --format '{player_icon} {status_icon} {title:20} - {artist}'

2. Status Glyph at the End with Duration

ScrollMPRIS --format '{player_icon} {title:20:marquee} - {artist} [{position}/{length}] {status_icon}'

3. Countdown Remaining Time

ScrollMPRIS --format '{player_icon} {title:20:bounce} - {artist} (-{remaining})'

4. Minimalist (Status Glyph Only)

ScrollMPRIS --format '{status_icon} {title:25} - {artist}'

5. Plain Text (No Icons)

ScrollMPRIS --format '{title:20} - {artist} [{position}]'

6. Dual-Field Independent Scrolling

ScrollMPRIS -s 50 --format '{player_icon} {title:15:marquee} | {artist:10:bounce} {status_icon}'

7. Persistent Placeholder (No Auto-Hide on Stop)

Keep the Waybar module visible with custom placeholder text even when music stops:

ScrollMPRIS --format '{player_icon} {status_icon} {title:20} - {artist}' --format-stopped '{status_icon} No Media'

🎨 Waybar CSS Styling

ScrollMPRIS tags the Waybar JSON output with CSS classes matching playback status and player service name (e.g. playing, paused, stopped, spotify, firefox).

Customize your ~/.config/waybar/style.css:

#custom-ScrollMPRIS {
    padding: 0 10px;
    color: #cdd6f4;
    background: #1e1e2e;
    border-radius: 8px;
}

#custom-ScrollMPRIS.playing {
    color: #a6e3a1;
}

#custom-ScrollMPRIS.paused {
    color: #f9e2af;
}

#custom-ScrollMPRIS.stopped {
    color: #6c7086;
}

/* Player-specific styling */
#custom-ScrollMPRIS.spotify {
    color: #1db954;
}

#custom-ScrollMPRIS.firefox {
    color: #ff7139;
}

#custom-ScrollMPRIS.playing.spotify {
    border-bottom: 2px solid #1db954;
}

📦 Installation & Build

Arch User Repository (AUR)

yay -S scrollmpris-git

Manual Build from Source

git clone https://github.com/BEST8OY/ScrollMPRIS.git
cd ScrollMPRIS
cargo build --release
install -Dt /usr/local/bin target/release/ScrollMPRIS
ln -sf /usr/local/bin/ScrollMPRIS /usr/local/bin/scrollmpris

🖼️ Preview

Restart mode:

Restart mode

Marquee mode:

Marquee mode


📄 License

This project is licensed under the GNU General Public License v3.0 or later.

About

Scrolling MPRIS module for waybar

Topics

Resources

Stars

18 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages