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:

KDE-FreeBSD CI

KDE runs a whole bunch of Continuous Integration (CI) builders. These try to build KDE software from version control all the time, and are triggered by commits from developers. We might quibble over the name “CI”, but at least we know most of the time tha…

via [bobulate] April 26, 2022

Announcing the Hare programming language

The “secret programming language” I have been teasing for several months now is finally here! It is called Hare, and you can read about it on the Hare blog: https://harelang.org/blog/2022-04-25-announcing-hare/ Check it out!

via Drew DeVault's blog April 25, 2022

About Logging

TL;DR: This post also talks about the problems I faced while working on my logging. To log to syslog from within my containers that do not support configuring a remote syslog server, I had syslog-ng expose a unix domain socket and mounte…

via PapaTutuWawa's Blog April 16, 2021

Generated by openring