Skip to content

Commit

Permalink
Add mpris module
Browse files Browse the repository at this point in the history
Uses libplayerctl to use the MPRIS dbus protocol to query, listen and
control media players.

Signed-off-by: Robert Günzler <r@gnzler.io>
  • Loading branch information
robertgzr committed Jan 6, 2023
1 parent b5c686c commit 207b462
Show file tree
Hide file tree
Showing 8 changed files with 588 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
#ifdef HAVE_DBUSMENU
#include "modules/sni/tray.hpp"
#endif
#ifdef HAVE_MPRIS
#include "modules/mpris/mpris.hpp"
#endif
#ifdef HAVE_LIBNL
#include "modules/network.hpp"
#endif
Expand Down
67 changes: 67 additions & 0 deletions include/modules/mpris/mpris.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

#include <iostream>
#include <string>

#include "gtkmm/box.h"
#include "gtkmm/label.h"

extern "C" {
#include <playerctl/playerctl.h>
}

#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"

namespace waybar::modules::mpris {

class Mpris : public AModule {
public:
Mpris(const std::string&, const Json::Value&);
~Mpris();
auto update() -> void;
bool handleToggle(GdkEventButton* const&);

private:
static auto onPlayerNameAppeared(PlayerctlPlayerManager*, PlayerctlPlayerName*, gpointer) -> void;
static auto onPlayerNameVanished(PlayerctlPlayerManager*, PlayerctlPlayerName*, gpointer) -> void;
static auto onPlayerPlay(PlayerctlPlayer*, gpointer) -> void;
static auto onPlayerPause(PlayerctlPlayer*, gpointer) -> void;
static auto onPlayerStop(PlayerctlPlayer*, gpointer) -> void;
static auto onPlayerMetadata(PlayerctlPlayer*, GVariant*, gpointer) -> void;

struct PlayerInfo {
std::string name;
PlayerctlPlaybackStatus status;
std::string status_string;

std::optional<std::string> artist;
std::optional<std::string> album;
std::optional<std::string> title;
std::optional<std::string> length; // as HH:MM:SS
};

auto getPlayerInfo() -> std::optional<PlayerInfo>;
auto getIcon(const Json::Value&, const std::string&) -> std::string;

Gtk::Box box_;
Gtk::Label label_;

// config
std::string format_;
std::string format_playing_;
std::string format_paused_;
std::string format_stopped_;
std::chrono::seconds interval_;
std::string player_;
std::vector<std::string> ignored_players_;

PlayerctlPlayerManager* manager;
PlayerctlPlayer* player;
std::string lastStatus;
std::string lastPlayer;

util::SleeperThread thread_;
};

} // namespace waybar::modules::mpris
103 changes: 103 additions & 0 deletions man/waybar-mpris.5.scd
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
waybar-mpris(5)

# NAME

waybar - MPRIS module

# DESCRIPTION

The *mpris* module displays currently playing media via libplayerctl.

# CONFIGURATION

*player*: ++
typeof: string ++
default: playerctld ++
Name of the MPRIS player to attach to. Using the default value always
follows the currenly active player.

*ignored-players*: ++
typeof: []string ++
Ignore updates of the listed players, when using playerctld.

*interval*: ++
typeof: integer ++
Refresh MPRIS information on a timer.

*format*: ++
typeof: string ++
default: {player} ({status}) {dynamic} ++
The text format.

*format-[status]*: ++
typeof: string ++
The status-specific text format.

*on-click*: ++
typeof: string ++
default: play-pause ++
Overwrite default action toggles.

*on-middle-click*: ++
typeof: string ++
default: previous track ++
Overwrite default action toggles.

*on-right-click*: ++
typeof: string ++
default: next track ++
Overwrite default action toggles.

*player-icons*: ++
typeof: map[string]string
Allows setting _{player-icon}_ based on player-name property.

*status-icons*: ++
typeof: map[string]string
Allows setting _{status-icon}_ based on player status (playing, paused,
stopped).


# FORMAT REPLACEMENTS

*{player}*: The name of the current media player

*{status}*: The current status (playing, paused, stopped)

*{artist}*: The artist of the current track

*{album}*: The album title of the current track

*{title}*: The title of the current track

*{length}*: Length of the track, formatted as HH:MM:SS

*{dynamic}*: Use _{artist}_, _{album}_, _{title}_ and _{length}_, automatically omit++
empty values

*{player-icon}*: Chooses an icon from _player-icons_ based on _{player}_

*{status-icon}*: Chooses an icon from _status-icons_ based on _{status}_

# EXAMPLES

```
"mpris": {
"format": "DEFAULT: {player_icon} {dynamic}",
"format-paused": "DEFAULT: {status_icon} <i>{dynamic}</i>",
"player-icons": {
"default": "▶",
"mpv": "🎵"
},
"status-icons": {
"paused": "⏸"
},
// "ignored-players": ["firefox"]
}
```

# STYLE

- *#mpris*
- *#mpris.${status}*
- *#mpris.${player}*
1 change: 1 addition & 0 deletions man/waybar.5.scd.in
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ A module group is defined by specifying a module named "group/some-group-name".
- *waybar-keyboard-state(5)*
- *waybar-memory(5)*
- *waybar-mpd(5)*
- *waybar-mpris(5)*
- *waybar-network(5)*
- *waybar-pulseaudio(5)*
- *waybar-river-mode(5)*
Expand Down
13 changes: 12 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ wayland_cursor = dependency('wayland-cursor')
wayland_protos = dependency('wayland-protocols')
gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0'])
dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk'))
giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabled() or get_option('logind').enabled() or get_option('upower_glib').enabled()))
giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabled() or
get_option('logind').enabled() or
get_option('upower_glib').enabled() or
get_option('mpris').enabled()))
jsoncpp = dependency('jsoncpp', version : ['>=1.9.2'], fallback : ['jsoncpp', 'jsoncpp_dep'])
sigcpp = dependency('sigc++-2.0')
libinotify = dependency('libinotify', required: false)
Expand All @@ -95,6 +98,7 @@ libinput = dependency('libinput', required: get_option('libinput'))
libnl = dependency('libnl-3.0', required: get_option('libnl'))
libnlgen = dependency('libnl-genl-3.0', required: get_option('libnl'))
upower_glib = dependency('upower-glib', required: get_option('upower_glib'))
playerctl = dependency('playerctl', version : ['>=2.0.0'], required: get_option('mpris'))
libpulse = dependency('libpulse', required: get_option('pulseaudio'))
libudev = dependency('libudev', required: get_option('libudev'))
libevdev = dependency('libevdev', required: get_option('libevdev'))
Expand Down Expand Up @@ -238,6 +242,11 @@ if (upower_glib.found() and giounix.found() and not get_option('logind').disable
src_files += 'src/modules/upower/upower_tooltip.cpp'
endif

if (playerctl.found() and giounix.found() and not get_option('logind').disabled())
add_project_arguments('-DHAVE_MPRIS', language: 'cpp')
src_files += 'src/modules/mpris/mpris.cpp'
endif

if libpulse.found()
add_project_arguments('-DHAVE_LIBPULSE', language: 'cpp')
src_files += 'src/modules/pulseaudio.cpp'
Expand Down Expand Up @@ -334,6 +343,7 @@ executable(
libnl,
libnlgen,
upower_glib,
playerctl,
libpulse,
libjack,
libwireplumber,
Expand Down Expand Up @@ -387,6 +397,7 @@ if scdoc.found()
'waybar-keyboard-state.5.scd',
'waybar-memory.5.scd',
'waybar-mpd.5.scd',
'waybar-mpris.5.scd',
'waybar-network.5.scd',
'waybar-pulseaudio.5.scd',
'waybar-river-mode.5.scd',
Expand Down
1 change: 1 addition & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ option('libudev', type: 'feature', value: 'auto', description: 'Enable libudev s
option('libevdev', type: 'feature', value: 'auto', description: 'Enable libevdev support for evdev related features')
option('pulseaudio', type: 'feature', value: 'auto', description: 'Enable support for pulseaudio')
option('upower_glib', type: 'feature', value: 'auto', description: 'Enable support for upower')
option('mpris', type: 'feature', value: 'auto', description: 'Enable support for mpris')
option('systemd', type: 'feature', value: 'auto', description: 'Install systemd user service unit')
option('dbusmenu-gtk', type: 'feature', value: 'auto', description: 'Enable support for tray')
option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages')
Expand Down
5 changes: 5 additions & 0 deletions src/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
return new waybar::modules::upower::UPower(id, config_[name]);
}
#endif
#ifdef HAVE_MPRIS
if (ref == "mpris") {
return new waybar::modules::mpris::Mpris(id, config_[name]);
}
#endif
#ifdef HAVE_SWAY
if (ref == "sway/mode") {
return new waybar::modules::sway::Mode(id, config_[name]);
Expand Down

0 comments on commit 207b462

Please sign in to comment.