-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
get_peak_sample #73
Comments
I'd try something like this:
Two issues exhibited here:
Not sure if I understand the problem correctly though. |
Yes, I am using multiple threads. One for reading pulse events, one for reading sink sound level with get_subscribe_peak, and another one for reading source sound level with get_subscribe_peak. Everytime I run get_subscribe_peak it emits many sink and source change events on the index values i'm interested in. I need to run get_subscribe_peak multiple times in a second to display a smooth sound meter. So unfortunately, with your solution I would be checking port/profile for changes multiple times a second, which isn't efficient. I would be better off polling for changes every one second instead. I wish the pulseaudio client name came across in the events, then I could use the client name to ignore the events generated by get_subscribe_peak. |
You can debounce these events easily - i.e. upon receiving event, check it once, delay next check to 200ms minimum. |
With threads or asyncio, I'd probably do it via something like:
...where you run |
Sorry I meant to say get_peak_sample rather than get_subscribe_peak in my last reply. I'm using threading using the PySide6 library (Qt6). I'm trying to understand your example. This is what my thread looks like that runs get_peak_sample() for reading the sound levels of a sink. I need to call get_peak_sample() multiple times a second to get the volume level between 0.0 and 1.0. But don't want the pulseaudio events generated from it. I understand that this is what debouncing does, I am just not sure where to intercept the events in order to delay them before reading them with event_callback_set(print_events).
Where are you suggesting that I can debounce the events that are generated from me runing get_peak_sample in my example? |
What generates events doesn't really matter for the purposes of such debouncing, idea is only to enforce min 200ms interval between any checks via simple time.sleep(), regardless of why things change in pulse rapidly. Pretty sure if you'll look at the code that handles pulse events or get to implementing it, you'll figure it out, regardless of whether it'll be anything like my example :) |
That sounds like a bit strange thing to do, but idk what the app does, so maybe necessary.
No no, it doesn't suppress events or whatever, only supposed to delay the check for port/profile that you do in response for these, or at least that was the idea in my example. |
Yes, understood. My app is simply displaying a bar like this when music is playing: Should I not be using get_peak_sample? |
Hm, yeah, that's kinda what pavucontrol tool does too. It uses same thing as get_peak_sample, but it doesn't ever close that sampling stream, which I guess is how to best do it in your case as well. Would be way more efficient and none of those pesky change events! |
Yes that would be great! I'll look into rewriting that function to avoid all those change events. Thanks! |
Any ideas on how to change this function to run forever? It uses c.pa.stream_set_read_callback(s, read_cb, None) to point to a callback function.
|
I'd do it something like this:
But you didn't seem to even try to do anything there, so idk if getting more examples will help in the same way, unless they fit into your code exactly :) |
This is very helpful, it works great for sinks, thanks! I have tried adapting your example to work for a source (microphone), it works properly for about 5 seconds and then PulseAudio suspends the source. See here: https://i.imgur.com/tMrZuBy.gif Here is the log output of PulseAudio, when it stops working:
It seems PulseAudio thinks the source/microphone is idle, so it suspends it. This happens even when I am actively talking into the microphone. If I remove c.PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND from the call to c.pa.stream_connect_record, then it works properly and does not suspend the source. I just don't know if this is the best way. See below for how I have changed your example to work with a source.
|
Hm, I think maybe it suspends the source because of some other stream flags in combination with this one. But you don't have to guess, just check pulseadio code, like grep for that exact "PA_STREAM_DONT_INHIBIT" thing which will get you to a place - likely in somefile like source.c - with couple if's which control all the logic and can see exactly why/when stuff gets suspended. |
I already encountered that issue in pulsectl-asyncio and recently added an option to set this flag optionally. The PulseAudio flag actually does exactly what it says: Usually, PulseAudio suspends sources and sinks, when for a few seconds no stream is running. Each running stream, related to that source/sink, will inhibit the suspension, unless it has the Typically, you want to inhibit suspension when monitoring source devices (so the source doesn't get suspended if no other application is listening to it), but you don't want to inhibit suspension when monitoring a sink's monitor source (so the sink can get suspended when no application is playing audio to it). |
Ah, and I guess @RESP3CT88 knows about it, as they've filed that issue as well :) |
Thanks a lot guys! Your tips are helpful and I'm very grateful for the support. Btw, both of your projects are so amazing I have used both :) |
I am using get_peak_sample() to display the sound level of a playing sample.
But I notice that everytime it runs it floods the pulseaudio events with:
When an actual sink/source port is changed it also sends similar event like so:
I need a reliable way to determine when a sink/source port and card profile is updated .
The text was updated successfully, but these errors were encountered: