wwmm / easyeffects

Limiter, compressor, convolver, equalizer and auto volume and many other plugins for PipeWire applications
GNU General Public License v3.0
6.12k stars 264 forks source link

Autoload breaks due to overzealous `str_contains` test #3180

Closed andersk closed 2 weeks ago

andersk commented 2 weeks ago

EasyEffects Version

7.1.6

What package are you using?

NixOS

Distribution

NixOS 24.11

Describe the bug

I created different autoload configurations for speakers and headphones, but they have no effect when wired headphones are plugged or unplugged:

$ cat ~/.config/easyeffects/autoload/output/alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink\:\[Out]\ Headphones.json 
{
    "device": "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink",
    "device-description": "Comet Lake PCH-LP cAVS Speaker + Headphones",
    "device-profile": "[Out] Headphones",
    "preset-name": "None"
}
$ cat ~/.config/easyeffects/autoload/output/alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink\:\[Out]\ Speaker.json 
{
    "device": "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink",
    "device-description": "Comet Lake PCH-LP cAVS Speaker + Headphones",
    "device-profile": "[Out] Speaker",
    "preset-name": "X1Yg4 speakers"
}

Upon pluging or unpluging wired headphones, I get the debug message output autoloading: the target node name does not match the output device name.

I added some extra debug messages and rebuilt easyeffects to diagnose the exact mismatch:

device.bus_path  == "pci-0000_00_1f.3-platform-skl_hda_dsp_generic"
device.bus_id    == ""
target_node.name == "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_5__sink"
name             == "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink"

On my system, hw_sofhdadsp_5 (Comet Lake PCH-LP cAVS HDMI / DisplayPort 3 Output) is a completely different node from hw_sofhdadsp (Comet Lake PCH-LP cAVS Speaker + Headphones) that just happens to be enumerated before hw_sofhdadsp and include the same bus_path as a substring (also, every string includes the bus_id "" as a substring), resulting in a false positive match for this str_contains test:

https://github.com/wwmm/easyeffects/blob/27c4f544f46d8ffbe88a69ca654a2c341eb2a065/src/application.cpp#L160-L165

Expected Behavior

No response

Debug Log

Debug Log
``` (process:197746): easyeffects-DEBUG: 16:51:06.523: easyeffects.cpp:46 easyeffects version: 7.1.6 (process:197746): easyeffects-DEBUG: 16:51:06.524: easyeffects.cpp:56 locale directory: /nix/store/ipfaf3d0rismh447hwh86ccqx6zs8rx3-easyeffects-7.1.6/share/locale (easyeffects:197746): easyeffects-DEBUG: 16:51:06.526: presets_manager.cpp:212 user presets directory already exists: /home/anders/.config/easyeffects/ (easyeffects:197746): easyeffects-DEBUG: 16:51:06.526: presets_manager.cpp:212 user presets directory already exists: /home/anders/.config/easyeffects/input (easyeffects:197746): easyeffects-DEBUG: 16:51:06.526: presets_manager.cpp:212 user presets directory already exists: /home/anders/.config/easyeffects/output (easyeffects:197746): easyeffects-DEBUG: 16:51:06.526: presets_manager.cpp:212 user presets directory already exists: /home/anders/.config/easyeffects/autoload/input (easyeffects:197746): easyeffects-DEBUG: 16:51:06.526: presets_manager.cpp:212 user presets directory already exists: /home/anders/.config/easyeffects/autoload/output (easyeffects:197746): easyeffects-DEBUG: 16:51:06.615: pipe_manager.cpp:1534 compiled with PipeWire: 1.0.6 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.615: pipe_manager.cpp:1535 linked to PipeWire: 1.0.6 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1505 core version: 1.0.6 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1506 core name: pipewire-0 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1417 found metadata: settings (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1417 found metadata: schema-sm-settings (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1417 found metadata: persistent-sm-settings (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1417 found metadata: sm-settings (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1417 found metadata: sm-objects (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1417 found metadata: default (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1417 found metadata: filters (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1417 found metadata: route-settings (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1271 Audio/Sink 49 alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_5__sink with serial 49 has been added (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1271 Audio/Sink 50 alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_4__sink with serial 50 has been added (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1271 Audio/Sink 51 alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_3__sink with serial 51 has been added (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1271 Audio/Sink 52 alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink with serial 52 has been added (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1271 Audio/Source 53 alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__source with serial 53 has been added (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1271 Audio/Source 54 alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_6__source with serial 54 has been added (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1271 Audio/Sink 121 easyeffects_sink with serial 1750 has been added (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1271 Audio/Source/Virtual 105 easyeffects_source with serial 1751 has been added (easyeffects:197746): easyeffects-DEBUG: 16:51:06.620: pipe_manager.cpp:1007 new metadata property: 0, default.configured.audio.sink, Spa:String:JSON, {"name":"bluez_output.AC_80_0A_06_6B_91.1"} (easyeffects:197746): easyeffects-DEBUG: 16:51:06.621: pipe_manager.cpp:1007 new metadata property: 0, default.configured.audio.source, Spa:String:JSON, {"name":"alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_6__source"} (easyeffects:197746): easyeffects-DEBUG: 16:51:06.621: pipe_manager.cpp:1007 new metadata property: 0, default.audio.sink, Spa:String:JSON, {"name":"alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink"} (easyeffects:197746): easyeffects-DEBUG: 16:51:06.621: pipe_manager.cpp:1007 new metadata property: 0, default.audio.source, Spa:String:JSON, {"name":"alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_6__source"} (easyeffects:197746): easyeffects-DEBUG: 16:51:06.621: pipe_manager.cpp:1007 new metadata property: 0, default.video.source, Spa:String:JSON, {"name":"v4l2_input.pci-0000_00_14.0-usb-0_8_1.0"} (easyeffects:197746): easyeffects-DEBUG: 16:51:06.621: pipe_manager.cpp:1633 easyeffects_sink node successfully retrieved with id 121 and serial 1750 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.621: pipe_manager.cpp:1638 easyeffects_source node successfully retrieved with id 105 and serial 1751 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.626: plugin_base.cpp:403 soe: output_level successfully connected to PipeWire graph (easyeffects:197746): easyeffects-DEBUG: 16:51:06.627: plugin_base.cpp:403 soe: spectrum successfully connected to PipeWire graph (easyeffects:197746): easyeffects-DEBUG: 16:51:06.629: plugin_base.cpp:403 soe: convolver successfully connected to PipeWire graph (easyeffects:197746): easyeffects-DEBUG: 16:51:06.630: pipe_manager.cpp:1311 easyeffects_sink port 132 is connected to ee_soe_convolver port 113 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.630: pipe_manager.cpp:1311 easyeffects_sink port 114 is connected to ee_soe_convolver port 131 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.630: pipe_manager.cpp:1314 No node with id 95 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.631: pipe_manager.cpp:1314 No node with id 95 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.631: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.631: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.632: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.632: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.634: plugin_base.cpp:403 sie: output_level successfully connected to PipeWire graph (easyeffects:197746): easyeffects-DEBUG: 16:51:06.636: plugin_base.cpp:403 sie: spectrum successfully connected to PipeWire graph (easyeffects:197746): easyeffects-DEBUG: 16:51:06.636: pipe_manager.cpp:1314 No node with id 93 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.637: pipe_manager.cpp:1314 No node with id 93 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.637: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.637: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.638: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.638: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.638: stream_output_effects.cpp:349 disconnecting the convolver filter from PipeWire (easyeffects:197746): easyeffects-DEBUG: 16:51:06.639: pipe_manager.cpp:265 149 ee_soe_convolver has been removed (easyeffects:197746): easyeffects-DEBUG: 16:51:06.642: plugin_base.cpp:403 soe: convolver successfully connected to PipeWire graph (easyeffects:197746): easyeffects-DEBUG: 16:51:06.642: pipe_manager.cpp:1311 easyeffects_sink port 132 is connected to ee_soe_convolver port 146 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.642: pipe_manager.cpp:1311 easyeffects_sink port 114 is connected to ee_soe_convolver port 122 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.643: pipe_manager.cpp:1314 No node with id 95 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.643: pipe_manager.cpp:1314 No node with id 95 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.643: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.643: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.644: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.644: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.646: pipe_manager.cpp:1314 No node with id 93 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.647: pipe_manager.cpp:1314 No node with id 93 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.647: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.647: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.648: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.648: pipe_manager.cpp:1314 No node with id 141 in our node_map easyeffects-INFO: 16:51:06.648: application.cpp:76 disabling global bypass (easyeffects:197746): easyeffects-DEBUG: 16:51:06.653: application_ui.cpp:109 Icon Theme Adwaita detected (easyeffects:197746): easyeffects-DEBUG: 16:51:06.744: convolver_ui.cpp:652 irs directory already exists: /home/anders/.config/easyeffects/irs (easyeffects:197746): easyeffects-DEBUG: 16:51:06.874: stream_output_effects.cpp:349 disconnecting the convolver filter from PipeWire (easyeffects:197746): easyeffects-DEBUG: 16:51:06.875: pipe_manager.cpp:265 148 ee_soe_convolver has been removed (easyeffects:197746): easyeffects-DEBUG: 16:51:06.878: plugin_base.cpp:403 soe: convolver successfully connected to PipeWire graph (easyeffects:197746): easyeffects-DEBUG: 16:51:06.878: pipe_manager.cpp:1311 easyeffects_sink port 132 is connected to ee_soe_convolver port 135 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.879: pipe_manager.cpp:1311 easyeffects_sink port 114 is connected to ee_soe_convolver port 131 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.879: pipe_manager.cpp:1314 No node with id 95 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.879: pipe_manager.cpp:1314 No node with id 95 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.880: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.880: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.881: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.881: pipe_manager.cpp:1314 No node with id 107 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.884: pipe_manager.cpp:1314 No node with id 93 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.884: pipe_manager.cpp:1314 No node with id 93 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.885: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.885: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.886: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.886: pipe_manager.cpp:1314 No node with id 141 in our node_map (easyeffects:197746): easyeffects-DEBUG: 16:51:06.886: application.cpp:104 new default output device: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink (easyeffects:197746): easyeffects-DEBUG: 16:51:06.886: application.cpp:112 new default input device: alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_6__source (easyeffects:197746): easyeffects-DEBUG: 16:51:06.886: application.cpp:156 device alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic has changed its output route to: [Out] Speaker (easyeffects:197746): easyeffects-DEBUG: 16:51:06.886: application.cpp:176 output autoloading: the target node name does not match the output device name (easyeffects:197746): easyeffects-DEBUG: 16:51:06.886: application.cpp:124 device alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic has changed its input route to: [In] Mic1 (easyeffects:197746): easyeffects-DEBUG: 16:51:06.886: application.cpp:144 input autoloading: the target node name does not match the input device name ```

When plugging in headphones:

(easyeffects:197746): easyeffects-DEBUG: 16:51:32.637:  application.cpp:156 device alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic has changed its output route to: [Out] Headphones
(easyeffects:197746): easyeffects-DEBUG: 16:51:32.637:  application.cpp:176 output autoloading: the target node name does not match the output device name

When unplugging headphones:

(easyeffects:197746): easyeffects-DEBUG: 16:51:47.618:  application.cpp:156 device alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic has changed its output route to: [Out] Speaker
(easyeffects:197746): easyeffects-DEBUG: 16:51:47.618:  application.cpp:176 output autoloading: the target node name does not match the output device name

Additional Information

pw-cli ls output ``` id 0, type PipeWire:Interface:Core/4 object.serial = "0" core.name = "pipewire-0" id 1, type PipeWire:Interface:Module/3 object.serial = "1" module.name = "libpipewire-module-rt" id 2, type PipeWire:Interface:Module/3 object.serial = "2" module.name = "libpipewire-module-protocol-native" id 3, type PipeWire:Interface:Module/3 object.serial = "3" module.name = "libpipewire-module-profiler" id 4, type PipeWire:Interface:Profiler/3 object.serial = "4" id 5, type PipeWire:Interface:Module/3 object.serial = "5" module.name = "libpipewire-module-metadata" id 6, type PipeWire:Interface:Factory/3 object.serial = "6" module.id = "5" factory.name = "metadata" factory.type.name = "PipeWire:Interface:Metadata" factory.type.version = "3" id 7, type PipeWire:Interface:Module/3 object.serial = "7" module.name = "libpipewire-module-spa-device-factory" id 8, type PipeWire:Interface:Factory/3 object.serial = "8" module.id = "7" factory.name = "spa-device-factory" factory.type.name = "PipeWire:Interface:Device" factory.type.version = "3" id 9, type PipeWire:Interface:Module/3 object.serial = "9" module.name = "libpipewire-module-spa-node-factory" id 10, type PipeWire:Interface:Factory/3 object.serial = "10" module.id = "9" factory.name = "spa-node-factory" factory.type.name = "PipeWire:Interface:Node" factory.type.version = "3" id 11, type PipeWire:Interface:Module/3 object.serial = "11" module.name = "libpipewire-module-client-node" id 12, type PipeWire:Interface:Factory/3 object.serial = "12" module.id = "11" factory.name = "client-node" factory.type.name = "PipeWire:Interface:ClientNode" factory.type.version = "5" id 13, type PipeWire:Interface:Module/3 object.serial = "13" module.name = "libpipewire-module-client-device" id 14, type PipeWire:Interface:Factory/3 object.serial = "14" module.id = "13" factory.name = "client-device" factory.type.name = "Spa:Pointer:Interface:Device" factory.type.version = "0" id 15, type PipeWire:Interface:Module/3 object.serial = "15" module.name = "libpipewire-module-portal" id 16, type PipeWire:Interface:Module/3 object.serial = "16" module.name = "libpipewire-module-access" id 17, type PipeWire:Interface:Module/3 object.serial = "17" module.name = "libpipewire-module-adapter" id 18, type PipeWire:Interface:Factory/3 object.serial = "18" module.id = "17" factory.name = "adapter" factory.type.name = "PipeWire:Interface:Node" factory.type.version = "3" id 19, type PipeWire:Interface:Module/3 object.serial = "19" module.name = "libpipewire-module-link-factory" id 20, type PipeWire:Interface:Factory/3 object.serial = "20" module.id = "19" factory.name = "link-factory" factory.type.name = "PipeWire:Interface:Link" factory.type.version = "3" id 21, type PipeWire:Interface:Module/3 object.serial = "21" module.name = "libpipewire-module-session-manager" id 22, type PipeWire:Interface:Factory/3 object.serial = "22" module.id = "21" factory.name = "client-endpoint" factory.type.name = "PipeWire:Interface:ClientEndpoint" factory.type.version = "0" id 23, type PipeWire:Interface:Factory/3 object.serial = "23" module.id = "21" factory.name = "client-session" factory.type.name = "PipeWire:Interface:ClientSession" factory.type.version = "0" id 24, type PipeWire:Interface:Factory/3 object.serial = "24" module.id = "21" factory.name = "session" factory.type.name = "PipeWire:Interface:Session" factory.type.version = "0" id 25, type PipeWire:Interface:Factory/3 object.serial = "25" module.id = "21" factory.name = "endpoint" factory.type.name = "PipeWire:Interface:Endpoint" factory.type.version = "0" id 26, type PipeWire:Interface:Factory/3 object.serial = "26" module.id = "21" factory.name = "endpoint-stream" factory.type.name = "PipeWire:Interface:EndpointStream" factory.type.version = "0" id 27, type PipeWire:Interface:Factory/3 object.serial = "27" module.id = "21" factory.name = "endpoint-link" factory.type.name = "PipeWire:Interface:EndpointLink" factory.type.version = "0" id 28, type PipeWire:Interface:Module/3 object.serial = "28" module.name = "libpipewire-module-x11-bell" id 29, type PipeWire:Interface:Module/3 object.serial = "29" module.name = "libpipewire-module-jackdbus-detect" id 30, type PipeWire:Interface:Node/3 object.serial = "30" factory.id = "10" priority.driver = "20000" node.name = "Dummy-Driver" id 31, type PipeWire:Interface:Node/3 object.serial = "31" factory.id = "10" priority.driver = "19000" node.name = "Freewheel-Driver" id 32, type PipeWire:Interface:Metadata/3 object.serial = "32" metadata.name = "settings" id 33, type PipeWire:Interface:Client/3 object.serial = "33" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "82094" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = ".gnome-shell-wrapped" id 34, type PipeWire:Interface:Client/3 object.serial = "34" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "82475" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0-manager" pipewire.access = "unrestricted" application.name = "WirePlumber" id 35, type PipeWire:Interface:Client/3 object.serial = "35" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "2924" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = "GNOME Shell Volume Control" id 36, type PipeWire:Interface:Client/3 object.serial = "36" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "2924" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = "GNOME Volume Control Media Keys" id 37, type PipeWire:Interface:Metadata/3 metadata.name = "schema-sm-settings" factory.id = "6" module.id = "5" client.id = "34" object.serial = "37" id 38, type PipeWire:Interface:Metadata/3 metadata.name = "persistent-sm-settings" factory.id = "6" module.id = "5" client.id = "34" object.serial = "38" id 39, type PipeWire:Interface:Metadata/3 metadata.name = "sm-settings" factory.id = "6" module.id = "5" client.id = "34" object.serial = "39" id 40, type PipeWire:Interface:Metadata/3 metadata.name = "sm-objects" factory.id = "6" module.id = "5" client.id = "34" object.serial = "40" id 41, type PipeWire:Interface:Metadata/3 metadata.name = "default" factory.id = "6" module.id = "5" client.id = "34" object.serial = "41" id 42, type PipeWire:Interface:Metadata/3 metadata.name = "filters" factory.id = "6" module.id = "5" client.id = "34" object.serial = "42" id 43, type PipeWire:Interface:Metadata/3 metadata.name = "route-settings" factory.id = "6" module.id = "5" client.id = "34" object.serial = "43" id 44, type PipeWire:Interface:Client/3 object.serial = "44" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "82475" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0-manager" pipewire.access = "unrestricted" application.name = "WirePlumber [export]" id 45, type PipeWire:Interface:Device/3 object.serial = "45" factory.id = "14" client.id = "44" device.api = "alsa" device.description = "Comet Lake PCH-LP cAVS" device.name = "alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic" device.nick = "sof-hda-dsp" media.class = "Audio/Device" id 46, type PipeWire:Interface:Node/3 object.serial = "46" factory.id = "10" client.id = "44" priority.session = "100" priority.driver = "1" node.name = "Midi-Bridge" media.class = "Midi/Bridge" id 47, type PipeWire:Interface:Port/3 object.serial = "47" object.path = "alsa:seq:default:client_14:playback_0" format.dsp = "8 bit raw midi" node.id = "46" port.id = "0" port.name = "Midi Through:(playback_0) Midi Through Port-0" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "Midi Through:Midi Through Port-0" id 48, type PipeWire:Interface:Port/3 object.serial = "48" object.path = "alsa:seq:default:client_14:capture_0" format.dsp = "8 bit raw midi" node.id = "46" port.id = "0" port.name = "Midi Through:(capture_0) Midi Through Port-0" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Midi Through:Midi Through Port-0" id 49, type PipeWire:Interface:Node/3 object.serial = "49" object.path = "alsa:pcm:0:hw:sofhdadsp,5:playback" factory.id = "18" client.id = "44" device.id = "45" priority.session = "664" priority.driver = "664" node.description = "Comet Lake PCH-LP cAVS HDMI / DisplayPort 3 Output" node.name = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_5__sink" node.nick = "HDMI / DisplayPort 3 Output" media.class = "Audio/Sink" id 50, type PipeWire:Interface:Node/3 object.serial = "50" object.path = "alsa:pcm:0:hw:sofhdadsp,4:playback" factory.id = "18" client.id = "44" device.id = "45" priority.session = "680" priority.driver = "680" node.description = "Comet Lake PCH-LP cAVS HDMI / DisplayPort 2 Output" node.name = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_4__sink" node.nick = "HDMI / DisplayPort 2 Output" media.class = "Audio/Sink" id 51, type PipeWire:Interface:Node/3 object.serial = "51" object.path = "alsa:pcm:0:hw:sofhdadsp,3:playback" factory.id = "18" client.id = "44" device.id = "45" priority.session = "696" priority.driver = "696" node.description = "Comet Lake PCH-LP cAVS HDMI / DisplayPort 1 Output" node.name = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_3__sink" node.nick = "HDMI / DisplayPort 1 Output" media.class = "Audio/Sink" id 52, type PipeWire:Interface:Node/3 object.serial = "52" object.path = "alsa:pcm:0:hw:sofhdadsp:playback" factory.id = "18" client.id = "44" device.id = "45" priority.session = "1000" priority.driver = "1000" node.description = "Comet Lake PCH-LP cAVS Speaker + Headphones" node.name = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink" node.nick = "Speaker + Headphones" media.class = "Audio/Sink" id 53, type PipeWire:Interface:Node/3 object.serial = "53" object.path = "alsa:pcm:0:hw:sofhdadsp:capture" factory.id = "18" client.id = "44" device.id = "45" priority.session = "2000" priority.driver = "2000" node.description = "Comet Lake PCH-LP cAVS Headphones Stereo Microphone" node.name = "alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__source" node.nick = "Headphones Stereo Microphone" media.class = "Audio/Source" id 54, type PipeWire:Interface:Node/3 object.serial = "54" object.path = "alsa:pcm:0:hw:sofhdadsp,6:capture" factory.id = "18" client.id = "44" device.id = "45" priority.session = "1648" priority.driver = "1648" node.description = "Comet Lake PCH-LP cAVS Digital Microphone" node.name = "alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_6__source" node.nick = "Digital Microphone" media.class = "Audio/Source" id 55, type PipeWire:Interface:Node/3 object.serial = "55" factory.id = "13" client.id = "44" node.description = "BLE MIDI 1" node.name = "bluez_midi.server" media.class = "Midi/Bridge" id 56, type PipeWire:Interface:Port/3 object.serial = "56" object.path = "bluez_midi.server:input_0" format.dsp = "8 bit raw midi" node.id = "55" port.id = "0" port.name = "in" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "in" id 57, type PipeWire:Interface:Port/3 object.serial = "57" object.path = "bluez_midi.server:output_0" format.dsp = "8 bit raw midi" node.id = "55" port.id = "0" port.name = "out" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "out" id 58, type PipeWire:Interface:Port/3 object.serial = "58" object.path = "alsa:pcm:0:hw:sofhdadsp,5:playback:playback_0" format.dsp = "32 bit float mono audio" node.id = "49" audio.channel = "FL" port.id = "0" port.name = "playback_FL" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "HDMI / DisplayPort 3 Output:playback_FL" id 59, type PipeWire:Interface:Port/3 object.serial = "59" object.path = "alsa:pcm:0:hw:sofhdadsp,5:playback:monitor_0" format.dsp = "32 bit float mono audio" node.id = "49" audio.channel = "FL" port.id = "0" port.name = "monitor_FL" port.direction = "out" port.monitor = "true" port.alias = "HDMI / DisplayPort 3 Output:monitor_FL" id 60, type PipeWire:Interface:Port/3 object.serial = "60" object.path = "alsa:pcm:0:hw:sofhdadsp,5:playback:playback_1" format.dsp = "32 bit float mono audio" node.id = "49" audio.channel = "FR" port.id = "1" port.name = "playback_FR" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "HDMI / DisplayPort 3 Output:playback_FR" id 61, type PipeWire:Interface:Port/3 object.serial = "61" object.path = "alsa:pcm:0:hw:sofhdadsp,5:playback:monitor_1" format.dsp = "32 bit float mono audio" node.id = "49" audio.channel = "FR" port.id = "1" port.name = "monitor_FR" port.direction = "out" port.monitor = "true" port.alias = "HDMI / DisplayPort 3 Output:monitor_FR" id 62, type PipeWire:Interface:Device/3 object.serial = "62" factory.id = "14" client.id = "44" device.api = "v4l2" device.description = "Integrated Camera" device.name = "v4l2_device.pci-0000_00_14.0-usb-0_8_1.0" media.class = "Video/Device" id 63, type PipeWire:Interface:Device/3 object.serial = "63" factory.id = "14" client.id = "44" device.api = "v4l2" device.description = "Integrated Camera" device.name = "v4l2_device.pci-0000_00_14.0-usb-0_8_1.0" media.class = "Video/Device" id 64, type PipeWire:Interface:Device/3 object.serial = "64" factory.id = "14" client.id = "44" device.api = "v4l2" device.description = "Integrated Camera" device.name = "v4l2_device.pci-0000_00_14.0-usb-0_8_1.2" media.class = "Video/Device" id 65, type PipeWire:Interface:Device/3 object.serial = "65" factory.id = "14" client.id = "44" device.api = "v4l2" device.description = "Integrated Camera" device.name = "v4l2_device.pci-0000_00_14.0-usb-0_8_1.2" media.class = "Video/Device" id 66, type PipeWire:Interface:Port/3 object.serial = "66" object.path = "alsa:pcm:0:hw:sofhdadsp,4:playback:playback_0" format.dsp = "32 bit float mono audio" node.id = "50" audio.channel = "FL" port.id = "0" port.name = "playback_FL" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "HDMI / DisplayPort 2 Output:playback_FL" id 67, type PipeWire:Interface:Port/3 object.serial = "67" object.path = "alsa:pcm:0:hw:sofhdadsp,4:playback:monitor_0" format.dsp = "32 bit float mono audio" node.id = "50" audio.channel = "FL" port.id = "0" port.name = "monitor_FL" port.direction = "out" port.monitor = "true" port.alias = "HDMI / DisplayPort 2 Output:monitor_FL" id 68, type PipeWire:Interface:Port/3 object.serial = "68" object.path = "alsa:pcm:0:hw:sofhdadsp,4:playback:playback_1" format.dsp = "32 bit float mono audio" node.id = "50" audio.channel = "FR" port.id = "1" port.name = "playback_FR" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "HDMI / DisplayPort 2 Output:playback_FR" id 69, type PipeWire:Interface:Port/3 object.serial = "69" object.path = "alsa:pcm:0:hw:sofhdadsp,4:playback:monitor_1" format.dsp = "32 bit float mono audio" node.id = "50" audio.channel = "FR" port.id = "1" port.name = "monitor_FR" port.direction = "out" port.monitor = "true" port.alias = "HDMI / DisplayPort 2 Output:monitor_FR" id 70, type PipeWire:Interface:Device/3 object.serial = "70" factory.id = "14" client.id = "44" device.api = "libcamera" device.description = "Unknown device" device.name = "libcamera_device.0" media.class = "Video/Device" id 71, type PipeWire:Interface:Device/3 object.serial = "71" factory.id = "14" client.id = "44" device.api = "libcamera" device.description = "Unknown device" device.name = "libcamera_device.1" media.class = "Video/Device" id 72, type PipeWire:Interface:Node/3 object.serial = "72" object.path = "v4l2:/dev/video0" factory.id = "10" client.id = "44" device.id = "62" priority.session = "1000" node.description = "Integrated Camera (V4L2)" node.name = "v4l2_input.pci-0000_00_14.0-usb-0_8_1.0" node.nick = "Integrated Camera" media.class = "Video/Source" media.role = "Camera" id 73, type PipeWire:Interface:Port/3 object.serial = "73" object.path = "v4l2:/dev/video0:capture_0" node.id = "72" port.id = "0" port.name = "capture_1" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Integrated Camera:capture_1" id 74, type PipeWire:Interface:Node/3 object.serial = "74" object.path = "v4l2:/dev/video2" factory.id = "10" client.id = "44" device.id = "64" priority.session = "980" node.description = "Integrated Camera (V4L2)" node.name = "v4l2_input.pci-0000_00_14.0-usb-0_8_1.2" node.nick = "Integrated Camera" media.class = "Video/Source" media.role = "Camera" id 75, type PipeWire:Interface:Port/3 object.serial = "75" object.path = "v4l2:/dev/video2:capture_0" node.id = "74" port.id = "0" port.name = "capture_1" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Integrated Camera:capture_1" id 76, type PipeWire:Interface:Port/3 object.serial = "76" object.path = "alsa:pcm:0:hw:sofhdadsp,3:playback:playback_0" format.dsp = "32 bit float mono audio" node.id = "51" audio.channel = "FL" port.id = "0" port.name = "playback_FL" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "HDMI / DisplayPort 1 Output:playback_FL" id 77, type PipeWire:Interface:Port/3 object.serial = "77" object.path = "alsa:pcm:0:hw:sofhdadsp,3:playback:monitor_0" format.dsp = "32 bit float mono audio" node.id = "51" audio.channel = "FL" port.id = "0" port.name = "monitor_FL" port.direction = "out" port.monitor = "true" port.alias = "HDMI / DisplayPort 1 Output:monitor_FL" id 78, type PipeWire:Interface:Port/3 object.serial = "78" object.path = "alsa:pcm:0:hw:sofhdadsp,3:playback:playback_1" format.dsp = "32 bit float mono audio" node.id = "51" audio.channel = "FR" port.id = "1" port.name = "playback_FR" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "HDMI / DisplayPort 1 Output:playback_FR" id 79, type PipeWire:Interface:Port/3 object.serial = "79" object.path = "alsa:pcm:0:hw:sofhdadsp,3:playback:monitor_1" format.dsp = "32 bit float mono audio" node.id = "51" audio.channel = "FR" port.id = "1" port.name = "monitor_FR" port.direction = "out" port.monitor = "true" port.alias = "HDMI / DisplayPort 1 Output:monitor_FR" id 80, type PipeWire:Interface:Port/3 object.serial = "80" object.path = "alsa:pcm:0:hw:sofhdadsp:playback:playback_0" format.dsp = "32 bit float mono audio" node.id = "52" audio.channel = "FL" port.id = "0" port.name = "playback_FL" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "Speaker + Headphones:playback_FL" id 81, type PipeWire:Interface:Port/3 object.serial = "81" object.path = "alsa:pcm:0:hw:sofhdadsp:playback:monitor_0" format.dsp = "32 bit float mono audio" node.id = "52" audio.channel = "FL" port.id = "0" port.name = "monitor_FL" port.direction = "out" port.monitor = "true" port.alias = "Speaker + Headphones:monitor_FL" id 82, type PipeWire:Interface:Port/3 object.serial = "82" object.path = "alsa:pcm:0:hw:sofhdadsp:playback:playback_1" format.dsp = "32 bit float mono audio" node.id = "52" audio.channel = "FR" port.id = "1" port.name = "playback_FR" port.direction = "in" port.physical = "true" port.terminal = "true" port.alias = "Speaker + Headphones:playback_FR" id 83, type PipeWire:Interface:Port/3 object.serial = "83" object.path = "alsa:pcm:0:hw:sofhdadsp:playback:monitor_1" format.dsp = "32 bit float mono audio" node.id = "52" audio.channel = "FR" port.id = "1" port.name = "monitor_FR" port.direction = "out" port.monitor = "true" port.alias = "Speaker + Headphones:monitor_FR" id 84, type PipeWire:Interface:Port/3 object.serial = "84" object.path = "alsa:pcm:0:hw:sofhdadsp,6:capture:capture_0" format.dsp = "32 bit float mono audio" node.id = "54" audio.channel = "FL" port.id = "0" port.name = "capture_FL" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Digital Microphone:capture_FL" id 85, type PipeWire:Interface:Port/3 object.serial = "85" object.path = "alsa:pcm:0:hw:sofhdadsp,6:capture:capture_1" format.dsp = "32 bit float mono audio" node.id = "54" audio.channel = "FR" port.id = "1" port.name = "capture_FR" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Digital Microphone:capture_FR" id 86, type PipeWire:Interface:Port/3 object.serial = "86" object.path = "alsa:pcm:0:hw:sofhdadsp,6:capture:capture_2" format.dsp = "32 bit float mono audio" node.id = "54" audio.channel = "RL" port.id = "2" port.name = "capture_RL" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Digital Microphone:capture_RL" id 87, type PipeWire:Interface:Port/3 object.serial = "87" object.path = "alsa:pcm:0:hw:sofhdadsp,6:capture:capture_3" format.dsp = "32 bit float mono audio" node.id = "54" audio.channel = "RR" port.id = "3" port.name = "capture_RR" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Digital Microphone:capture_RR" id 88, type PipeWire:Interface:Port/3 object.serial = "88" object.path = "alsa:pcm:0:hw:sofhdadsp:capture:capture_0" format.dsp = "32 bit float mono audio" node.id = "53" audio.channel = "FL" port.id = "0" port.name = "capture_FL" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Headphones Stereo Microphone:capture_FL" id 89, type PipeWire:Interface:Port/3 object.serial = "89" object.path = "alsa:pcm:0:hw:sofhdadsp:capture:capture_1" format.dsp = "32 bit float mono audio" node.id = "53" audio.channel = "FR" port.id = "1" port.name = "capture_FR" port.direction = "out" port.physical = "true" port.terminal = "true" port.alias = "Headphones Stereo Microphone:capture_FR" id 90, type PipeWire:Interface:Client/3 object.serial = "90" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "82545" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = ".xdg-desktop-portal-wrapped" id 108, type PipeWire:Interface:Client/3 object.serial = "2013" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "199854" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = "pw-cli" id 109, type PipeWire:Interface:Client/3 object.serial = "1657" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "2924" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = "Firefox" id 136, type PipeWire:Interface:Client/3 object.serial = "193" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "2924" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = "Mutter" id 137, type PipeWire:Interface:Client/3 object.serial = "182" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "2924" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = "libcanberra" id 139, type PipeWire:Interface:Client/3 object.serial = "650" module.id = "2" pipewire.protocol = "protocol-native" pipewire.sec.pid = "2924" pipewire.sec.uid = "1000" pipewire.sec.gid = "1000" pipewire.sec.label = "kernel" pipewire.sec.socket = "pipewire-0" pipewire.access = "unrestricted" application.name = "Firefox" ``` [`pw-dump` output](https://github.com/user-attachments/files/15812289/pw-dump.json)
wwmm commented 2 weeks ago

On my system, hw_sofhdadsp_5 (Comet Lake PCH-LP cAVS HDMI / DisplayPort 3 Output) is a completely different node from hw_sofhdadsp (Comet Lake PCH-LP cAVS Speaker + Headphones) that just happens to be enumerated before hw_sofhdadsp and include the same bus_path as a substring (also, every string includes the bus_id "" as a substring), resulting in a false positive match for this str_contains test:

Hum... That is going to be a little problematic to handle... PipeWire doesn't make it easy for us to implement preset autoloading. We have to listen to the changes in devices routing and mapping the device to the corresponding output/input node. But besides the fact that nodes are often destroyed and recreated while new routing signals are coming the way PipeWire creates the node name based on "some unique id" from the device changes depending on the device type. For pci devices it does one thing. For usb another... And for bluetooth the kind of unique id even changes depending on the bluetooth version. If I remember well that is when bus_id is used...

We can't rely on the node/device id number or serial number. Specially the id number because PipeWire reuses it for different things while its process is running. According to PipeWire's developers the only reliable thing for this task is the node name... Maybe instead of calling break; at the first match we should create a list of all possible matches for further use down the line when if (target_node.name == name) is verified...

wwmm commented 2 weeks ago

@andersk if possible test again using our master branch. It should be fixed now. If not let us know.

andersk commented 2 weeks ago

That does work on my system, thanks. But I think I have an even more robust fix: