PipeWire Media Session: Disable auto port switching on device connect
Intro
My 10 years old laptop has basically touch and look sensitive connectors, audio jack included. This means that the headphones plugged status is changed at random and with default settings in PulseAudio and PipeWire it will cause constant switching to speakers and I will be unable to enjoy my music (the soundcard is not great but the USB hub is also out of question since USB ports are also often touch sensitive).
PulseAudio
With PA there is a module module-switch-on-port-available
in default.pa which can be commented to disable this functionality.
The comment around this module is not perfect, but the module name speaks for itself and on top of that, it is easy to find help online.
### Should be after module-*-restore but before module-*-detect #load-module module-switch-on-port-available
PipeWire
With PipeWire the only thing I found is a mention in the Migration Guide was the mention that this feature is manager by Session manager
.
Name | Supported | Alternative | Notes |
---|---|---|---|
module-switch-on-port-available | No | Yes | Session manager |
Session manager
From my quick investigation there are two available session managers:
- WirePlumber
- Media Session
WirePlumber
This is their newer and recommended implementation, I am not using this thing yet. Maybe I will write something here after I will be forced to switch to it.
Media Session
This is an example implementation and it looks to be very basic but does the job for me.
To disable this unwanted behavior, edit pipewire/media-session.d/media-session.conf
. This file is located at the install directory of PipeWire eg.
/usr/share/pipewire/media-session.d/media-session.conf
Read the header in this file to know where to copy it.
Than search for default-routes
and comment all occurences of it. (You are free to experiment, this is how I have done it after some trial and error debugging).
The comment near this option in the default list also tells me nothing.
#default-routes # restore default route
My resulting media-session.conf looks like this:
# Media session config file for PipeWire version "0.3.33" # # # Copy and edit this file in /etc/pipewire/media-session.d/ # for systemwide changes or in # ~/.config/pipewire/media-session.d/ for local changes. context.properties = { # Properties to configure the session and some # modules. #mem.mlock-all = false #support.dbus = true #log.level = 2 #alsa.seq.name = Midi-Bridge } context.spa-libs = { # Mapping from factory name to library. api.bluez5.* = bluez5/libspa-bluez5 api.alsa.* = alsa/libspa-alsa api.v4l2.* = v4l2/libspa-v4l2 api.libcamera.* = libcamera/libspa-libcamera } context.modules = [ #{ name = <module-name> # [ args = { <key> = <value> ... } ] # [ flags = [ [ ifexists ] [ nofail ] ] #} # # Loads a module with the given parameters. # If ifexists is given, the module is ignored when it is not found. # If nofail is given, module initialization failures are ignored. # # Uses RTKit to boost the data thread priority. { name = libpipewire-module-rtkit args = { #nice.level = -11 #rt.prio = 88 #rt.time.soft = 2000000 #rt.time.hard = 2000000 } flags = [ ifexists nofail ] } # The native communication protocol. { name = libpipewire-module-protocol-native } # Allows creating nodes that run in the context of the # client. Is used by all clients that want to provide # data to PipeWire. { name = libpipewire-module-client-node } # Allows creating devices that run in the context of the # client. Is used by the session manager. { name = libpipewire-module-client-device } # Makes a factory for wrapping nodes in an adapter with a # converter and resampler. { name = libpipewire-module-adapter } # Allows applications to create metadata objects. It creates # a factory for Metadata objects. { name = libpipewire-module-metadata } # Provides factories to make session manager objects. { name = libpipewire-module-session-manager } ] session.modules = { # These are the modules that are enabled when a file with # the key name is found in the media-session.d config directory. # the default bundle is always enabled. default = [ flatpak # manages flatpak access portal # manage portal permissions v4l2 # video for linux udev detection #libcamera # libcamera udev detection suspend-node # suspend inactive nodes policy-node # configure and link nodes #metadata # export metadata API #default-nodes # restore default nodes #default-profile # restore default profiles #default-routes # restore default route #streams-follow-default # move streams when default changes #alsa-seq # alsa seq midi support #alsa-monitor # alsa udev detection #bluez5 # bluetooth support #bluez5-autoswitch # automatic bluetooth HSP/HFP profile switch #restore-stream # restore stream settings #logind # systemd-logind seat support ] with-audio = [ metadata default-nodes default-profile # default-routes alsa-seq alsa-monitor ] with-alsa = [ with-audio ] with-jack = [ with-audio ] with-pulseaudio = [ with-audio bluez5 bluez5-autoswitch logind restore-stream streams-follow-default ] }
Conclusion
While I am still using deprecated / example session manager I somehow forced it to do what I want. This solution could also affect some other features of which I have no knowledge of. So proceed at you own risk.