I Put Media Controls Directly in My XFCE Panel
There is a small interaction in XFCE that bothered me more often than it should have: changing a track usually meant opening a menu first.
The excellent xfce4-pulseaudio-plugin already supports media controls. I know that, and I am not trying to replace it. But when I am working, I skip tracks, pause something for a call, or resume a podcast many times a day. Opening a menu just to pause audio is a tiny friction point, but it happens constantly.
Before the keyboard purists ask: yes, media keys exist. But not every keyboard has dedicated ones, and remapping arbitrary hotkeys for basic playback always felt clunky to me. More importantly, when I’m deep in work with a mouse or trackpad already in hand, I simply prefer a quick click on the screen over reaching across the desk.
This project exists mostly for that very particular kind of nitpicking.
I wanted three familiar buttons, always visible in the panel:
- previous track
- play or pause
- next track
The result is xfce4-mpris-controls-plugin, a small native XFCE panel plugin written in C. It does one job and stays out of the way.
The goal was deliberately narrow
I did not want a new player menu, album art, track metadata, volume controls, or a replacement for a full media applet. XFCE already has good options for that. The desired workflow was more immediate: glance at the panel, press a button, continue working.
That constraint informed the UI. The plugin has no labels and no popup. It uses the standard symbolic media icons, follows the panel orientation, and sizes each button to the panel’s current height. It looks like a small part of XFCE rather than a separate application embedded inside the panel.
The play button also reflects the active player’s state. When something is playing, it becomes a pause button. When playback is paused or stopped, it becomes a play button. Tooltips follow the same state.
Why MPRIS instead of controlling a specific player?
On Linux, MPRIS is the right layer for this problem. It is a D-Bus specification that lets media players expose a common control interface. Players such as Firefox, Chromium, VLC, Spotify, Rhythmbox, and many others can publish an org.mpris.MediaPlayer2.* name on the session bus.
That gives the plugin a common vocabulary:
PreviousPlayPauseNextPlaybackStatus
The plugin therefore does not need to know how a particular player handles playback internally. It asks the session D-Bus which MPRIS players exist, reads the PlaybackStatus property, and sends methods to org.mpris.MediaPlayer2.Player.
Using MPRIS directly also avoids making playerctl a runtime dependency. playerctl is a very useful command-line MPRIS client, but this is a native panel plugin. Talking to D-Bus through GLib keeps the control path inside the plugin and makes the implementation easier to package.
Choosing a player is harder than sending a command
Sending PlayPause to one known player is straightforward. Choosing the right player is the interesting part.
Get Medard Konopík’s stories in your inbox
Join Medium for free to get updates from this writer.
Several applications can expose MPRIS at the same time. A browser tab, a music application, and a video player may all be available. The plugin follows a simple and understandable policy:
- Discover names beginning with
org.mpris.MediaPlayer2.on the session bus. - Prefer a player whose
PlaybackStatusisPlaying. - If none are playing, keep controlling the player selected previously when it is still available.
- Otherwise, use the first available MPRIS player.
This is intentionally conservative. It handles the normal single-player case well and avoids pretending it can perfectly infer intent when several paused players are open. A future version could expose player selection, track the most recently active player, or subscribe to D-Bus property-change signals instead of refreshing status periodically.
The stack
The plugin is intentionally small and uses the libraries XFCE plugins already live with:
- C
- GTK 3 for the buttons and icons
libxfce4panel-2.0for the XFCE panel plugin APIlibxfce4ui-2for the XFCE UI dependency chain- GLib and GIO for the session D-Bus connection and MPRIS calls
makeandpkg-configfor the build
The panel entry is conventional XFCE plugin metadata. A .desktop file tells XFCE the module name, display name, icon, and plugin API version. The compiled shared library is installed in XFCE's panel plugin directory, while the metadata goes under the shared data directory.
On Ubuntu and Xubuntu x86_64 systems, those locations are typically:
/usr/lib/x86_64-linux-gnu/xfce4/panel/plugins/libmpris-controls.so
/usr/share/xfce4/panel/plugins/mpris-controls.desktopThis is also why prebuilt binaries need to be treated carefully. A shared object built on one distribution or architecture may not be compatible with another. Source builds remain the most portable path, while release binaries are a convenience for matching systems.
What was trickier than expected
The three buttons themselves were not difficult. The surrounding details were.
Matching the panel
Panel plugins have to deal with both horizontal and vertical panels. A horizontal button box looks right on a top or bottom panel, but it should become vertical on a side panel. The plugin listens for XFCE orientation changes and updates the GTK box accordingly. It also responds to panel size changes so the controls remain compact instead of forcing the panel wider or taller than necessary.
Keeping the play icon honest
The first obvious approach was to invoke playerctl status periodically. It was convenient, but it added another process boundary and did not reliably reflect the same active MPRIS player that had received a command. The pause icon could briefly appear after a click and then revert to play.
The better approach was to learn from the existing XFCE PulseAudio plugin. Its MPRIS support discovers players on the session D-Bus and reads player properties directly. Moving to the same foundation made the state and the control path agree.
The plugin still refreshes PlaybackStatus every two seconds in this first version. That is simple, low-cost for a tiny panel plugin, and robust enough for the intended use. Subscribing to PropertiesChanged would be the next step for event-driven updates.
Installing a panel plugin is two files, not one
The shared library is the executable part, but XFCE also needs the metadata file to list the plugin in “Add New Items”. It is easy to share a .so release asset and forget the .desktop file. The project README documents both files and includes build, install, uninstall, and prebuilt-binary instructions.
Building it
On Debian, Ubuntu, or Xubuntu, install the development packages:
sudo apt install build-essential pkg-config libxfce4panel-2.0-dev libxfce4ui-2-dev libgtk-3-devThen build and install:
make
sudo make install
xfce4-panel -rAfter restarting the panel, add MPRIS Controls through the XFCE panel’s “Add New Items” dialog.
A small plugin for a small friction point
This is not a dramatic new capability for XFCE. It is just a faster route to a thing I already do often. That is the appeal of desktop customization: the best changes are sometimes the ones that remove one unnecessary click from a repeated action.
If you use XFCE and would rather have previous, play/pause, and next controls directly on the panel, the source, installation instructions, and release files are available here:
https://github.com/mkonopik87/xfce4-mpris-controls-plugin
The project is licensed under MIT. Contributions, bug reports, and suggestions are welcome.







