Add mpris support
This commit is contained in:
parent
f011b376bb
commit
86f9f75bd7
|
@ -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
|
||||
|
|
|
@ -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 = ./.;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue