Add mpris support

This commit is contained in:
Geoffrey Frogeye 2024-08-11 14:54:51 +02:00
parent f011b376bb
commit 86f9f75bd7
Signed by: geoffrey
GPG key ID: C72403E7F82E6AD8
6 changed files with 126 additions and 21 deletions

View file

@ -52,7 +52,7 @@
hwdec = "auto-safe";
profile = "gpu-hq";
};
scripts = with pkgs.mpvScripts; [ thumbnail ];
scripts = with pkgs.mpvScripts; [ thumbnail mpris ];
scriptOpts = {
mpv_thumbnail_script = {
autogenerate = false; # TODO It creates too many processes at once, crashing the system

View file

@ -25,7 +25,7 @@ pkgs.python3Packages.buildPythonApplication {
pulsectl
pyinotify
];
makeWrapperArgs = [ "--prefix PATH : ${pkgs.lib.makeBinPath ([ lemonbar ] ++ (with pkgs; [ wirelesstools ]))}" ];
makeWrapperArgs = [ "--prefix PATH : ${pkgs.lib.makeBinPath ([ lemonbar ] ++ (with pkgs; [ wirelesstools playerctl ]))}" ];
src = ./.;
}

View file

@ -37,7 +37,8 @@ def run() -> None:
)
# TODO Middle
Bar.addSectionAll(fp.MpdProvider(theme=9), BarGroupType.LEFT)
Bar.addSectionAll(fp.MprisProvider(theme=9), BarGroupType.LEFT)
# Bar.addSectionAll(fp.MpdProvider(theme=9), BarGroupType.LEFT)
# Bar.addSectionAll(I3WindowTitleProvider(), BarGroupType.LEFT)
# TODO Computer modes

View file

@ -849,3 +849,96 @@ class MpdProvider(Section, ThreadedUpdater):
self.connect()
except BaseException as e:
log.error(e, exc_info=True)
class MprisProviderSection(Section, Updater):
def __init__(self, parent: "MprisProvider"):
Updater.__init__(self)
Section.__init__(self, theme=parent.theme)
self.parent = parent
class MprisProvider(Section, ThreadedUpdater):
# TODO Controls (select player at least)
# TODO Use the Python native thing for it:
# https://github.com/altdesktop/playerctl?tab=readme-ov-file#using-the-library
# TODO Make it less sucky
SECTIONS = [
"{{ playerName }} {{ status }}",
"{{ album }}",
"{{ artist }}",
"{{ duration(position) }}|{{ duration(mpris:length) }}"
" {{ title }}",
]
# nf-fd icons don't work (UTF-16?)
SUBSTITUTIONS = {
"Playing": "",
"Paused": "",
"Stopped": "",
"mpd": "",
"firefox": "",
"chromium": "",
"mpv": "",
}
ICONS = {
1: "",
2: "",
3: "",
}
def __init__(self, theme: int | None = None):
ThreadedUpdater.__init__(self)
Section.__init__(self, theme)
self.line = ""
self.start()
self.sections: list[Section] = []
def fetcher(self) -> Element:
create = not len(self.sections)
populate = self.line
split = self.line.split("\t")
lastSection: Section = self
for i in range(len(self.SECTIONS)):
if create:
section = Section(theme=self.theme)
lastSection.appendAfter(section)
lastSection = section
self.sections.append(section)
else:
section = self.sections[i]
if populate:
text = split[i]
if i == 0:
for key, val in self.SUBSTITUTIONS.items():
text = text.replace(key, val)
if text:
if i in self.ICONS:
text = f"{self.ICONS[i]} {text}"
section.updateText(text)
else:
section.updateText(None)
else:
section.updateText(None)
return None
def loop(self) -> None:
cmd = [
"playerctl",
"metadata",
"--format",
"\t".join(self.SECTIONS),
"--follow",
]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
assert p.stdout
while p.poll() is None:
self.line = p.stdout.readline().decode().strip()
self.refreshData()

View file

@ -4,6 +4,7 @@ import functools
import logging
import math
import os
import subprocess
import threading
import time
@ -11,8 +12,8 @@ import coloredlogs
import i3ipc
import pyinotify
from frobar.display import Element
from frobar.common import notBusy
from frobar.display import Element
coloredlogs.install(level="DEBUG", fmt="%(levelname)s %(message)s")
log = logging.getLogger()

View file

@ -6,26 +6,36 @@
ashuffle
mpc-cli
vimpc
playerctl
];
sessionVariables = {
MPD_PORT = "${toString config.services.mpd.network.port}";
};
};
services.mpd = {
enable = true;
network = {
listenAddress = "0.0.0.0"; # Can be controlled remotely, determined with firewall
startWhenNeeded = true;
services = {
mpd = {
enable = true;
network = {
listenAddress = "0.0.0.0"; # Can be controlled remotely, determined with firewall
startWhenNeeded = true;
};
extraConfig = ''
restore_paused "yes"
audio_output {
type "pipewire"
name "PipeWire Sound Server"
}
'';
# UPST auto audio_output ?
musicDirectory = "${config.home.homeDirectory}/Musiques";
};
extraConfig = ''
restore_paused "yes"
audio_output {
type "pipewire"
name "PipeWire Sound Server"
}
'';
# UPST auto audio_output ?
musicDirectory = "${config.home.homeDirectory}/Musiques";
# Expose mpd to mpris
# mpd-mpris also exists but is MIT and make playerctld not pick up on play/pause events
mpdris2.enable = true;
# Allow control from headset
mpris-proxy.enable = true;
# Remember the last player
playerctld.enable = true;
};
xdg = {
configFile = {
@ -45,9 +55,9 @@
};
xsession.windowManager.i3.config.keybindings =
{
"XF86AudioPrev" = "exec ${pkgs.mpc-cli}/bin/mpc prev";
"XF86AudioPlay" = "exec ${pkgs.mpc-cli}/bin/mpc toggle";
"XF86AudioNext" = "exec ${pkgs.mpc-cli}/bin/mpc next";
"XF86AudioPrev" = "exec ${lib.getExe pkgs.playerctl} previous";
"XF86AudioPlay" = "exec ${lib.getExe pkgs.playerctl} play-pause";
"XF86AudioNext" = "exec ${lib.getExe pkgs.playerctl} next";
};
};
}