I'm trying to create a script to monitor a pipewire audio source, and provide outputs relating to the "percentage" of the volume. Since I'm using pipewire and wireplumber, I decided to use pw-mon, provided by pipewire for monitoring, and wpctl, provided by wireplumber to accomplish this.
pw-mon | while read; do
# wpctl returns output as Volume: 0.00 [MUTED] where 0.00 is the volume, and [MUTED] is irrelevant for our case.
# I process via cut to get the second field.
awk '{print $1 * 100}' <<< $(wpctl get-volume @DEFAULT_AUDIO_SINK@ | cut -d" " -f2)
done
The main issue with this is that pw-mon returns many stdout responses about their device state, and as a side-effect, awk has to process tens of times because while read gets a lot of lines from pw-mon stdout. I want to prevent this and only print out once, so essentially squash all the stdout from pw-mon, have the while run only once because of that, and then in-turn process my awk only once as well. Problem is I'm not sure how to accomplish this.
I tried to use tr -d "\r\n" from https://stackoverflow.com/a/68091645/9091276, but while read no longer runs (I made sure of this by doing while read l; do echo $l; done). I thought to add a sleep in the while loop, but that doesn't make sense because it'll just delay the reading of the pw-mon stdout lines rather than hold back on reading all of them.
Any thoughts or ideas of what I can do? For clarity, here's some output from pw-mon so you can see what happens per event callback from it: https://hastebin.com/share/agajayosoq.rust (its not rust idk why it says that).
EDIT: Let me clarify what I'm trying to do
pw-mon fires some audio device data into the stdout every time it detects a change to the audio device (volume up/down/mute). Otherwise, pw-mon does NOT output any data. The problem is every time a change occurs, pw-mon dumps a ton of lines of data to stdout, which means, with my current script, itll fire the while read multiple times. That is not what I want, I want to only run the "awk" portion once every time a change occurs. My idea was to squash all my stdout into one line, so while read would only fire once, but doing pw-mon | tr -d "\r\n" | while read did not work, for some reason the while read would not fire.
EDIT 2: sample output of pw-mon:
type: PipeWire:Interface:Core
cookie: 2956247259
user-name: "frontear"
host-name: "frontear-net"
version: "0.3.81"
name: "pipewire-0"
* properties:
* config.name = "pipewire.conf"
* link.max-buffers = "16"
* core.daemon = "true"
* core.name = "pipewire-0"
* module.jackdbus-detect = "true"
* module.x11.bell = "true"
* module.access = "true"
* cpu.max-align = "64"
* default.clock.rate = "48000"
* default.clock.quantum = "1024"
* default.clock.min-quantum = "32"
* default.clock.max-quantum = "2048"
* default.clock.quantum-limit = "8192"
* default.video.width = "640"
* default.video.height = "480"
* default.video.rate.num = "25"
* default.video.rate.denom = "1"
* log.level = "2"
* clock.power-of-two-quantum = "true"
* mem.warn-mlock = "false"
* mem.allow-mlock = "true"
* settings.check-quantum = "false"
* settings.check-rate = "false"
* object.id = "0"
* object.serial = "0"
added:
id: 0
permissions: r-xm-
type: PipeWire:Interface:Core (version 4)
properties:
object.serial = "0"
core.name = "pipewire-0"
added:
... (omitted for brevity)
* id:15 (Spa:Enum:ParamId:Latency)
Object: size 176, type Spa:Pod:Object:Param:Latency (262155), id Spa:Enum:ParamId:Latency (15)
Prop: key Spa:Pod:Object:Param:Latency:direction (1), flags 00000000
Id 0 (Spa:Enum:Direction:Input)
Prop: key Spa:Pod:Object:Param:Latency:minQuantum (2), flags 00000000
Float 0.000000
Prop: key Spa:Pod:Object:Param:Latency:maxQuantum (3), flags 00000000
Float 0.000000
Prop: key Spa:Pod:Object:Param:Latency:minRate (4), flags 00000000
Int 0
Prop: key Spa:Pod:Object:Param:Latency:maxRate (5), flags 00000000
Int 0
Prop: key Spa:Pod:Object:Param:Latency:minNs (6), flags 00000000
Long 0
Prop: key Spa:Pod:Object:Param:Latency:maxNs (7), flags 00000000
Long 0
properties:
port.id = "0"
port.direction = "out"
object.path = "xdg-desktop-portal-hyprland:capture_0"
port.name = "capture_1"
port.alias = "xdg-desktop-portal-hyprland:capture_1"
node.id = "74"
object.id = "75"
object.serial = "377"
pw-monwould generate. Given this is audio data, it seems there would be a time component, but that is not clear. So you want squash 24.secs/mins/hrs(+?) into one final output? I would go for a sqwashed output that also included the time range, and possibly the number of samples squashed. Also, try justtr -d "\r". Good luck!while readis expecting a\nline ending to trigger the read. I read your description the first time, and to MHO, your Edit doesn't add much to that description. "Avoid verbal descriptions"! show us your input data (just enough for one "iteration") and the required output from that same data.pw-mongives in a hastebin link above. This entire blurb of data contains information for when the monitoring app first runs + waits for ONE event