Module-based Waybar custom modules for controlling media players. The default player module is feishin, and Deckbar also ships modules for popular Linux players that expose the standard MPRIS surface through playerctl.
This is not a Feishin plugin or a direct Feishin API integration. It is a Waybar/playerctl control surface with player modules for detection, visibility, metadata, controls, labels, and generated Waybar snippets.
- Linux desktop session with Waybar
python33.11 or newerplayerctl- A supported MPRIS media player
The selected player must appear as an MPRIS player:
playerctl -l./install.sh
deckbar doctor
deckbar generate waybar
deckbar generate cssThe default install copies package files to ~/.local/share/deckbar, installs ~/.local/bin/deckbar, removes old playerctl-waybar and feishin-waybar wrappers/package files if present, and writes ~/.config/deckbar/config.toml if it does not already exist.
To patch the active Waybar config and style files with backups:
./install.sh --apply-waybarThe apply command updates ~/.config/waybar/config.jsonc and ~/.config/waybar/style.css between deckbar marker blocks. Existing files are backed up with .deckbar.<timestamp>.bak suffixes before edits.
deckbar doctor
deckbar modules
deckbar status track
deckbar status play_pause
deckbar action play-pause
deckbar action stop
deckbar action next
deckbar action previous
deckbar action shuffle
deckbar action loop
deckbar generate waybar
deckbar generate cssstatus commands print Waybar JSON. action commands dispatch through the selected player module.
Primary config path:
~/.config/deckbar/config.toml
Override the path for testing:
DECKBAR_CONFIG=/path/to/config.toml deckbar status trackImportant fields and sections:
module: selected player module. Default:feishin.player: optional MPRIS player name override. If omitted, the selected module uses its documented default player name.unavailable_mode: set tohiddento hide modules when the selected player is closed, orstatusto show an unavailable status label.[visible]: show or hidetrack,previous,play_pause,stop,next,shuffle, andloop.[labels]: change icons/text labels.[colors]: change generated CSS colors.[waybar]: set realtime signal and module insertion position.
See examples/config.toml.
The module system separates player-specific behavior from core Waybar rendering.
The core handles:
- CLI routing
- Waybar JSON rendering
- generated Waybar config and CSS
- install/apply helpers
- shared labels, colors, visibility, and intervals
Player modules handle:
- availability detection
- metadata/status lookup
- playback actions
- shuffle and loop semantics
- module-specific diagnostics
- generated module names and CSS class prefixes
Bundled modules:
| Module | Player | Default MPRIS name | Notes |
|---|---|---|---|
feishin |
Feishin | Feishin |
Default module. Existing custom/feishin-* generated names remain stable. |
spotify |
Spotify desktop client | spotify |
Some packages expose limited shuffle or loop behavior. |
vlc |
VLC | vlc |
Works for local music and mixed media playback when VLC exposes MPRIS. |
rhythmbox |
Rhythmbox | rhythmbox |
GNOME-oriented local library player. |
strawberry |
Strawberry | strawberry |
Strawberry documents MPRIS2 support. |
audacious |
Audacious | audacious |
MPRIS behavior depends on the Audacious MPRIS plugin/support in the installed build. |
tauon |
Tauon Music Box | tauon |
Tauon documents playerctl/MPRIS remote control on Linux. |
mpv |
mpv | mpv |
Requires an MPRIS plugin such as mpv-mpris; plain mpv does not expose MPRIS by default. |
To use another bundled module:
module = "spotify"If playerctl -l reports a different name, keep the module and override the target player:
module = "spotify"
player = "spotifyd"Then verify:
deckbar modules
deckbar doctor
deckbar generate waybar
deckbar generate cssMost local Linux players should add one file under src/deckbar/modules/ and subclass LocalMprisModule from src/deckbar/modules/base.py. Use a custom PlayerModule implementation only when the player cannot honestly fit the local MPRIS/playerctl behavior.
For a simple local MPRIS player:
- Add
src/deckbar/modules/<module_id>.py. - In that file, add a class that calls
LocalMprisModule.__init__with:id: stable config value used bymodule = "...".display_name: human-readable name shown by diagnostics.backend_name: normallylocal-mpris-playerctl.class_prefix: prefix for generated Waybar names and CSS classes.mpris_player: default value expected fromplayerctl -l.
- Add a
create_module()function that returns one instance of that class. Deckbar discovers bundled module files at startup and builds the in-memory registry from these factories. - Keep generated names stable.
class_prefix = "example"createscustom/example-track,custom/example-play,#custom-example-track, and classes likeexample-play-pause. - Add or update tests for discovery, default player selection, generated Waybar names, generated CSS selectors, hidden unavailable output, and any player-specific behavior.
- Document the module in this README, including default MPRIS name, prerequisites, and caveats.
Discovery is deterministic and limited to bundled files inside deckbar.modules; it is not a third-party plugin loader. Support files such as base.py and discovery.py are skipped. Override is_present, track, playback_status, shuffle_status, loop_status, do_action, or capabilities only when the player differs from normal MPRIS/playerctl semantics. Do not add player-specific branches to the core Waybar renderer unless the module interface is missing a hook.
The generated modules use one custom module per clickable control. This is intentional: Waybar binds click handlers to modules, not substrings inside a single label.
Add the generated custom/feishin-* module names to one of your Waybar module arrays, then add the generated module definitions at top level and append the generated CSS.
deckbar generate waybar
deckbar generate cssAfter clicking a control, the generated handlers send SIGRTMIN+9 to Waybar so all player modules refresh together.
v0.4 renames the project to Deckbar.
- The old
playerctl-waybarandfeishin-waybarcommands are removed by./install.sh. - The old internal Python package paths
playerctl_waybarandfeishin_waybarare gone. - Use
~/.config/deckbar/config.toml. - Existing
custom/feishin-*Waybar module names remain stable for the Feishin module.
If Feishin is closed and unavailable_mode = "hidden", the status commands return valid Waybar JSON with empty text. To show an unavailable label instead:
unavailable_mode = "status"If the widget says Feishin is unavailable or stays hidden while Feishin is open:
deckbar doctor
deckbar modules
playerctl -l
playerctl -p Feishin statusIf Feishin is running but listed under a different player name, update:
player = "YourPlayerName"If Waybar does not show Pango-colored artist/title text, make sure the generated module definitions include:
"escape": falsePYTHONPATH=src python3 -m deckbar.cli doctor
PYTHONPATH=src python3 -m unittest discover -s tests -v