Making DeaDBeeF work with Sway window manager

My fresh install of Debian 13 came with Wayland enabled which meant I had to switch away from my usual i3 window manager to Sway. While the change was very straginforward due to compatible configuration syntax there was one significant issue: DeaDBeeF, my music player of choice, does not show the taskbar icon when running under Wayland. This is annoying becase I like to use the taskbar icon to minimize the player while listening to music. Working around this proved to be a fairly invloved process, hence this writeup.

Configuring Waybar

The default bar that comes with Sway (sway-bar) provides only minimal functionality, so the first step is to switch to something a bit more powerful. Waybar is areplacement bar that seems quite popular.

apt install waybar

Configuration is done in 2 parts: conguring the bar itself and then CSS-like configuration of the bar's appearance. My configuration mimics the look of Sway's default bar but Waybar styling is extremely configurable and well documented.

// ~/.config/waybar/config - see https://github.com/Alexays/Waybar/wiki/Configuration

{
  "layer": "top",
  "position": "top",
  "modules-left": ["sway/workspaces"],
  "modules-right": ["tray", "mpris", "clock"],

  "clock": {
    "format": "{:%Y-%m-%d %H:%M}"
  },

  "tray": {
    "icon-size": 16,
    "pin": "right"
  },

  "mpris": {
    "format": "{player_icon} {dynamic}",
    "format-paused": "{status_icon} {dynamic}",
    "player-icons": {
      "default": "▶",
      "mpv": "🎵"
    },
    "status-icons": {
      "paused": "⏸"
    },
    "dynamic-order": ["title", "artist"],
    "ignored-players": ["firefox"]
  }
}
// ~/.config/waybar/style.css - see https://github.com/Alexays/Waybar/wiki/Styling

* {
    border-radius: 0;
    font-family: monospace;
    font-size: 13px;
    min-height: 26px;
    padding: 0;
}

window#waybar {
    background: #323232;
    color: white;
}

#workspaces button {
    color: white;
    padding: 0 6px;
}

#workspaces button.current_output.focused {
    background: #285577;
    border: 1px solid #4c7899;
}

#workspaces button.visible {
    background: #5c5c5c;
}

#workspaces button:hover {
    border: 1px solid #4c4c4c;
}

#clock, #mpris {
    padding: 0 5px;
}

Configuring Sway

To make Sway use Waybar is a simple configuration change:

// ~/.config/sway/config

bar {
  position top
  swaybar_command waybar
}

Then reload Sway to apply the change:

swaymsg reload

You should now see the new bar at the top of the screen:

Waybar

Compiling and installing the DeaDBeeF MPRISv2 plugin

The MPRISv2 plugin allows DeaDBeeF to be controlled from other applications, such as Waybar. The plugin is not part of the DeaDBeeF source code, so it needs to be compiled and installed separately. It is assumed that DeaDBeeF is already installed using the Debian package.

sudo apt install build-essential autoconf libtool pkgconf

git clone https://github.com/DeaDBeeF-Player/deadbeef-mpris2-plugin.git
cd deadbeef-mpris2-plugin

autoreconf --install
CPPFLAGS="$CPPFLAGS -I/opt/deadbeef/include/" ./configure --prefix=/opt/deadbeef
sudo make install

After this your should be able to see "MPRISv2 plugin" in DeaDBeeF's plugin list and when you start playing a track you should see control in the taskbar:

MPRIS control in bar

This control is not very sophisticated: left-click to play/pause, right-click to next track, middle-click to previous track.

Adding a keyboard shortcut to hide and show DeaDBeeF window

Although we still can't toggle DeaDBeeF window visibility from the taskbar, we can add a keyboard shortcut to hide and show leveraging Sway's special "scratchpad" workspace.

First, check that you have jq installed:

sudo apt install jq

Then add a script to toggle DeaDBeeF window visibility:

// ~/scripts/i3/toggle-deadbeef.sh

#!/bin/bash

set -o nounset
set -o errexit
set -o pipefail

WINDOW_INFO=$(swaymsg -t get_tree | jq '.. | select(type == "object" and (.type == "con" or .type == "floating_con") and (.app_id? | type == "string") and .app_id == "deadbeef") | {id, visible}')

if [ -z "$WINDOW_INFO" ]; then
  deadbeef &
  exit 0
fi

WINDOW_ID=$(echo "$WINDOW_INFO" | jq '.id')
WINDOW_VISIBLE=$(echo "$WINDOW_INFO" | jq '.visible')

if [ "$WINDOW_VISIBLE" == "true" ]; then
    swaymsg [con_id=$WINDOW_ID] move scratchpad
else
    swaymsg [con_id=$WINDOW_ID] scratchpad show
    swaymsg [con_id=$WINDOW_ID] floating disable
fi

Then bind this to a keyboard shortcut in your Sway configuration - I use Mod+Shift+d:

// ~/.config/sway/config

bindsym $mod+Shift+d exec --no-startup-id ./scripts/i3/toggle-deadbeef.sh

And reload Sway to apply the change:

swaymsg reload

After this you should be all set to go! :)