Page 1 of 1

pipewire

Posted: Wed Jun 26, 2024 7:55 am
by stemsee

I have pipewire installed .... but not sure if it is being used by the system. Gslapt reports that pipewire depends on libavahi ... avahi x64 is installed, What am i missing here?


Re: pipewire

Posted: Wed Jun 26, 2024 8:51 am
by jamesbond
stemsee wrote: Wed Jun 26, 2024 7:55 am

I have pipewire installed .... but not sure if it is being used by the system. Gslapt reprts that pipewire depends on ibavahi ... avahi x64 is installed, What am i missing here?

You're not missing anything. I wrote the dependency wrongly. It should be avahi (not libavahi), so you should be good to go. You may want to download qpwgraph too, and if you have pulseaudio application, then perhaps install pulseaudio as well.

Open three consoles, the run pipewire in one, wireplumber on another, and pipewire-pulse on the last one; and you should be set for life :lol:
Remember from Fatdog's point of view, both pipewire and pulseaudio are experimental packages. If things don't work, please don't complain, instead suggest what could be done to make it work, thanks :thumbup:


Re: pipewire

Posted: Wed Jun 26, 2024 10:39 am
by stemsee

recent wireplumber depends on libpipewire 1.0.2 or higher .... recompiling.


Re: pipewire

Posted: Wed Jun 26, 2024 11:41 am
by jamesbond

Don't build a standalone wireplumber, instead, get pipewire and build it from there.
wireplumber is a subproject of pipewire. They need to go hand in hand.


Re: pipewire

Posted: Wed Jun 26, 2024 12:30 pm
by stemsee

Got it! Thanks

EDIT: pipewire on linux on a chromebook!


Re: pipewire

Posted: Thu Jun 27, 2024 2:01 am
by stemsee

After compiling pipewire and wireplumber I found the wireplumber.conf in /root/.config/wireplumber/ had been mal-formed, but I already obtained an example from online documents.

Code: Select all

## The WirePlumber configuration

context.spa-libs = {
  ## SPA factory name to library mappings
  ## Used to find SPA factory names. It maps a SPA factory name regular
  ## expression to a library name that should contain that factory.
  ##
  ## Syntax:
  ## <factory-name regex> = <library-name>

  api.alsa.*      = alsa/libspa-alsa
  api.bluez5.*    = bluez5/libspa-bluez5
  api.v4l2.*      = v4l2/libspa-v4l2
  api.libcamera.* = libcamera/libspa-libcamera
  audio.convert.* = audioconvert/libspa-audioconvert
  support.*       = support/libspa-support
}

context.modules = [
  ## PipeWire modules to load.
  ## These modules are loaded before a connection to pipewire is attempted.
  ## This section should be kept minimal and load only the modules that are
  ## necessary for the protocol to work.
  ##
  ## If ifexists is given, the module is ignored when it is not found.
  ## If nofail is given, module initialization failures are ignored.
  ##
  ## Syntax:
  ## {
  ##    name = <module-name>
  ##    [ args = { <key> = <value> ... } ]
  ##    [ flags = [ ifexists | nofail ] ]
  ## }

  # Uses RTKit to boost the data thread priority. Also allows clamping
  # of utilisation when using the Completely Fair Scheduler on Linux.
  {
    name = libpipewire-module-rt
    args = {
        nice.level   = -11
        # rt.prio      = 88
        # rt.time.soft = -1
        # rt.time.hard = -1
        # uclamp.min = 0
        # uclamp.max = 1024
    }
    flags = [ ifexists, nofail ]
  }

  ## The native communication protocol.
  { name = libpipewire-module-protocol-native }

  ## Support for metadata objects
  { name = libpipewire-module-metadata }
]

wireplumber.profiles = {
  ## Syntax:
  ## <profile> = {
  ##   # optional is the default
  ##   <feature name> = [ required | optional | disabled ]
  ##   ...
  ## }

  # The default profile
  main = {
    check.no-media-session = required
    metadata.sm-settings = required
    support.settings = required
    support.log-settings = required
    metadata.sm-objects = required
    hardware.audio = required
    hardware.bluetooth = required
    hardware.video-capture = required
    policy.standard = required
    #policy.role-priority-system = optional
  }

  # Profile for video-only use cases (camera & screen sharing)
  video-only = {
    check.no-media-session = required
    metadata.sm-settings = required
    support.settings = required
    support.log-settings = required
    metadata.sm-objects = required
    hardware.audio = disabled
    hardware.bluetooth = disabled
    hardware.video-capture = required
    policy.standard = required
  }
}

wireplumber.components = [
  ## WirePlumber components to load.
  ## These components are loaded after a connection to pipewire is established.
  ## type is mandatory; rest of the tags are optional
  ##
  ## Syntax:
  ## {
  ##   name = <component-name>
  ##   type = <component-type>
  ##   arguments = { <json object> }
  ##
  ##   # Feature that this component provides
  ##   provides = <feature>
  ##
  ##   # List of features that must be provided before this component is loaded
  ##   requires = [ <features> ]
  ##
  ##   # List of features that would offer additional functionality if provided
  ##   # but are not strictly required
  ##   wants = [ <features> ]
  ## }

  ## Check to avoid loading together with media-session
  {
    name = ensure-no-media-session, type = built-in
    provides = check.no-media-session
  }

  ## Makes a secondary connection to PipeWire for exporting objects
  {
    name = export-core, type = built-in
    provides = support.export-core
  }

  ## Enables creating local nodes that are exported to pipewire
  ## This is needed for LocalNode() / WpImplNode
  ## This should be used with the export-core to avoid protocol deadlocks,
  ## unless you know what you are doing
  {
    name = libpipewire-module-client-node, type = pw-module
    provides = pw.client-node
    wants = [ support.export-core ]
  }

  ## Enables creating local devices that are exported to pipewire
  ## This is needed for SpaDevice() / WpSpaDevice
  ## This should be used with the export-core to avoid protocol deadlocks,
  ## unless you know what you are doing
  {
    name = libpipewire-module-client-device, type = pw-module
    provides = pw.client-device
    wants = [ support.export-core ]
  }

  # Provides a node factory to create SPA nodes
  # You need this to use LocalNode("spa-node-factory", ...)
  {
    name = libpipewire-module-spa-node-factory, type = pw-module
    provides = pw.node-factory.spa
    requires = [ pw.client-node ]
  }

  ## Provides a node factory to create SPA nodes wrapped in an adapter
  ## You need this to use LocalNode("adapter", ...)
  {
    name = libpipewire-module-adapter, type = pw-module
    provides = pw.node-factory.adapter
    requires = [ pw.client-node ]
  }

  ## Provides the "sm-settings" metadata object
  {
    name = libwireplumber-module-settings, type = module
    arguments = { metadata.name = sm-settings }
    provides = metadata.sm-settings
  }

  ## Activates a global WpSettings instance, providing settings from
  ## the sm-settings metadata object
  {
    name = settings-instance, type = built-in
    arguments = { metadata.name = sm-settings }
    provides = support.settings
  }

  ## Log level settings
  {
    name = libwireplumber-module-log-settings, type = module
    provides = support.log-settings
  }

  ## The lua scripting engine
  {
    name = libwireplumber-module-lua-scripting, type = module
    provides = support.lua-scripting
  }

  ## Module listening for pipewire objects to push events
  {
    name = libwireplumber-module-standard-event-source, type = module
    provides = support.standard-event-source
  }

  ## The shared D-Bus connection
  {
    name = libwireplumber-module-dbus-connection, type = module
    provides = support.dbus
  }

  ## Module managing the portal permissions
  {
    name = libwireplumber-module-portal-permissionstore, type = module
    provides = support.portal-permissionstore
    requires = [ support.dbus ]
  }

  ## Needed for device reservation to work
  {
    name = libwireplumber-module-reserve-device, type = module
    provides = support.reserve-device
    requires = [ support.dbus ]
  }

  ## logind integration to enable certain functionality only on the active seat
  {
    name = libwireplumber-module-logind, type = module
    provides = support.logind
  }

  ## Session item factories
  {
    name = libwireplumber-module-si-node, type = module
    provides = si.node
  }
  {
    name = libwireplumber-module-si-audio-adapter, type = module
    provides = si.audio-adapter
  }
  {
    name = libwireplumber-module-si-standard-link, type = module
    provides = si.standard-link
  }
  {
    name = libwireplumber-module-si-audio-virtual, type = module
    provides = si.audio-virtual
  }

  ## API to access default nodes from scripts
  {
    name = libwireplumber-module-default-nodes-api, type = module
    provides = api.default-nodes
  }

  ## API to access mixer controls
  {
    name = libwireplumber-module-mixer-api, type = module
    provides = api.mixer
  }

  ## API to get notified about file changes
  {
    name = libwireplumber-module-file-monitor-api, type = module
    provides = api.file-monitor
  }

  ## Provide the "default" pw_metadata
  {
    name = metadata.lua, type = script/lua
    arguments = { metadata.name = default }
    provides = metadata.default
  }

  ## Provide the "filters" pw_metadata
  {
    name = metadata.lua, type = script/lua
    arguments = { metadata.name = filters }
    provides = metadata.filters
  }

  ## Provide the "sm-objects" pw_metadata, supporting dynamic loadable objects
  {
    name = sm-objects.lua, type = script/lua
    provides = metadata.sm-objects
  }

  ## Device monitors' optional features
  {
    type = virtual, provides = monitor.alsa.reserve-device,
    requires = [ support.reserve-device ]
  }
  {
    type = virtual, provides = monitor.alsa-midi.monitoring,
    requires = [ api.file-monitor ]
  }
  {
    type = virtual, provides = monitor.bluez.seat-monitoring,
    requires = [ support.logind ]
  }

  ## Device monitors
  {
    name = monitors/alsa.lua, type = script/lua
    provides = monitor.alsa
    requires = [ support.export-core, pw.client-device ]
    wants = [ monitor.alsa.reserve-device ]
  }
  {
    name = monitors/bluez.lua, type = script/lua
    provides = monitor.bluez
    requires = [ support.export-core,
                 pw.client-device,
                 pw.client-node,
                 pw.node-factory.adapter ]
    wants = [ monitor.bluez.seat-monitoring ]
  }
  {
    name = monitors/bluez-midi.lua, type = script/lua
    provides = monitor.bluez-midi
    requires = [ support.export-core,
                 pw.client-device,
                 pw.client-node,
                 pw.node-factory.spa ]
    wants = [ monitor.bluez.seat-monitoring ]
  }
  {
    name = monitors/alsa-midi.lua, type = script/lua
    provides = monitor.alsa-midi
    wants = [ monitor.alsa-midi.monitoring ]
  }
  ## v4l2 monitor hooks
  {
    name = monitors/v4l2/name-device.lua, type = script/lua
    provides = hooks.monitor.v4l2-name-device
    requires = [ support.export-core,
                 support.standard-event-source ]
  }
  {
    name = monitors/v4l2/create-device.lua, type = script/lua
    provides = hooks.monitor.v4l2-create-device
    requires = [ support.export-core,
                 pw.client-device,
                 support.standard-event-source ]
  }
  {
    name = monitors/v4l2/name-node.lua, type = script/lua
    provides = hooks.monitor.v4l2-name-node
    requires = [ support.export-core,
                 support.standard-event-source ]
  }
  {
    name = monitors/v4l2/create-node.lua, type = script/lua
    provides = hooks.monitor.v4l2-create-node
    requires = [ support.export-core,
                 support.standard-event-source ]
  }
  {
    type = virtual, provides = monitor.v4l2.hooks
    wants = [ hooks.monitor.v4l2-name-device,
              hooks.monitor.v4l2-create-device,
              hooks.monitor.v4l2-name-node,
              hooks.monitor.v4l2-create-node ]
  }
  # enumerate-device.lua needs rest of the monitor hooks to be loaded first.
  {
    name = monitors/v4l2/enumerate-device.lua, type = script/lua
    provides = hooks.monitor.v4l2-enumerate-device
    requires = [ support.export-core,
                 pw.client-device,
                 support.standard-event-source,
                 monitor.v4l2.hooks ]
  }
  {
    type = virtual, provides = monitor.v4l2
    wants = [ hooks.monitor.v4l2-enumerate-device,
              monitor.v4l2.hooks ]
  }

  ## libcamera monitor hooks
  {
    name = monitors/libcamera/name-device.lua, type = script/lua
    provides = hooks.monitor.libcamera-name-device
    requires = [ support.export-core,
                 support.standard-event-source ]
  }
  {
    name = monitors/libcamera/create-device.lua, type = script/lua
    provides = hooks.monitor.libcamera-create-device
    requires = [ support.export-core,
                 pw.client-device,
                 support.standard-event-source ]
  }
  {
    name = monitors/libcamera/name-node.lua, type = script/lua
    provides = hooks.monitor.libcamera-name-node
    requires = [ support.export-core,
                 support.standard-event-source ]
  }
  {
    name = monitors/libcamera/create-node.lua, type = script/lua
    provides = hooks.monitor.libcamera-create-node
    requires = [ support.export-core,
                 support.standard-event-source ]
  }
  {
    type = virtual, provides = monitor.libcamera.hooks
    wants = [ hooks.monitor.libcamera-name-device,
              hooks.monitor.libcamera-create-device,
              hooks.monitor.libcamera-name-node,
              hooks.monitor.libcamera-create-node ]
  }
  # enumerate-device.lua needs rest of the monitor hooks to be loaded first.
  {
    name = monitors/libcamera/enumerate-device.lua, type = script/lua
    provides = hooks.monitor.libcamera-enumerate-device
    requires = [ support.export-core,
                 pw.client-device,
                 support.standard-event-source,
                 monitor.libcamera.hooks ]
  }
  {
    type = virtual, provides = monitor.libcamera
    wants = [ hooks.monitor.libcamera-enumerate-device,
              monitor.libcamera.hooks ]
  }

  ## Client access configuration hooks
  {
    name = client/access-default.lua, type = script/lua
    provides = script.client.access-default
  }
  {
    name = client/access-portal.lua, type = script/lua
    provides = script.client.access-portal
    requires = [ support.portal-permissionstore ]
  }
  {
    name = client/access-snap.lua, type = script/lua
    provides = script.client.access-snap
  }
  {
    type = virtual, provides = policy.client.access
    wants = [ script.client.access-default,
              script.client.access-portal,
              script.client.access-snap ]
  }

  ## Device profile selection hooks
  {
    name = device/select-profile.lua, type = script/lua
    provides = hooks.device.profile.select
  }
  {
    name = device/find-preferred-profile.lua, type = script/lua
    provides = hooks.device.profile.find-preferred
  }
  {
    name = device/find-best-profile.lua, type = script/lua
    provides = hooks.device.profile.find-best
  }
  {
    name = device/state-profile.lua, type = script/lua
    provides = hooks.device.profile.state
  }
  {
    name = device/apply-profile.lua, type = script/lua
    provides = hooks.device.profile.apply
  }
  {
    name = device/autoswitch-bluetooth-profile.lua, type = script/lua
    provides = hooks.device.profile.autoswitch-bluetooth
  }
  {
    type = virtual, provides = policy.device.profile
    requires = [ hooks.device.profile.select,
                 hooks.device.profile.autoswitch-bluetooth,
                 hooks.device.profile.apply ]
    wants = [ hooks.device.profile.find-best, hooks.device.profile.find-preferred,
              hooks.device.profile.state ]
  }

  # Device route selection hooks
  {
    name = device/select-routes.lua, type = script/lua
    provides = hooks.device.routes.select
  }
  {
    name = device/find-best-routes.lua, type = script/lua
    provides = hooks.device.routes.find-best
  }
  {
    name = device/state-routes.lua, type = script/lua
    provides = hooks.device.routes.state
  }
  {
    name = device/apply-routes.lua, type = script/lua
    provides = hooks.device.routes.apply
  }
  {
    type = virtual, provides = policy.device.routes
    requires = [ hooks.device.routes.select,
                 hooks.device.routes.apply ]
    wants = [ hooks.device.routes.find-best,
              hooks.device.routes.state ]
  }

  ## Default nodes selection hooks
  {
    name = default-nodes/rescan.lua, type = script/lua
    provides = hooks.default-nodes.rescan
  }
  {
    name = default-nodes/find-selected-default-node.lua, type = script/lua
    provides = hooks.default-nodes.find-selected
    requires = [ metadata.default ]
  }
  {
    name = default-nodes/find-best-default-node.lua, type = script/lua
    provides = hooks.default-nodes.find-best
  }
  {
    name = default-nodes/state-default-nodes.lua, type = script/lua
    provides = hooks.default-nodes.state
    requires = [ metadata.default ]
  }
  {
    name = default-nodes/apply-default-node.lua, type = script/lua,
    provides = hooks.default-nodes.apply
    requires = [ metadata.default ]
  }
  {
    type = virtual, provides = policy.default-nodes
    requires = [ hooks.default-nodes.rescan,
                 hooks.default-nodes.apply ]
    wants = [ hooks.default-nodes.find-selected,
              hooks.default-nodes.find-best,
              hooks.default-nodes.state ]
  }

  ## Node configuration hooks
  {
    name = node/create-item.lua, type = script/lua
    provides = hooks.node.create-session-item
    requires = [ si.audio-adapter, si.node ]
  }
  {
    name = node/suspend-node.lua, type = script/lua
    provides = hooks.node.suspend
  }
  {
    name = node/state-stream.lua, type = script/lua
    provides = hooks.stream.state
  }
  {
    name = node/filter-forward-format.lua, type = script/lua
    provides = hooks.filter.forward-format
  }
  {
    name = node/create-virtual-item.lua, type = script/lua
    provides = script.create-role-items
    requires = [ si.audio-virtual ]
  }
  {
    type = virtual, provides = policy.node
    requires = [ hooks.node.create-session-item ]
    wants = [ hooks.node.suspend
              hooks.stream.state
              hooks.filter.forward-format ]
  }
  {
    name = node/software-dsp.lua, type = script/lua
    provides = node.software-dsp
  }

  ## Linking hooks
  {
    name = linking/rescan.lua, type = script/lua
    provides = hooks.linking.rescan
  }
  {
    name = linking/find-defined-target.lua, type = script/lua
    provides = hooks.linking.target.find-defined
  }
  {
    name = linking/find-filter-target.lua, type = script/lua
    provides = hooks.linking.target.find-filter
    requires = [ metadata.filters ]
  }
  {
    name = linking/find-default-target.lua, type = script/lua
    provides = hooks.linking.target.find-default
    requires = [ api.default-nodes ]
  }
  {
    name = linking/find-best-target.lua, type = script/lua
    provides = hooks.linking.target.find-best
  }
  {
    name = linking/get-filter-from-target.lua, type = script/lua
    provides = hooks.linking.target.get-filter-from
    requires = [ metadata.filters ]
  }
  {
    name = linking/prepare-link.lua, type = script/lua
    provides = hooks.linking.target.prepare-link
    requires = [ api.default-nodes ]
  }
  {
    name = linking/link-target.lua, type = script/lua
    provides = hooks.linking.target.link
    requires = [ si.standard-link ]
  }
  {
    type = virtual, provides = policy.linking.standard
    requires = [ hooks.linking.rescan,
                 hooks.linking.target.prepare-link,
                 hooks.linking.target.link ]
    wants = [ hooks.linking.target.find-defined,
              hooks.linking.target.find-filter,
              hooks.linking.target.find-default,
              hooks.linking.target.find-best,
              hooks.linking.target.get-filter-from ]
  }

  ## Linking: Role-based priority system
  {
    name = linking/rescan-virtual-links.lua, type = script/lua
    provides = hooks.linking.role-priority-system.links.rescan
    requires = [ api.mixer ]
  }
  {
    name = linking/find-virtual-target.lua, type = script/lua
    provides = hooks.linking.role-priority-system.target.find
  }
  {
    type = virtual, provides = policy.linking.role-priority-system
    requires = [ policy.linking.standard,
                 hooks.linking.role-priority-system.links.rescan,
                 hooks.linking.role-priority-system.target.find ]
  }
  {
    type = virtual, provides = policy.standard
    requires = [ policy.client.access
                 policy.device.profile
                 policy.device.routes
                 policy.default-nodes
                 policy.linking.standard
                 policy.node
                 support.standard-event-source ]
  }
  {
    type = virtual, provides = policy.role-priority-system
    requires = [ policy.standard,
                 script.create-role-items,
                 policy.linking.role-priority-system ]
  }
  ## Load targets
  {
    type = virtual, provides = hardware.audio
    wants = [ monitor.alsa, monitor.alsa-midi ]
  }
  {
    type = virtual, provides = hardware.bluetooth
    wants = [ monitor.bluez, monitor.bluez-midi ]
  }
  {
    type = virtual, provides = hardware.video-capture
    wants = [ monitor.v4l2, monitor.libcamera ]
  }
]

wireplumber.components.rules = [
  ## Rules to apply on top of wireplumber.components
  ## Syntax:
  ## {
  ##   matches = [
  ##     {
  ##       [ <key> = <value> ... ]
  ##     }
  ##     ...
  ##   ]
  ##   actions = {
  ##     <override|merge> = {
  ##       [ <key> = <value> ... ]
  ##     }
  ##     ...
  ##   }
  ## }

  {
    matches = [
      {
        type = "script/lua"
      }
    ]
    actions = {
      merge = {
        requires = [ support.lua-scripting ]
      }
    }
  }
]

wireplumber.settings.schema = {
  ## Bluetooth
  bluetooth.use-persistent-storage = {
    description = "Whether to use persistent BT storage or not"
    type = "bool"
    default = true
  }
  bluetooth.autoswitch-to-headset-profile = {
    description = "Whether to autoswitch to BT headset profile or not"
    type = "bool"
    default = true
  }

  ## Device
  device.restore-profile = {
    description = "Whether to restore device profile or not"
    type = "bool"
    default = true
  }
  device.restore-routes = {
    description = "Whether to restore device routes or not"
    type = "bool"
    default = true
  }
  device.routes.default-sink-volume = {
    description = "The default volume for sink devices"
    type = "float"
    default = 0.064
    min = 0.0
    max = 1.0
  }
  device.routes.default-source-volume = {
    description = "The default volume for source devices"
    type = "float"
    default = 1.0
    min = 0.0
    max = 1.0
  }

  ## Linking
  linking.allow-moving-streams = {
    description = "Whether to allow metadata to move streams at runtime or not"
    type = "bool"
    default = true
  }
  linking.follow-default-target = {
    description = "Whether to allow streams follow the default device or not"
    type = "bool"
    default = true
  }

  ## Monitor
  monitor.camera-discovery-timeout = {
    description = "The camera discovery timeout in milliseconds"
    type = "int"
    default = 1000
    min = 0
    max = 60000
  }

  ## Node
  node.features.audio.no-dsp = {
    description = "Whether to never convert audio to F32 format or not"
    type = "bool"
    default = false
  }
  node.features.audio.monitor-ports = {
    description = "Whether to enable monitor ports on audio nodes or not"
    type = "bool"
    default = true
  }
  node.features.audio.control-port = {
    description = "Whether to enable control ports on audio nodes or not"
    type = "bool"
    default = false
  }
  node.stream.restore-props = {
    description = "Whether to restore properties on stream nodes or not"
    type = "bool"
    default = true
  }
  node.stream.restore-target = {
    description = "Whether to restore target on stream nodes or not"
    type = "bool"
    default = true
  }
  node.stream.default-playback-volume = {
    description = "The default volume for playback nodes"
    type = "float"
    default = 1.0
    min = 0.0
    max = 1.0
  }
  node.stream.default-capture-volume = {
    description = "The default volume for capture nodes"
    type = "float"
    default = 1.0
    min = 0.0
    max = 1.0
  }
  node.filter.forward-format = {
    description = "Whether to forward format on filter nodes or not"
    type = "bool"
    default = false
  }
  node.restore-default-targets = {
    description = "Whether to restore default targets or not"
    type = "bool"
    default = true
  }
}

my startup script in /root/Startup/wp.sh

Code: Select all

#!/bin/sh
pipewire &
pipewire-pulse &
wireplumber &
qpwgraph &