Skip to content
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

connected microphone false positive #133

Closed
cromelex opened this issue Oct 31, 2024 · 9 comments · Fixed by #135
Closed

connected microphone false positive #133

cromelex opened this issue Oct 31, 2024 · 9 comments · Fixed by #135
Labels
bug Something isn't working

Comments

@cromelex
Copy link
Contributor

What type of installation are you running?

Desktop

Which Linux OS are you using?

aurora-dx:stable (Fedora 40)

Which version of LNXLink has the issue?

2024.10.1 (non-flatpak)

Describe the problem

After adding a new webcam with built in Microphone, lnxlink always reports "Microphone Used" as On.

The microphone isn't actually always on. When it is on, I get a "Microphone" symbol on the KDE system tray. However lnxlink fails to capture this correctly.

If I run a pactl list short source-outputs while the mic isn't being used I get this:

❯ pactl list short source-outputs
10239 4294967295 6357 PipeWire float32le 1ch 25Hz
10275 4294967295 6357 PipeWire float32le 1ch 25Hz
11248 4294967295 6357 PipeWire float32le 1ch 25Hz
11314 4294967295 6357 PipeWire float32le 1ch 25Hz
11961 4294967295 6357 PipeWire float32le 1ch 25Hz

If I run a pactl list short source-outputs while the mic is actually being used, I get the below

❯ pactl list short source-outputs
10239 4294967295 6357 PipeWire float32le 1ch 25Hz
10275 4294967295 6357 PipeWire float32le 1ch 25Hz
11248 4294967295 6357 PipeWire float32le 1ch 25Hz
11314 4294967295 6357 PipeWire float32le 1ch 25Hz
11961 4294967295 6357 PipeWire float32le 1ch 25Hz
12095 11975 12050 PipeWire s16le 2ch 48000Hz

So is there any potential way to capture this info so as to avoid the false positive issue?
12095 11975 12050 PipeWire s16le 2ch 48000Hz

All the false positives have an application.name = "", so empty name in pactl list source-outputs

Alternatively, is there a way to expose the application.name property from the pactl list source-outputs ?
For my use in Home Assistant, I just need to be able to know I am in a meeting. The Zoom app using the microphone as per below is sufficient.

	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		pipewire.access.portal.app_id = "us.zoom.Zoom"
		media.category = "Manager"
		pipewire.client.access = "flatpak"
		application.name = "ZOOM VoiceEngine"

I looked at the old #54 and not sure if this is a bug or something you'd need to improve.

Thank you in advance.

Additional context

No response

Configuration

No response

Logs

No response

@cromelex cromelex added the bug Something isn't working label Oct 31, 2024
@bkbilly
Copy link
Owner

bkbilly commented Nov 1, 2024

Thanks for pointing this out.
I had a similar issue when I was using the NoiseTorch.
By filtering by application used as you suggested, I don't get these false positives.

I've pushed an update for this and it will be available at the next release.

@cromelex
Copy link
Contributor Author

cromelex commented Nov 1, 2024

Cheers, appreciate it

@bkbilly
Copy link
Owner

bkbilly commented Nov 4, 2024

I've published the new release, so you can upgrade to try out this feature.

@cromelex
Copy link
Contributor Author

cromelex commented Nov 4, 2024

I've published the new release, so you can upgrade to try out this feature.

Thank you, I can confirm this has fixed it for me!

@cromelex cromelex closed this as completed Nov 4, 2024
@cromelex cromelex reopened this Nov 8, 2024
@cromelex
Copy link
Contributor Author

cromelex commented Nov 8, 2024

I am seeing the false positive again today on 2024.11.0 for some reason.
(did reboot the machine, it's an atomic distribution so the OS would have been updated with a new image, wondering if that changes anything that could cause it to have a false positive again).
The last few days it had been working without issue.

This is what I see while the mic is off (ie, the false positive).

❯ pactl list source-outputs
Source Output #11058
	Driver: PipeWire
	Owner Module: n/a
	Client: 4665
	Source: 4294967295
	Sample Specification: float32le 1ch 25Hz
	Channel Map: mono
	Format: pcm, format.sample_format = "\"float32le\""  format.rate = "25"  format.channels = "1"  format.channel_map = "\"mono\""
	Corked: yes
	Mute: no
	Volume: mono: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: PipeWire
	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		application.name = ""
		application.id = "org.kde.plasma-pa"
		application.icon_name = ""
		application.process.id = "487908"
		application.process.user = "user"
		application.process.host = "host"
		application.process.binary = "plasmashell"
		application.language = "en_IE.UTF-8"
		window.x11.display = ":0"
		application.process.machine_id = "322c54d45d2e4a8cade3bfdb0e604ed6"
		application.process.session_id = "5"
		media.name = "PlasmaPA-VolumeMeter"
		node.rate = "1/25"
		node.latency = "1/25"
		stream.monitor = "true"
		target.object = "10771"
		stream.is-live = "true"
		node.name = ""
		node.want-driver = "true"
		node.autoconnect = "true"
		node.dont-reconnect = "true"
		media.class = "Stream/Input/Audio"
		resample.peaks = "true"
		channelmix.normalize = "true"
		port.ignore-latency = "true"
		adapt.follower.spa-node = ""
		object.register = "false"
		factory.id = "6"
		clock.quantum-limit = "8192"
		factory.mode = "merge"
		audio.adapt.follower = ""
		library.name = "audioconvert/libspa-audioconvert"
		client.id = "82"
		object.id = "111"
		object.serial = "11058"
		pulse.attr.maxlength = "4194304"
		pulse.attr.fragsize = "4"
		module-stream-restore.id = "source-output-by-application-id:org.kde.plasma-pa"

Let me know if there is anything else I can provide to help debug this.

@cromelex
Copy link
Contributor Author

cromelex commented Nov 8, 2024

Update, I checked the MQTT and the topic doesn't seem to be getting updated at all (the "application" attribute isn't changing).

{"is_used": "ON", "application": ""}

I've run pactl list source-outputs again while Zoom is using the microphone and this is what I see.

❯ pactl list source-outputs
Source Output #11058
	Driver: PipeWire
	Owner Module: n/a
	Client: 4665
	Source: 4294967295
	Sample Specification: float32le 1ch 25Hz
	Channel Map: mono
	Format: pcm, format.sample_format = "\"float32le\""  format.rate = "25"  format.channels = "1"  format.channel_map = "\"mono\""
	Corked: yes
	Mute: no
	Volume: mono: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: PipeWire
	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		application.name = ""
		application.id = "org.kde.plasma-pa"
		application.icon_name = ""
		application.process.id = "487908"
		application.process.user = "user"
		application.process.host = "aurora"
		application.process.binary = "plasmashell"
		application.language = "en_IE.UTF-8"
		window.x11.display = ":0"
		application.process.machine_id = "322c54d45d2e4a8cade3bfdb0e604ed6"
		application.process.session_id = "5"
		media.name = "PlasmaPA-VolumeMeter"
		node.rate = "1/25"
		node.latency = "1/25"
		stream.monitor = "true"
		target.object = "10771"
		stream.is-live = "true"
		node.name = ""
		node.want-driver = "true"
		node.autoconnect = "true"
		node.dont-reconnect = "true"
		media.class = "Stream/Input/Audio"
		resample.peaks = "true"
		channelmix.normalize = "true"
		port.ignore-latency = "true"
		adapt.follower.spa-node = ""
		object.register = "false"
		factory.id = "6"
		clock.quantum-limit = "8192"
		factory.mode = "merge"
		audio.adapt.follower = ""
		library.name = "audioconvert/libspa-audioconvert"
		client.id = "82"
		object.id = "111"
		object.serial = "11058"
		pulse.attr.maxlength = "4194304"
		pulse.attr.fragsize = "4"
		module-stream-restore.id = "source-output-by-application-id:org.kde.plasma-pa"

Source Output #14241
	Driver: PipeWire
	Owner Module: n/a
	Client: 4665
	Source: 4294967295
	Sample Specification: float32le 1ch 25Hz
	Channel Map: mono
	Format: pcm, format.sample_format = "\"float32le\""  format.rate = "25"  format.channels = "1"  format.channel_map = "\"mono\""
	Corked: yes
	Mute: no
	Volume: mono: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: PipeWire
	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		application.name = ""
		application.id = "org.kde.plasma-pa"
		application.icon_name = ""
		application.process.id = "487908"
		application.process.user = "user"
		application.process.host = "aurora"
		application.process.binary = "plasmashell"
		application.language = "en_IE.UTF-8"
		window.x11.display = ":0"
		application.process.machine_id = "322c54d45d2e4a8cade3bfdb0e604ed6"
		application.process.session_id = "5"
		media.name = "PlasmaPA-VolumeMeter"
		node.rate = "1/25"
		node.latency = "1/25"
		stream.monitor = "true"
		target.object = "10771"
		stream.is-live = "true"
		node.name = ""
		node.want-driver = "true"
		node.autoconnect = "true"
		node.dont-reconnect = "true"
		media.class = "Stream/Input/Audio"
		resample.peaks = "true"
		channelmix.normalize = "true"
		port.ignore-latency = "true"
		adapt.follower.spa-node = ""
		object.register = "false"
		factory.id = "6"
		clock.quantum-limit = "8192"
		factory.mode = "merge"
		audio.adapt.follower = ""
		library.name = "audioconvert/libspa-audioconvert"
		client.id = "82"
		object.id = "42"
		object.serial = "14241"
		pulse.attr.maxlength = "4194304"
		pulse.attr.fragsize = "4"
		module-stream-restore.id = "source-output-by-application-id:org.kde.plasma-pa"

Source Output #14242
	Driver: PipeWire
	Owner Module: n/a
	Client: 4665
	Source: 4294967295
	Sample Specification: float32le 1ch 25Hz
	Channel Map: mono
	Format: pcm, format.sample_format = "\"float32le\""  format.rate = "25"  format.channels = "1"  format.channel_map = "\"mono\""
	Corked: yes
	Mute: no
	Volume: mono: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: PipeWire
	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		application.name = ""
		application.id = "org.kde.plasma-pa"
		application.icon_name = ""
		application.process.id = "487908"
		application.process.user = "user"
		application.process.host = "aurora"
		application.process.binary = "plasmashell"
		application.language = "en_IE.UTF-8"
		window.x11.display = ":0"
		application.process.machine_id = "322c54d45d2e4a8cade3bfdb0e604ed6"
		application.process.session_id = "5"
		media.name = "PlasmaPA-VolumeMeter"
		node.rate = "1/25"
		node.latency = "1/25"
		stream.monitor = "true"
		target.object = "13493"
		stream.is-live = "true"
		node.name = ""
		node.want-driver = "true"
		node.autoconnect = "true"
		node.dont-reconnect = "true"
		media.class = "Stream/Input/Audio"
		resample.peaks = "true"
		channelmix.normalize = "true"
		port.ignore-latency = "true"
		adapt.follower.spa-node = ""
		object.register = "false"
		factory.id = "6"
		clock.quantum-limit = "8192"
		factory.mode = "merge"
		audio.adapt.follower = ""
		library.name = "audioconvert/libspa-audioconvert"
		client.id = "82"
		object.id = "87"
		object.serial = "14242"
		module-stream-restore.id = "source-output-by-application-id:org.kde.plasma-pa"

Source Output #17377
	Driver: PipeWire
	Owner Module: n/a
	Client: 17347
	Source: 4649
	Sample Specification: s16le 2ch 48000Hz
	Channel Map: front-left,front-right
	Format: pcm, format.sample_format = "\"s16le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
	Corked: no
	Mute: no
	Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: PipeWire
	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		pipewire.access.portal.app_id = "us.zoom.Zoom"
		media.category = "Manager"
		pipewire.client.access = "flatpak"
		application.name = "ZOOM VoiceEngine"
		application.process.id = "4"
		application.process.user = "user"
		application.process.host = "aurora"
		application.process.binary = "zoom"
		application.language = "en_IE.UTF-8"
		window.x11.display = ":0"
		application.process.machine_id = "322c54d45d2e4a8cade3bfdb0e604ed6"
		application.process.session_id = "5"
		media.name = "recStream"
		node.rate = "1/48000"
		node.latency = "480/48000"
		target.object = "alsa_input.usb-046d_MX_Brio_2428ZB218S28-04.pro-input-0"
		stream.is-live = "true"
		node.name = "ZOOM VoiceEngine"
		node.want-driver = "true"
		node.autoconnect = "true"
		media.class = "Stream/Input/Audio"
		adapt.follower.spa-node = ""
		object.register = "false"
		factory.id = "6"
		clock.quantum-limit = "8192"
		factory.mode = "merge"
		audio.adapt.follower = ""
		library.name = "audioconvert/libspa-audioconvert"
		client.id = "60"
		object.id = "91"
		object.serial = "17377"
		pulse.attr.maxlength = "146880"
		pulse.attr.fragsize = "1920"
		module-stream-restore.id = "source-output-by-application-name:ZOOM VoiceEngine"

I am not sure if your code is only going through the first output or if it is misreading application.name = "" as not none?

As this worked when I first tested I didn't check the mqtt attribute to see if the app name was being correctly reported - my HomeAssistant setup doesn't store the attributes in the history so I can't go back and find if that was working or not.

@cromelex
Copy link
Contributor Author

cromelex commented Nov 8, 2024

Right, so I restarted and now my source-outputs is blank, and lnxlink is reporting correctly.

❯ pactl list source-outputs

~ 

MQTT
```{"is_used": "OFF", "application": null}``


I open Zoom, everything updates as expected:

❯ pactl list source-outputs
Source Output #191
	Driver: PipeWire
	Owner Module: n/a
	Client: 189
	Source: 49
	Sample Specification: s16le 2ch 48000Hz
	Channel Map: front-left,front-right
	Format: pcm, format.sample_format = "\"s16le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
	Corked: no
	Mute: no
	Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: PipeWire
	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		pipewire.access.portal.app_id = "us.zoom.Zoom"
		media.category = "Manager"
		pipewire.client.access = "flatpak"
		application.name = "ZOOM VoiceEngine"
		application.process.id = "4"
		application.process.user = "user"
		application.process.host = "aurora"
		application.process.binary = "zoom"
		application.language = "en_IE.UTF-8"
		window.x11.display = ":0"
		application.process.machine_id = "322c54d45d2e4a8cade3bfdb0e604ed6"
		application.process.session_id = "2"
		media.name = "recStream"
		node.rate = "1/48000"
		node.latency = "480/48000"
		target.object = "alsa_input.usb-046d_MX_Brio_2428ZB218S28-04.pro-input-0"
		stream.is-live = "true"
		node.name = "ZOOM VoiceEngine"
		node.want-driver = "true"
		node.autoconnect = "true"
		media.class = "Stream/Input/Audio"
		adapt.follower.spa-node = ""
		object.register = "false"
		factory.id = "6"
		clock.quantum-limit = "8192"
		factory.mode = "merge"
		audio.adapt.follower = ""
		library.name = "audioconvert/libspa-audioconvert"
		client.id = "84"
		object.id = "85"
		object.serial = "191"
		pulse.attr.maxlength = "146880"
		pulse.attr.fragsize = "1920"
		module-stream-restore.id = "source-output-by-application-name:ZOOM VoiceEngine"

MQTT:
{"is_used": "ON", "application": "ZOOM VoiceEngine"}

I close zoom and pactl list source-outputs becomes empty again, and lnxlink updates correctly.

{"is_used": "OFF", "application": null}


Once I connect my bluetooth headset, it breaks. Even after disconnecting, when the microphone is not being used, it leaves these "phantom" entries that cause the false positive.

application.name = ""

❯ pactl list source-outputs
Source Output #407
	Driver: PipeWire
	Owner Module: n/a
	Client: 77
	Source: 4294967295
	Sample Specification: float32le 1ch 25Hz
	Channel Map: mono
	Format: pcm, format.sample_format = "\"float32le\""  format.rate = "25"  format.channels = "1"  format.channel_map = "\"mono\""
	Corked: yes
	Mute: no
	Volume: mono: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: PipeWire
	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		application.name = ""
		application.id = "org.kde.plasma-pa"
		application.icon_name = ""
		application.process.id = "9133"
		application.process.user = "user"
		application.process.host = "aurora"
		application.process.binary = "plasmashell"
		application.language = "en_IE.UTF-8"
		window.x11.display = ":0"
		application.process.machine_id = "322c54d45d2e4a8cade3bfdb0e604ed6"
		application.process.session_id = "2"
		media.name = "PlasmaPA-VolumeMeter"
		node.rate = "1/25"
		node.latency = "1/25"
		stream.monitor = "true"
		target.object = "97"
		stream.is-live = "true"
		node.name = ""
		node.want-driver = "true"
		node.autoconnect = "true"
		node.dont-reconnect = "true"
		media.class = "Stream/Input/Audio"
		resample.peaks = "true"
		channelmix.normalize = "true"
		port.ignore-latency = "true"
		adapt.follower.spa-node = ""
		object.register = "false"
		factory.id = "6"
		clock.quantum-limit = "8192"
		factory.mode = "merge"
		audio.adapt.follower = ""
		library.name = "audioconvert/libspa-audioconvert"
		client.id = "62"
		object.id = "77"
		object.serial = "407"
		module-stream-restore.id = "source-output-by-application-id:org.kde.plasma-pa"

Source Output #482
	Driver: PipeWire
	Owner Module: n/a
	Client: 77
	Source: 4294967295
	Sample Specification: float32le 1ch 25Hz
	Channel Map: mono
	Format: pcm, format.sample_format = "\"float32le\""  format.rate = "25"  format.channels = "1"  format.channel_map = "\"mono\""
	Corked: yes
	Mute: no
	Volume: mono: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 0 usec
	Source Latency: 0 usec
	Resample method: PipeWire
	Properties:
		client.api = "pipewire-pulse"
		pulse.server.type = "unix"
		application.name = ""
		application.id = "org.kde.plasma-pa"
		application.icon_name = ""
		application.process.id = "9133"
		application.process.user = "user"
		application.process.host = "aurora"
		application.process.binary = "plasmashell"
		application.language = "en_IE.UTF-8"
		window.x11.display = ":0"
		application.process.machine_id = "322c54d45d2e4a8cade3bfdb0e604ed6"
		application.process.session_id = "2"
		media.name = "PlasmaPA-VolumeMeter"
		node.rate = "1/25"
		node.latency = "1/25"
		stream.monitor = "true"
		target.object = "97"
		stream.is-live = "true"
		node.name = ""
		node.want-driver = "true"
		node.autoconnect = "true"
		node.dont-reconnect = "true"
		media.class = "Stream/Input/Audio"
		resample.peaks = "true"
		channelmix.normalize = "true"
		port.ignore-latency = "true"
		adapt.follower.spa-node = ""
		object.register = "false"
		factory.id = "6"
		clock.quantum-limit = "8192"
		factory.mode = "merge"
		audio.adapt.follower = ""
		library.name = "audioconvert/libspa-audioconvert"
		client.id = "62"
		object.id = "123"
		object.serial = "482"
		module-stream-restore.id = "source-output-by-application-id:org.kde.plasma-pa"

@cromelex
Copy link
Contributor Author

cromelex commented Nov 8, 2024

@bkbilly summary here:

Once I connect my bluetooth headset, it breaks. Even after disconnecting, when the microphone is not being used, it leaves these "phantom" entries in pactl list source-outputs that cause the false positive.

application.name = ""

As it is, the "phantom entry" seems to populate first on the order than the actual "true" entries. As such the mic is permanently reporting {"is_used": "ON", "application": ""} in lnxlink, regardless of being in use or not.

Do you think you can account for those application.name = "" and only take the applications/outputs in case the application.name is not equal to "" ? That is, keep going through the list of outputs until you get a valid entry?

Hope the above helps!
Thank you in advance

@cromelex
Copy link
Contributor Author

cromelex commented Nov 8, 2024

@bkbilly sorry for the spam but I think I found a solution.

from your original code

            for output in data:
                app_name = output.get("properties", {}).get("application.name")
                if app_name is not None:
                    return {"is_used": "ON", "application": app_name}
            return {"is_used": "OFF", "application": None}

I changed it so it checks for a valid, non app_name="" output before returning the app name.
I modified the .py and reloaded the lnxlink.service.

            for output in data:
                app_name = output.get("properties", {}).get("application.name")
                if app_name and app_name != "":
                    return {"is_used": "ON", "application": app_name}
            return {"is_used": "OFF", "application": None}

This seems to be working for me, both for no outputs and the "phantom" output returning None, and returning the valid app_name even if it's not the first in the order.

I am not a dev so if you want to have a look and see if this make sense, and make the change for future versions?

Thanks,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants