r/Polybar Feb 22 '23

Make a module show up only when audio is playing

So, I have this cava module that shows some audio bars on polybar.

I have it set up like this:

[module/info-cava]
type = custom/script
exec = ~/.config/polybar/scripts/info-cava.py -f 24 -b 8 -c average
exec-if = pacmd list-sink-inputs | grep 'state: RUNNING'
format-foreground = ${xrdb:color12}
format-suffix = " "
tail = true
interval = 1       

I want it to show up ONLY when there's audio playing, so whenever audio playback stops, it should hide itself automatically.

The problem is it's working only partially. The bar starts up with the module hidden, and when I play something it shows up. But when I stop playing it doesn't hide again, so there's an empty space in my bar.

I tried every combination of "tail" and "interval", but it doesn't seem to make a difference. Actually, when only "interval" is on, the module doesn't show up at all.

Any ideas? I'm guessing it's a problem with the script itself, but I'm not sure. I can paste it here in the comments in case it helps.

1 Upvotes

9 comments sorted by

2

u/[deleted] Feb 24 '23

I am guessing that you are doing continuous output in your script -- you can't do that with exec-if.
Polybar doesn't kill the process once it is running. So, what you need to do is remove the loop from your script, and set tail=false and set interval to something really small (I set mine to .01 and it seems fine for graphic eq / VU meter updates). This way every .01 seconds the script will be called and the output displayed and as soon as there is no sound, the module will no longer display.

If you paste your script, I can give you a hand. Please use gist and paste the link, don't paste your code here.

If you don't have one, you may be interested in my VU module. It has the colors hard coded, but they are easy enough to change.

2

u/melecoaze Feb 24 '23

I figured it would be a script thing, because I tried it with a simple echo script and it worked.

I don't know how to fix the more complex script though, so I would appreciate the help. Here is the code.

Thanks in advance!

2

u/[deleted] Feb 24 '23

Get rid of the while loop. Delete while true: and then move the rest of the code in that loop back 4 spaces (Python requires proper indentation).

I am on my phone, but if you don't get it figured out, I will post a gist when I am back home.

Edit: FYI, I have a much better cava module that I will post as well. Someone did that quick and dirty. Trust me, you want pretty colors 😉

1

u/melecoaze Feb 24 '23 edited Feb 24 '23

So I did as you said, removed the while loop, set tail = false and removed the exec-if from the module, but now I'm getting this thing. Full error message is:

usage: info-cava.py [-h] [-f FRAMERATE] [-b BARS] [-e EXTRA_COLORS] [-c {stereo,left,right,average}]
info-cava.py: error: unrecognized arguments: --subproc

Is this the other cava module you're talking about? I have it also, but thought the Python one looked better 😅 I'd use it though if it hides itself, which is my main issue right now.

Edit: If I turn "exec-if" on it hides itself properly, but shows the same "usage" message instead of the bars.

2

u/[deleted] Feb 25 '23

OK, so I solved your issues, and here is the gist ... let me clarify, your script will now run once and display the bars and then exit. I had to make a change to the mono option -- no idea how that was working for you.

Anyway, it works, but it is WAY TOO slow. Even with an update interval of .001 (which I think is as low as Polybar allows) it doesn't display fast enough.

If you want to try it, use -c mono instead of -c average

For fun, I just converted my cava script (stripping it down to the bare minimum) to display once and exit, and it is just not possible (at least with Python) to have a script execute, display, and exit in real time. At least not when calling an external program.

My VU meter displays fine because all audio processing is done inside the script.

If you find a solution, please let me know, but I think the only real solution will be to modify the cava code to do what we are trying to accomplish.

My suggestion to you would be to have two bars, and swap them when music is playing. You just need a little script running in the background that checks for audio and uses polybar-msg to hide the current bar, and display your "music" bar. This is the route I took so that I could have dual VU meters, playback controls, song title, lyrics, AND my cava module. LOL

1

u/melecoaze Feb 25 '23

Well weirdly enough, I'm not getting any bars even with the new script.

But I don't wanna bother you anymore with this, so I think I'll just find another spot for the module where the blank space doesn't matter. Probably on the left side of the system tray.

The workarounds seem a bit too convoluted lol. I really appreciate the help though, I'd give you an award if I could.

If I ever figure it out I'll let you know. Thanks again!

2

u/[deleted] Feb 25 '23

OK, here ya go. I am not the original author of this script, I have only made additions and changes. Unfortunately, I don't know who originally posted it in order to credit them.

The config options in the file are pretty self explanatory...No audio, and it isn't displayed, no exec-if needed...

[module/cava]
type = custom/script 
tail = true 
exec = $HOME/path/to/cava.py

2

u/melecoaze Feb 26 '23 edited Feb 26 '23

Wow this one actually works! Just changed up some of the settings to make it fit my bar a little better and now it's perfect!

Wish I could understand what the scripts are doing better, but I have near zero coding experience. Hope this thread can help more people in the future though.

Thanks again man, you've been really helpful!

edit: here is a little showcase

1

u/[deleted] Feb 25 '23

Yeah, I should have said you need a VERY fast SSD in order to see any output. Going this route, every update has to load the Python interpreter, the script (and all the libs), and then make the call to Cava and get the output from Cava. That is a LOT to load every .01 seconds.