programs: wob (and wob-audio): remove
i don't use it, and its service file was no longer compatible with s6 (it used 'environment')
This commit is contained in:
@@ -118,7 +118,6 @@
|
|||||||
./wine.nix
|
./wine.nix
|
||||||
./wireplumber.nix
|
./wireplumber.nix
|
||||||
./wireshark.nix
|
./wireshark.nix
|
||||||
./wob
|
|
||||||
./wvkbd.nix
|
./wvkbd.nix
|
||||||
./xarchiver.nix
|
./xarchiver.nix
|
||||||
./xdg-desktop-portal.nix
|
./xdg-desktop-portal.nix
|
||||||
|
@@ -152,7 +152,6 @@ in
|
|||||||
"wdisplays" # like xrandr
|
"wdisplays" # like xrandr
|
||||||
"wireplumber" # used by sway config
|
"wireplumber" # used by sway config
|
||||||
"wl-clipboard"
|
"wl-clipboard"
|
||||||
# "wob" # render volume changes on-screen
|
|
||||||
"xdg-desktop-portal"
|
"xdg-desktop-portal"
|
||||||
# xdg-desktop-portal-gtk provides portals for:
|
# xdg-desktop-portal-gtk provides portals for:
|
||||||
# - org.freedesktop.impl.portal.Access
|
# - org.freedesktop.impl.portal.Access
|
||||||
|
@@ -1,118 +0,0 @@
|
|||||||
# docs:
|
|
||||||
# - <https://github.com/francma/wob/blob/master/wob.ini.5.scd>
|
|
||||||
# - `wob -vv` to see config defaults
|
|
||||||
#
|
|
||||||
# the wob services defined here are largely based on those from SXMO.
|
|
||||||
#
|
|
||||||
# this should arguably be just a (user) service. nothing actually needs `wob` on the PATH.
|
|
||||||
#
|
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
let
|
|
||||||
wob-audio = pkgs.static-nix-shell.mkPython3Bin {
|
|
||||||
pname = "wob-audio";
|
|
||||||
srcRoot = ./.;
|
|
||||||
pkgs = [ "wireplumber" ];
|
|
||||||
};
|
|
||||||
cfg = config.sane.programs.wob;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sane.programs.wob = {
|
|
||||||
configOption = with lib; mkOption {
|
|
||||||
default = {};
|
|
||||||
type = types.submodule {
|
|
||||||
options.autostart = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
};
|
|
||||||
options.sock = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "wob.sock";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
|
||||||
sandbox.whitelistWayland = true;
|
|
||||||
|
|
||||||
suggestedPrograms = [
|
|
||||||
"wob-audio"
|
|
||||||
];
|
|
||||||
|
|
||||||
fs.".config/wob/wob.ini".symlink.text = ''
|
|
||||||
timeout = 900
|
|
||||||
|
|
||||||
anchor = top right
|
|
||||||
orientation = vertical
|
|
||||||
# margin top right bottom left
|
|
||||||
# note that wob is "aware" of the sway bar, so margin 0 never overlaps it.
|
|
||||||
# however it's not aware of sway's window title
|
|
||||||
margin = 54 3 54 3
|
|
||||||
|
|
||||||
height = 164
|
|
||||||
width = 30
|
|
||||||
|
|
||||||
border_offset = 0
|
|
||||||
border_size = 2
|
|
||||||
bar_padding = 0
|
|
||||||
|
|
||||||
# very light teal, derived from conky background
|
|
||||||
bar_color = e1f0efDC
|
|
||||||
background_color = 000000B4
|
|
||||||
border_color = 000000C8
|
|
||||||
|
|
||||||
overflow_bar_color = FF4040DC
|
|
||||||
overflow_background_color = FFFFFFC8
|
|
||||||
overflow_border_color = FF4040DC
|
|
||||||
'';
|
|
||||||
|
|
||||||
services.wob = {
|
|
||||||
description = "Wayland Overlay Bar (wob) renders volume/backlight levels when requested";
|
|
||||||
after = [ "graphical-session.target" ];
|
|
||||||
partOf = [ "graphical-session.target" ];
|
|
||||||
wantedBy = lib.mkIf cfg.config.autostart [ "graphical-session.target" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
# ExecStart = "${cfg.package}/bin/wob";
|
|
||||||
Type = "simple";
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = "20s";
|
|
||||||
};
|
|
||||||
script = ''
|
|
||||||
wobsock="$XDG_RUNTIME_DIR/$WOBSOCK_NAME"
|
|
||||||
rm -f "$wobsock" || true
|
|
||||||
mkfifo "$wobsock" && wob <> "$wobsock"
|
|
||||||
|
|
||||||
# TODO: cleanup should be done in a systemd OnFailure, or OnExit, or whatever
|
|
||||||
rm -f "$wobsock"
|
|
||||||
'';
|
|
||||||
environment.WOBSOCK_NAME = cfg.config.sock;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.programs.wob-audio = {
|
|
||||||
packageUnwrapped = wob-audio;
|
|
||||||
sandbox.method = "bwrap";
|
|
||||||
sandbox.whitelistAudio = true;
|
|
||||||
sandbox.extraRuntimePaths = [
|
|
||||||
cfg.config.sock
|
|
||||||
];
|
|
||||||
|
|
||||||
suggestedPrograms = [
|
|
||||||
"wireplumber" #< TODO: replace with just the one binary we need.
|
|
||||||
];
|
|
||||||
|
|
||||||
services.wob-audio = {
|
|
||||||
description = "wob-audio: monitor audio and display volume changes on-screen";
|
|
||||||
after = [ "wob.service" ];
|
|
||||||
wantedBy = [ "wob.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
ExecStart = "${wob-audio}/bin/wob-audio";
|
|
||||||
Type = "simple";
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = "20s";
|
|
||||||
};
|
|
||||||
# environment.WOB_VERBOSE = "1";
|
|
||||||
environment.WOBSOCK_NAME = cfg.config.sock;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,97 +0,0 @@
|
|||||||
#!/usr/bin/env nix-shell
|
|
||||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p wireplumber
|
|
||||||
# vim: set filetype=python :
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class PwMonConsumer:
|
|
||||||
last_volume: float | None = None
|
|
||||||
last_mute: bool | None = None
|
|
||||||
last_effective_volume: float | None = None
|
|
||||||
|
|
||||||
# parser state:
|
|
||||||
in_changed: bool = False
|
|
||||||
in_node: bool = False
|
|
||||||
in_vol: bool = False
|
|
||||||
in_mute: bool = False
|
|
||||||
|
|
||||||
def feed_line(self, line: str) -> float | None:
|
|
||||||
""" consume a line and *maybe* return the volume """
|
|
||||||
|
|
||||||
logger.debug("got pw-mon line: %s", line.rstrip())
|
|
||||||
line = line.strip()
|
|
||||||
|
|
||||||
if line.startswith("changed:"):
|
|
||||||
self.in_changed = True
|
|
||||||
elif line.startswith("added:") or line.startswith("removed:"):
|
|
||||||
self.in_changed = False
|
|
||||||
elif line.startswith("type: "):
|
|
||||||
self.in_node = line.startswith("type: PipeWire:Interface:Node")
|
|
||||||
logger.debug("parsed `type:` %s %d", line, self.in_node)
|
|
||||||
elif line.startswith("Prop: "):
|
|
||||||
# which of the *Volumes params we read is unclear.
|
|
||||||
# alternative to this is to just detect the change, and then cal wpctl get-volume @DEFAULT_AUDIO_SINK@
|
|
||||||
self.in_vol = line.startswith("Prop: key Spa:Pod:Object:Param:Props:channelVolumes")
|
|
||||||
self.in_mute = line.startswith("Prop: key Spa:Pod:Object:Param:Props:softMute")
|
|
||||||
logger.debug("parsed `Prop:` %s %d", line, self.in_vol)
|
|
||||||
elif line.startswith("Float ") and self.in_changed and self.in_node and self.in_vol:
|
|
||||||
value = float(line[len("Float "):])
|
|
||||||
self.feed_volume(value)
|
|
||||||
elif line.startswith("Bool ") and self.in_changed and self.in_node and self.in_mute:
|
|
||||||
value = line[len("Bool "):] == "true"
|
|
||||||
self.feed_mute(value)
|
|
||||||
|
|
||||||
def feed_volume(self, new: float) -> None:
|
|
||||||
logger.debug("feed volume: %f -> %f", self.last_volume or 0.0, new)
|
|
||||||
self.last_volume = new
|
|
||||||
self.check_effective_volume()
|
|
||||||
|
|
||||||
def feed_mute(self, new: bool) -> None:
|
|
||||||
logger.debug("feed mute: %d -> %d", self.last_mute or False, new)
|
|
||||||
self.last_mute = new
|
|
||||||
self.check_effective_volume()
|
|
||||||
|
|
||||||
def check_effective_volume(self) -> None:
|
|
||||||
eff_volume = 0.0 if self.last_mute else self.last_volume
|
|
||||||
if eff_volume != self.last_effective_volume:
|
|
||||||
logger.info("new effective volume: %f", eff_volume)
|
|
||||||
self.on_new_volume(eff_volume)
|
|
||||||
self.last_effective_volume = eff_volume
|
|
||||||
|
|
||||||
|
|
||||||
class PwMonWobConsumer(PwMonConsumer):
|
|
||||||
def __init__(self):
|
|
||||||
self.sock_name = os.path.join(
|
|
||||||
os.environ.get("XDG_RUNTIME_DIR", "/run"),
|
|
||||||
os.environ.get("WOBSOCK_NAME", "wob.sock"),
|
|
||||||
)
|
|
||||||
self.wob_sock = open(self.sock_name, "w")
|
|
||||||
|
|
||||||
def on_new_volume(self, vol: float) -> None:
|
|
||||||
# pipewire volume is between 0 and 3.375.
|
|
||||||
# wob is between 0 - 1, or 1 - 2 if overdriven.
|
|
||||||
# idk where vol ** (1/3) comes from, but it precisely matches what wpctl shows,
|
|
||||||
# getting the range to 0.00 - 1.50 with precise 0.05 increments.
|
|
||||||
int_vol = int(round(vol ** 0.3333 * 100))
|
|
||||||
logger.info("writing to %s: %d", self.sock_name, int_vol)
|
|
||||||
self.wob_sock.write(f"{int_vol}\n")
|
|
||||||
self.wob_sock.flush()
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
logging.basicConfig()
|
|
||||||
logging.getLogger().setLevel(logging.INFO)
|
|
||||||
if os.environ.get("WOB_VERBOSE", "") == "1":
|
|
||||||
logging.getLogger().setLevel(logging.DEBUG)
|
|
||||||
|
|
||||||
consumer = PwMonWobConsumer()
|
|
||||||
proc = subprocess.Popen(["pw-mon"], stdout=subprocess.PIPE)
|
|
||||||
for line in iter(proc.stdout.readline, b''):
|
|
||||||
consumer.feed_line(line.decode("utf-8"))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
Reference in New Issue
Block a user