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.

Articles from blogs I follow:

Why is your open source project still hosted on GitHub?

Perhaps the younger generation don't know anything about the past "evils" of Microsoft and naively believe that Microsoft is now the good friend to open source, but the truth is that all Microsoft acquisitions of open source projects is a busi…

via unixdigest.com May 22, 2025

StarFive VisionFive v2 and FreeBSD

This week I powered up the StarFive VisionFive v2 board that I have. I figured I would give FreeBSD another whirl on it, in the vague hope that RISC-V boards are a more cohesive family than ARM boards were five years ago. tl;dr: I didn’t get it to work as…

via [bobulate] May 20, 2025

Steve Ballmer was an underrated CEO

There's a common narrative that Microsoft was moribund under Steve Ballmer and then later saved by the miraculous leadership of Satya Nadella. This is the dominant narrative in every online discussion about the topic I've seen and it's a commo…

via danluu.com October 28, 2024

Generated by openring