Documentation Updates

This commit is contained in:
jasker5183 2022-05-08 17:06:28 +00:00 committed by Wim Taymans
parent 8afe5fe0f0
commit c71db353f1
27 changed files with 513 additions and 498 deletions

View file

@ -1,15 +1,16 @@
/** \page page_dma_buf DMA-BUF sharing /** \page page_dma_buf DMA-BUF Sharing
PipeWire supports sharing Direct Memory Access buffers (DMA-BUFs) between PipeWire supports sharing Direct Memory Access buffers (DMA-BUFs) between
clients via the `SPA_DATA_DmaBuf` data type. However properly negotiating clients via the `SPA_DATA_DmaBuf` data type. However properly negotiating
DMA-BUF support on both the producer and the consumer side require following DMA-BUF support on both the producer and the consumer side require following
a specific procedure. This page describes said procedure by using events and a specific procedure. This page describes said procedure by using events and
methods from the filter or stream API. methods from the filter or stream API.
Note: This article focuses mostly on DMA-BUF sharing from arbitrary devices, Note: This article focuses mostly on DMA-BUF sharing from arbitrary devices,
like discrete GPUs. For using DMA-BUFs created by v4l2 please refer to the like discrete GPUs. For using DMA-BUFs created by v4l2 please refer to the
corresponding paragraph. corresponding paragraph.
# Capability negotiations # Capability Negotiations
The capability negotiation for DMA-BUFs is complicated by the fact, that a The capability negotiation for DMA-BUFs is complicated by the fact, that a
usable and preferred optimal modifier for a given format can only be usable and preferred optimal modifier for a given format can only be
@ -40,7 +41,7 @@ property.
To prioritise DMA-BUFs place those `SPA_PARAM_EnumFormat` containing modifiers To prioritise DMA-BUFs place those `SPA_PARAM_EnumFormat` containing modifiers
first, when emitting them to PipeWire. first, when emitting them to PipeWire.
## param_changed hook ## param_changed Hook
When the `param_changed` hook is called for a `SPA_PARAM_Format` the client When the `param_changed` hook is called for a `SPA_PARAM_Format` the client
has to parse the `spa_pod` directly. Use has to parse the `spa_pod` directly. Use
@ -57,15 +58,15 @@ format modifier pair. The producer is also responsible to check if all clients
announce sufficient capabilities or fallback to shared memory buffers when announce sufficient capabilities or fallback to shared memory buffers when
possible. possible.
### For consumers ### For Consumers
Use `spa_format_video_raw_parse` to get the format and modifier. Use `spa_format_video_raw_parse` to get the format and modifier.
### For producers ### For Producers
Producers have to handle two cases when it comes to modifiers wrt. to the Producers have to handle two cases when it comes to modifiers wrt. to the
previous announced capabilities: Using only the modifier-less API, only the previous announced capabilities: Using only the modifier-less API, only the
modifier aware one, or supporting both. modifier-aware one, or supporting both.
- modifier-less: - modifier-less:
In this case only the modifier `DRM_FORMAT_MOD_INVALID` was announced with In this case only the modifier `DRM_FORMAT_MOD_INVALID` was announced with
@ -77,12 +78,12 @@ modifier aware one, or supporting both.
In this case a list with all supported modifiers will be returned in the format. In this case a list with all supported modifiers will be returned in the format.
(using `DRM_FORMAT_MOD_INVALID` as the token for the modifier-less API). (using `DRM_FORMAT_MOD_INVALID` as the token for the modifier-less API).
On the `param_changed` event check if the modifier key is present and has the flag On the `param_changed` event check if the modifier key is present and has the flag
`SPA_POD_PROP_FLAG_DONT_FIXATE`. attached to it. In this case extract all modifiers `SPA_POD_PROP_FLAG_DONT_FIXATE` attached to it. In this case extract all modifiers
from the list and do a test allocation with your allocator to choose the preferred from the list and do a test allocation with your allocator to choose the preferred
modifier. Fixate on that `EnumFormat` by announcing a `SPA_PARAM_EnumFormat` with modifier. Fixate on that `EnumFormat` by announcing a `SPA_PARAM_EnumFormat` with
only one modifier in the `SPA_CHOICE_Enum` and without the only one modifier in the `SPA_CHOICE_Enum` and without the
`SPA_POD_PROP_FLAG_DONT_FIXATE` flag, followed by the previous announced `SPA_POD_PROP_FLAG_DONT_FIXATE` flag, followed by the previous announced
`EnumFormat`s. This will retrigger the `param_changed` event with an `EnumFormat`. This will retrigger the `param_changed` event with an
`SPA_PARAM_Format` as described below. `SPA_PARAM_Format` as described below.
If the `SPA_PARAM_Format` contains a modifier key, without the flag If the `SPA_PARAM_Format` contains a modifier key, without the flag
`SPA_POD_PROP_FLAG_DONT_FIXATE`, it should only contain one value in the `SPA_POD_PROP_FLAG_DONT_FIXATE`, it should only contain one value in the
@ -96,32 +97,32 @@ pass them all to the graphics API. If the allocation fails and the list of
possible modifiers contains `DRM_FORMAT_MOD_INVALID`, fall back to allocating possible modifiers contains `DRM_FORMAT_MOD_INVALID`, fall back to allocating
without an explicit modifier if the graphics API allows it. without an explicit modifier if the graphics API allows it.
## add_buffer hook ## add_buffer Hook
This is relevant for producers. This is relevant for producers.
Allocate a DMA-BUF only using the negotiated format and modifier. Allocate a DMA-BUF only using the negotiated format and modifier.
## on_event hook ## on_event Hook
This is relevant for consumers. This is relevant for consumers.
Check the type of the dequeued buffer. If its `SPA_DATA_MemFd` or Check the type of the dequeued buffer. If its `SPA_DATA_MemFd` or
`SPA_DATA_MemPtr` use the fallback SHM import mechanism. `SPA_DATA_MemPtr` use the fallback SHM import mechanism.
If it's `SPA_DATA_DmaBuf`: If it's `SPA_DATA_DmaBuf`
Get the DMA-BUF FDs (the plane count is encoded in the `n_datas` variable of the get the DMA-BUF FDs (the plane count is encoded in the `n_datas` variable of the
`spa_buffer` struct) and import them with the graphics API. `spa_buffer` struct) and import them with the graphics API.
Note: Some graphics APIs have separated functions for the modifier-less case Note: Some graphics APIs have separated functions for the modifier-less case
(`DRM_FORMAT_MOD_INVALID`) or are omitting the modifier, since it might be used (`DRM_FORMAT_MOD_INVALID`) or are omitting the modifier, since it might be used
for error handling. for error handling.
## Example programs ## Example Programs
- \ref video-src-fixate.c "": \snippet{doc} video-src-fixate.c title - \ref video-src-fixate.c "": \snippet{doc} video-src-fixate.c title
- \ref video-play-fixate.c "": \snippet{doc} video-play-fixate.c title - \ref video-play-fixate.c "": \snippet{doc} video-play-fixate.c title
# DMA-BUF mapping warning # DMA-BUF Mapping Warning
It's important to make sure all consumers of the PipeWire stream are prepared It's important to make sure all consumers of the PipeWire stream are prepared
to deal with DMA-BUFs. Most DMA-BUFs cannot be treated like shared memory in general to deal with DMA-BUFs. Most DMA-BUFs cannot be treated like shared memory in general

View file

@ -1,37 +1,38 @@
/** \mainpage PipeWire /** \mainpage PipeWire
PipeWire is low-level multimedia framework that provides: PipeWire is low-level multimedia framework that provides:
- Graph based processing
- Support for out-of-process processing graphs with minimal overhead - Graph based processing.
- Flexible and extensible media format negotiation and buffer allocation - Support for out-of-process processing graphs with minimal overhead.
- Hard real-time capable plugins - Flexible and extensible media format negotiation and buffer allocation.
- Very low-latency for both audio and video processing - Hard real-time capable plugins.
- Very low-latency for both audio and video processing.
See \ref page_overview for an overview of PipeWire and \ref page_design See \ref page_overview for an overview of PipeWire and \ref page_design
for the design principles guiding PipeWire. for the design principles guiding PipeWire.
### Components # Components
PipeWire ships with the following components: PipeWire ships with the following components:
- a \ref page_daemon that implements the IPC and graph processing - A \ref page_daemon that implements the IPC and graph processing.
- an example \ref page_session_manager that manages objects in the \ref page_daemon - An example \ref page_session_manager that manages objects in the \ref page_daemon.
- a set of \ref page_tools to introspect and use the \ref page_daemon - A set of \ref page_tools to introspect and use the \ref page_daemon.
- a \ref page_library to develop PipeWire applications and plugins (\ref - A \ref page_library to develop PipeWire applications and plugins (\ref
page_tutorial "tutorial"). page_tutorial "tutorial").
- the \ref page_spa used by both the \ref page_daemon and in the \ref - The \ref page_spa used by both the \ref page_daemon and in the \ref
page_library. page_library.
### API Documentation # API Documentation
See \ref page_api See \ref page_api.
### More Documentation # More Documentation
See our [Wiki](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/home) for See our [Wiki](https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/home) for
More information on how to configure and use PipeWire. More information on how to configure and use PipeWire.
### Resources # Resources
- [PipeWire and AGL](https://wiki.automotivelinux.org/_media/pipewire_agl_20181206.pdf) - [PipeWire and AGL](https://wiki.automotivelinux.org/_media/pipewire_agl_20181206.pdf)
- [LAC 2020 Paper](https://lac2020.sciencesconf.org/307881/document) - [LAC 2020 Paper](https://lac2020.sciencesconf.org/307881/document)
@ -39,4 +40,5 @@ More information on how to configure and use PipeWire.
- [PipeWire: The Linux audio/video bus (LWN)](https://lwn.net/Articles/847412) - [PipeWire: The Linux audio/video bus (LWN)](https://lwn.net/Articles/847412)
- [PipeWire Wikipedia](https://en.wikipedia.org/wiki/PipeWire) - [PipeWire Wikipedia](https://en.wikipedia.org/wiki/PipeWire)
- [Bluetooth, PipeWire and Whatsapp calls](https://gjhenrique.com/pipewire.html) - [Bluetooth, PipeWire and Whatsapp calls](https://gjhenrique.com/pipewire.html)
*/ */

View file

@ -1,24 +1,24 @@
/** \page page_overview Overview /** \page page_overview Overview
PipeWire is a new low-level multimedia framework designed from scratch that PipeWire is a new low-level multimedia framework designed from scratch that
aims to provide aims to provide:
- graph based processing - Graph based processing.
- support for out-of-process processing graphs with minimal overhead - Support for out-of-process processing graphs with minimal overhead.
- flexible and extensible media format negotiation and buffer allocation - Flexible and extensible media format negotiation and buffer allocation.
- Hard real-time capable plugins - Hard real-time capable plugins.
- achieve very low-latency for both audio and video processing - Achieve very low-latency for both audio and video processing.
The framework is used to build a modular daemon that can be configured to: The framework is used to build a modular daemon that can be configured to:
- be a low-latency audio server with features like pulseaudio and/or jack - Be a low-latency audio server with features like PulseAudio and/or JACK.
- a video capture server that can manage hardware video capture devices and - A video capture server that can manage hardware video capture devices and
provide access to them provide access to them.
- a central hub where video can be made available for other applications - A central hub where video can be made available for other applications
such as the gnome-shell screencast API. such as the gnome-shell screencast API.
## Motivation # Motivation
Linux has no unified framework for exchanging multimedia content between Linux has no unified framework for exchanging multimedia content between
applications or even devices. In most cases, developers realized that applications or even devices. In most cases, developers realized that
@ -29,14 +29,14 @@ a user-space daemon is needed to make this possible:
- For video capture, we usually go directly to the hardware devices, with - For video capture, we usually go directly to the hardware devices, with
all security implications and inflexible routing that this brings. all security implications and inflexible routing that this brings.
- For consumer audio, we use PulseAudio to manage and mix multiple streams - For consumer audio, we use PulseAudio to manage and mix multiple streams
from clients from clients.
- For Pro audio, we use JACK to manage the graph of nodes. - For Pro audio, we use JACK to manage the graph of nodes.
None of these solutions (except perhaps to some extent Wayland), however, None of these solutions (except perhaps to some extent Wayland) however
were designed to support the security features that are required when were designed to support the security features that are required when
dealing with flatpaks or other containerized applications. PipeWire dealing with flatpaks or other containerized applications. PipeWire
aims to solve this problem and provides a unified framework to run both aims to solve this problem and provides a unified framework to run both
consumer and Pro audio as well as video capture and processing in a consumer and pro audio as well as video capture and processing in a
secure way. secure way.
*/ */

View file

@ -14,46 +14,47 @@ Permissions include `R` (read), `W` (write), `X` (execute) and `M` (metadata).
Some of those methods will only query state, others will modify the object. Some of those methods will only query state, others will modify the object.
As said above, modifying the object through one of these methods requires As said above, modifying the object through one of these methods requires
the `W` permission. the `W` permission.
- `M`: An object with M permission can be used as the subject in metadata. - `M`: An object with `M` permission can be used as the subject in metadata.
Clients with all permissions set are referred to as "ALL" in the Clients with all permissions set are referred to as "ALL" in the
documentation. documentation.
# Use cases
### New clients need their permissions configured # Use Cases
## New Clients Need Their Permissions Configured
A new client is not allowed to communicate with the PipeWire daemon until A new client is not allowed to communicate with the PipeWire daemon until
it has been configured with permissions. it has been configured with permissions.
### Flatpaks can't modify other stream/device volumes ## Flatpaks Can't Modify Other Stream/Device Volumes
An application running as Flatpak should not be able to modify the state of An application running as Flatpak should not be able to modify the state of
certain objects. Permissions of the relevant PipeWire objects should not have certain objects. Permissions of the relevant PipeWire objects should not have
the `W` permission to avoid this. the `W` permission to avoid this.
### Flatpaks can't move other streams to different devices ## Flatpaks Can't Move Other Streams To Different Devices
Streams are moved to another device by setting the "target.node" metadata Streams are moved to another device by setting the `target.node` metadata
on the node id. By not setting the `M` bit on the other objects, this can be on the node ID. By not setting the `M` bit on the other objects, this can be
avoided. avoided.
### Application should be restricted in what they can see ## Application Should Be Restricted In What They Can See
In general, applications should only be able to see the objects that they are In general, applications should only be able to see the objects that they are
allowed to see. For example, a web browser that was given access to a camera allowed to see. For example, a web browser that was given access to a camera
should not be able to see (and thus receive input data from) audio devices. should not be able to see (and thus receive input data from) audio devices.
### "Manager" applications require full access ## "Manager" Applications Require Full Access
Some applications require full access to the PipeWire graph, including Some applications require full access to the PipeWire graph, including
moving streams between nodes (by setting metadata) and modifying properties moving streams between nodes (by setting metadata) and modifying properties
(e.g. volume). These applications must work even when running as Flatpak. (eg. volume). These applications must work even when running as Flatpak.
# Design # Design
## The PipeWire daemon ## The PipeWire Daemon
Immediately after a new client connects to the PipeWire daemon and updates Immediately after a new client connects to the PipeWire daemon and updates
its properties, the client will be registered and made visible to other its properties, the client will be registered and made visible to other
@ -71,8 +72,7 @@ A suspended client can only resume processing after some other client
sets the core permissions to `R`. This other client is usually a session sets the core permissions to `R`. This other client is usually a session
manager, see e.g. \ref page_session_manager. manager, see e.g. \ref page_session_manager.
## The PipeWire Access Module
## The PipeWire access module
The \ref page_module_access hooks into the `check_access` event that is The \ref page_module_access hooks into the `check_access` event that is
emitted when a new client is registered. The module checks the permissions of emitted when a new client is registered. The module checks the permissions of
@ -80,23 +80,23 @@ the client and stores those in the \ref PW_KEY_ACCESS
property on the client object. If this property is already set, the access property on the client object. If this property is already set, the access
module does nothing. module does nothing.
If the property is not set, it will go through a set of checks to determine If the property is not set it will go through a set of checks to determine
the permissions for a client, see the \ref page_module_access documentation the permissions for a client. See the \ref page_module_access documentation
for details, particularly on the values documented below. Depending on the for details, particularly on the values documented below. Depending on the
value of the \ref PW_KEY_ACCESS property one the following happens: value of the \ref PW_KEY_ACCESS property one the following happens:
- `"allowed"`, `"unrestricted"`: ALL permissions are set on the core - `"allowed"`, `"unrestricted"`: ALL permissions are set on the core
object and the client will be able to resume. object and the client will be able to resume.
- `"restricted"`, `"flatpak"`, `"$access.force"`: no permissions are set on - `"restricted"`, `"flatpak"`, `"$access.force"`: No permissions are set on
the core object and the client will be suspended. the core object and the client will be suspended.
- `"rejected"`: an error is sent to the client and the client is - `"rejected"`: An error is sent to the client and the client is
suspended. suspended.
As detailed above, the client may be suspended. In that case the session As detailed above, the client may be suspended. In that case the session
manager or another client is required to configure permissions on the object manager or another client is required to configure permissions on the object
for it to resume. for it to resume.
## The session manager ## The Session Manager
The session manager listens for new clients to appear. It will use the The session manager listens for new clients to appear. It will use the
\ref PW_KEY_ACCESS property to determine what to do. \ref PW_KEY_ACCESS property to determine what to do.
@ -117,7 +117,7 @@ configure ALL permissions on the client. Possible checks include
permission store checks or ask the user if the application is allowed permission store checks or ask the user if the application is allowed
full access. full access.
Manager applications (i.e. applications that need to modify the graph) will Manager applications (ie. applications that need to modify the graph) will
set the \ref PW_KEY_MEDIA_CATEGORY property in the client object to "Manager". set the \ref PW_KEY_MEDIA_CATEGORY property in the client object to "Manager".
For details on the pipewire-media-session implementation of access control, For details on the pipewire-media-session implementation of access control,

View file

@ -2,19 +2,19 @@
This document explains how Audio is implemented. This document explains how Audio is implemented.
# Use cases # Use Cases
## Audio devices are made available as processing nodes/ports ## Audio Devices Are Made Available As Processing Nodes/Ports
Applications need to be able to see a port for each stream of an Applications need to be able to see a port for each stream of an
Audio device. audio device.
### Audio devices can be plugged and unplugged ## Audio Devices Can Be Plugged and Unplugged
When devices are plugged and unplugged the associated nodes/ports When devices are plugged and unplugged the associated nodes/ports
need to be created and removed. need to be created and removed.
### Audio port in canonical format ## Audio Port In Canonical Format
It must be possible to make individual audio channels available It must be possible to make individual audio channels available
as a single mono stream with a fixed format and samplerate. as a single mono stream with a fixed format and samplerate.
@ -22,7 +22,7 @@ as a single mono stream with a fixed format and samplerate.
This makes it possible to link any of the audio ports together This makes it possible to link any of the audio ports together
without doing conversions. without doing conversions.
### Applications can connect to audio devices ## Applications Can Connect To Audio Devices
Applications can create ports that can connect to the audio ports Applications can create ports that can connect to the audio ports
so that data can be provided to or consumed from them. so that data can be provided to or consumed from them.
@ -30,19 +30,19 @@ so that data can be provided to or consumed from them.
It should be possible to automatically connect an application to It should be possible to automatically connect an application to
a sink/source when it requests this. a sink/source when it requests this.
### Default audio sink and sources ## Default Audio Sink and Sources
It should be possible to mark a source or sink as the default source It should be possible to mark a source or sink as the default source
and sink so that applications are routed to them by default. and sink so that applications are routed to them by default.
It should be possible to change the default audio sink/source. It should be possible to change the default audio sink/source.
### Application should be able to move between sinks/sources ## Application Should Be Able To Move Between Sinks/Sources
It should be possible to move an application from one device to It should be possible to move an application from one device to
another dynamically. another dynamically.
### Exclusive access ## Exclusive Access
Application should be able to connect to a device in exclusive mode. Application should be able to connect to a device in exclusive mode.
This allows the application to negotiate a specific format with the This allows the application to negotiate a specific format with the
@ -62,13 +62,13 @@ Audio devices are implemented with an \ref spa_device "SPA Device" object.
This object is then responsible for controlling the \ref spa_node "SPA Nodes" that This object is then responsible for controlling the \ref spa_node "SPA Nodes" that
provide the audio ports to interface with the device. provide the audio ports to interface with the device.
The Nodes operate on the native audio formats supported by the device. The nodes operate on the native audio formats supported by the device.
This includes the sample rate as well as the number of channels and This includes the sample rate as well as the number of channels and
the audio format. the audio format.
## Audio Adapter ## Audio Adapter
An SPA Node called the "adapter" is usually used with the SPA device Node as An SPA Node called the "adapter" is usually used with the SPA device node as
the internal node. the internal node.
The function of the adapter is to convert the device native format to The function of the adapter is to convert the device native format to
@ -80,14 +80,14 @@ as separate mono ports. This is called the DSP setup.
The audio adapter can also be configured in passthrough mode when it The audio adapter can also be configured in passthrough mode when it
will not do any conversions but simply pass through the port information will not do any conversions but simply pass through the port information
of the internal Node. This can be used to implement exclusive access. of the internal node. This can be used to implement exclusive access.
Setup of the different configurations of the adapter can be done with Setup of the different configurations of the adapter can be done with
the PortConfig parameter. the PortConfig parameter.
## The session manager ## The Session Manager
The session manager is responsible for creating Nodes and Ports for The session manager is responsible for creating nodes and ports for
the various audio devices. It will need to wrap them into an audio the various audio devices. It will need to wrap them into an audio
adapter so that the specific configuration of the node can be adapter so that the specific configuration of the node can be
decided by the policy mode. decided by the policy mode.
@ -96,33 +96,32 @@ The session manager should create name and description for the
devices and nodes. devices and nodes.
The session manager is responsible for assigning priorities to the The session manager is responsible for assigning priorities to the
Nodes. At least \ref PW_KEY_PRIORITY_SESSION and \ref PW_KEY_PRIORITY_DRIVER nodes. At least \ref PW_KEY_PRIORITY_SESSION and \ref PW_KEY_PRIORITY_DRIVER
need to be set. need to be set.
The session manager might need to work with other services to gain The session manager might need to work with other services to gain
exclusive access to the device (e.g. DBus). exclusive access to the device (eg. DBus).
# Implementation # Implementation
## pipewire-media-session (alsa-monitor) ## PipeWire Media Session (alsa-monitor)
PipeWire media session uses the \ref SPA_NAME_API_ALSA_ENUM_UDEV plugin PipeWire media session uses the \ref SPA_NAME_API_ALSA_ENUM_UDEV plugin
for enumerating the ALSA devices. For each device it does: for enumerating the ALSA devices. For each device it does:
- Try to acquire the DBus device reservation object to gain exclusive - Try to acquire the DBus device reservation object to gain exclusive
access to the device. access to the device.
- Create an SPA Device instance for the device and monitor this device instance. - Create an SPA device instance for the device and monitor this device instance.
- For each Node created by the device, create an adapter with - For each node created by the device, create an adapter with
an ALSA PCM node in the context of the PipeWire daemon. an ALSA PCM node in the context of the PipeWire daemon.
The session manager will also create suitable names and descriptions The session manager will also create suitable names and descriptions
for the Devices and Nodes that it creates as well as assign session for the devices and nodes that it creates as well as assign session
and driver priorities. and driver priorities.
The session manager has the option to add extra properties on the The session manager has the option to add extra properties on the
Devices and Node that it creates to control their behavior. This devices and nodes that it creates to control their behavior. This
is implemented with match rules. is implemented with match rules.
*/ */

View file

@ -7,7 +7,7 @@ Typically general, users run one PipeWire daemon that listens for incoming
connections and manages devices. Clients (including the \ref connections and manages devices. Clients (including the \ref
page_session_manager) are separate processes that talk to the daemon using the page_session_manager) are separate processes that talk to the daemon using the
PipeWire socket (default: `$XDG_RUNTIME_DIR/pipewire-0`). This approach PipeWire socket (default: `$XDG_RUNTIME_DIR/pipewire-0`). This approach
provides provides address-space separation between the privileged daemon and provides address-space separation between the privileged daemon and
non-privileged clients. non-privileged clients.
\dot \dot
@ -52,7 +52,7 @@ As shown above, the protocol is handled by the \ref
page_module_protocol_native. From PipeWire's point-of-view this module is just page_module_protocol_native. From PipeWire's point-of-view this module is just
another module. another module.
\section sec_config Configuration Files # Configuration Files
On startup, the daemon reads a configuration file to configure itself. On startup, the daemon reads a configuration file to configure itself.
It executes a series of commands listed in the config file. The lookup order It executes a series of commands listed in the config file. The lookup order
@ -75,14 +75,14 @@ They are applied to the global configuration file. Properties are overwritten
and array elements are appended. This makes it possible to make small custom customizations and array elements are appended. This makes it possible to make small custom customizations
or additions to the main configuration file. or additions to the main configuration file.
The environment variables `PIPEWIRE_CONFIG_DIR`, `PIPEWIRE_CONFIG_PREFIX` The environment variables `PIPEWIRE_CONFIG_DIR`, `PIPEWIRE_CONFIG_PREFIX`,
and `PIPEWIRE_CONFIG_NAME` can be used to specify an alternative config and `PIPEWIRE_CONFIG_NAME`. Can be used to specify an alternative configuration
directory, subdirectory and filename, respectively. directory, subdirectory, and filename respectively.
\subsection sec_config_format Configuration File Format ## Configuration File Format
PipeWire's configuration file format is JSON. In addition to true JSON, PipeWire's configuration file format is JSON. In addition to true JSON
PipeWire also understands a more compact JSON representation where PipeWire also understands a more compact JSON representation. Where
`"` can be omitted around strings, no trailing commas are required and `"` can be omitted around strings, no trailing commas are required and
`:` or `=` can be used to separate object keys from their values. `:` or `=` can be used to separate object keys from their values.
Also, `#` can be used to start a comment until the end of the line. Also, `#` can be used to start a comment until the end of the line.
@ -117,63 +117,60 @@ Allowed configuration file sections are:
- **context.properties** (dictionary): These properties configure the - **context.properties** (dictionary): These properties configure the
pipewire instance. pipewire instance.
- **context.spa-libs** (dictionary): Maps plugin features with globs to a - **context.spa-libs** (dictionary): Maps plugin features with globs to a
spa library. spa library.
- **context.modules** (array): Each entry in the array is a dictionary with - **context.modules** (array): Each entry in the array is a dictionary with
the name of the module to load, including optional args and flags. Most the name of the module to load, including optional args and flags. Most
modules support being loaded multiple times. modules support being loaded multiple times.
- **context.objects** (array): Each entry in the array is a dictionary con - **context.objects** (array): Each entry in the array is a dictionary con
taining the factory to create an object from and optional extra argu taining the factory to create an object from and optional extra argu
ments specific to that factory. ments specific to that factory.
- **context.exec** (array): Each entry in the array is dictionary containing - **context.exec** (array): Each entry in the array is dictionary containing
the path of a program to execute on startup and optional args. This ar the path of a program to execute on startup and optional args. This ar
ray usually contains an entry to start the session manager. ray usually contains an entry to start the session manager.
\section sec_logging Logging # Logging
The `PIPEWIRE_DEBUG` environment variable can be used to enable The `PIPEWIRE_DEBUG` environment variable can be used to enable
more debugging. This variable supports one of two formats: more debugging. This variable supports one of two formats:
- `PIPEWIRE_DEBUG=<level>` where `<level>` is either a numerical log level or it's - `PIPEWIRE_DEBUG=<level>` where `<level>` is either a numerical log level or its
respective key, see below. respective key, see below.
- `PIPEWIRE_DEBUG=<glob1>:<level1>,<glob2>:<level2>,...` where the globs are - `PIPEWIRE_DEBUG=<glob1>:<level1>,<glob2>:<level2>,...` where the globs are
shell-globs to match on log topics and the levels are the respective shell globs to match on log topics and the levels are the respective
log level to set for that topic. Globs are applied in-order and a matching log level to set for that topic. Globs are applied in order and a matching
glob overrides an earlier glob for that category. For example, glob overrides an earlier glob for that category. For example,
`PIPEWIRE_DEBUG=*:E,mod.*:D,mod.foo:X" enables global error messages, `PIPEWIRE_DEBUG=*:E,mod.*:D,mod.foo:X` enables global error messages,
debugging on all modules but no messages on the foo module. debugging on all modules but no messages on the foo module.
- `<level>` specifies the log level: - `<level>` specifies the log level:
+ `X` or `0`: no logging is enabled
+ `E` or `1`: Error logging is enabled + `X` or `0`: No logging is enabled.
+ `W` or `2`: Warnings are enabled + `E` or `1`: Error logging is enabled.
+ `I` or `3`: Informational messages are enabled + `W` or `2`: Warnings are enabled.
+ `D` or `4`: Debug messages are enabled + `I` or `3`: Informational messages are enabled.
+ `D` or `4`: Debug messages are enabled.
+ `T` or `5`: Trace messages are enabled. These messages can be logged + `T` or `5`: Trace messages are enabled. These messages can be logged
from the realtime threads. from the realtime threads.
PipeWire uses a "category.topic" naming scheme, with the following categories: PipeWire uses a `category.topic` naming scheme, with the following categories:
- `pw.*`: pipewire-internal topics
- `mod.*`: module topics, for example `mod.foo` would usually refer to the - `pw.*`: PipeWire internal topics.
"foo" module - `mod.*`: Module topics, for example `mod.foo` would usually refer to the
- `ms.*`: media session topics `foo` module.
- `ms.mod.*`: media session modules, for example `ms.foo` would usually refer - `ms.*`: Media session topics.
to the "media-session-foo" module - `ms.mod.*`: Media session modules, for example `ms.foo` would usually refer
- `conn.*`: connection-specific topics such as printing raw messages sent over to the `media-session-foo` module.
- `conn.*`: Connection specific topics such as printing raw messages sent over
a communication socket. These are in a separate namespace as they are a communication socket. These are in a separate namespace as they are
usually vastly more verbose than the normal debugging topics. usually vastly more verbose than the normal debugging topics.
This namespace must be explicitly enabled with a `conn.<glob>` glob. This namespace must be explicitly enabled with a `conn.<glob>` glob.
The behavior of the logging can be further controlled with the following The behavior of the logging can be further controlled with the following
environment variables: environment variables:
- `PIPEWIRE_LOG_SYSTEMD=false`: disable logging to the systemd journal
- `PIPEWIRE_LOG=<filename>`: redirect the log to the given filename - `PIPEWIRE_LOG_SYSTEMD=false`: Disable logging to the systemd journal.
- `PIPEWIRE_LOG_LINE=false`: don't log filename, function, and source code line - `PIPEWIRE_LOG=<filename>`: Redirect the log to the given filename.
- `PIPEWIRE_LOG_LINE=false`: Don't log filename, function, and source code line.
*/ */

View file

@ -6,13 +6,13 @@ PipeWire is a media server that can run graphs of multimedia nodes.
Nodes can run inside the server process or in separate processes, Nodes can run inside the server process or in separate processes,
communicating with the server. communicating with the server.
PipeWire was designed to PipeWire was designed to:
- be efficient for raw video using fd passing and audio with - Be efficient for raw video using fd passing and audio with
shared ringbuffers shared ringbuffers.
- be able to provide/consume/process media from any process - Be able to provide/consume/process media from any process.
- provide policy to restrict access to devices and streams - Provide policy to restrict access to devices and streams.
- be easily extensible - Be easily extensible.
Although an initial goal, the design is not limited to raw video Although an initial goal, the design is not limited to raw video
only and should be able to handle compressed video and other only and should be able to handle compressed video and other
@ -23,36 +23,30 @@ SPA is designed for low-latency and efficient processing of any multimedia
format. SPA also provides a number of helper utilities that are not available format. SPA also provides a number of helper utilities that are not available
in the standard C library. in the standard C library.
Some of the application we intend to build Some of the application we intend to build:
- v4l2 device provider: Provide controlled access to v4l2 devices - v4l2 device provider: Provide controlled access to v4l2 devices
and share one device between multiple processes. and share one device between multiple processes.
- gnome-shell video provider: GNOME Shell provides a node that
- gnome-shell video provider: GNOME Shell provides a node that gives the contents of the frame buffer for screen sharing or
gives the contents of the frame buffer for screen sharing or screen recording.
screen recording. - Audio server: Mix and playback multiple audio streams. The design
is more like CRAS (Chromium audio server) than PulseAudio and with
- audio server: Mix and playback multiple audio streams. The design the added benefit that processing can be arranged in a graph.
is more like CRAS (Chromium audio server) than PulseAudio and with - Professional audio graph processing like JACK.
the added benefit that processing can be arranged in a graph. - Media playback backend.
- Pro audio graph processing like JACK.
- Media playback backend
Protocol # Protocol
--------
The native protocol and object model is similar to The native protocol and object model is similar to
[Wayland](https://wayland.freedesktop.org) but with custom [Wayland](https://wayland.freedesktop.org) but with custom
serialization/deserialization of messages. This is because the datastructures serialization/deserialization of messages. This is because the data structures
in the messages are more complicated and not easily expressible in XML. in the messages are more complicated and not easily expressible in XML.
See \ref page_module_protocol_native for details. See \ref page_module_protocol_native for details.
Extensibility # Extensibility
-------------
The functionality of the server is implemented and extended with modules and The functionality of the server is implemented and extended with modules and
extensions. Modules are server side bits of logic that hook into various extensions. Modules are server side bits of logic that hook into various
@ -64,16 +58,13 @@ Extensions are the client side version of the modules. Most extensions provide
both a client side and server side init function. New interfaces or new object both a client side and server side init function. New interfaces or new object
implementation can easily be added with modules/extensions. implementation can easily be added with modules/extensions.
Some of the extensions that can be written Some of the extensions that can be written:
- protocol extensions: a client/server side API (.h) together with protocol - Protocol extensions: A client/server side API (.h) together with protocol
extensions and server/client side logic to implement a new object or extensions and server/client side logic to implement a new object or
interface. interface.
- A module to check security of method calls.
- a module to check security of method calls - A module to automatically create, link or relink nodes.
- A module to suspend idle nodes.
- a module to automatically create, link or relink nodes
- a module to suspend idle nodes
*/ */

View file

@ -1,15 +1,15 @@
/** \page page_library PipeWire Library /** \page page_library PipeWire Library
There are 2 main components that make up the PipeWire library: There are two main components that make up the PipeWire library:
1. An implementation of a graph based media processing engine. 1. An implementation of a graph based media processing engine.
2. An asynchronous IPC mechanism to manipulate and introspect 2. An asynchronous IPC mechanism to manipulate and introspect
a graph in another process. a graph in another process.
There is usually a daemon that implements the global graph and There is usually a daemon that implements the global graph and
clients that operate on this graph. clients that operate on this graph.
The IPC mechanism in PipeWire is inspired by wayland in that it The IPC mechanism in PipeWire is inspired by Wayland in that it
follows the same design principles of objects and methods/events follows the same design principles of objects and methods/events
along with how this API is presented to the user. along with how this API is presented to the user.
@ -18,7 +18,8 @@ be added (or removed) by the user. Plugins can hook into many
aspects of PipeWire and change the behaviour or number of aspects of PipeWire and change the behaviour or number of
features dynamically. features dynamically.
## Principles
# Principles
The PipeWire API is an object oriented asynchronous protocol. The PipeWire API is an object oriented asynchronous protocol.
All requests and replies are method invocations on some object. All requests and replies are method invocations on some object.
@ -51,7 +52,8 @@ their state.
State about objects can be obtained by binding to them and listening State about objects can be obtained by binding to them and listening
for state changes. for state changes.
## Versioning
# Versioning
All interfaces have a version number. The maximum supported version All interfaces have a version number. The maximum supported version
number of an interface is advertized in the registry global event. number of an interface is advertized in the registry global event.
@ -64,7 +66,8 @@ Interfaces increase their version number when new methods or events
are added. Methods or events should never be removed or changed for are added. Methods or events should never be removed or changed for
simplicity. simplicity.
## Proxies and resources
# Proxies and Resources
When a client connects to a PipeWire daemon, a new `struct pw_proxy` When a client connects to a PipeWire daemon, a new `struct pw_proxy`
object is created with ID 0. The `struct pw_core` interface is object is created with ID 0. The `struct pw_core` interface is
@ -83,25 +86,22 @@ ID) becomes unused. The client is responsible for destroying the
proxy when it no longer wants to use it. proxy when it no longer wants to use it.
## Interfaces # Interfaces
### `struct pw_loop` ## struct pw_loop
An abstraction for a `poll(2)` loop. It is usually part of one of: An abstraction for a `poll(2)` loop. It is usually part of one of:
* `struct pw_main_loop`: a helper that can run and stop a `pw_loop`. - `struct pw_main_loop`: A helper that can run and stop a `pw_loop`.
- `struct pw_thread_loop`: A helper that can run and stop a `pw_loop`
in a different thread. It also has some helper
functions for various thread related synchronization
issues.
- `struct pw_data_loop`: A helper that can run and stop a `pw_loop`
in a real-time thread along with some useful helper
functions.
* `struct pw_thread_loop`: a helper that can run and stop a `pw_loop` ## struct pw_context
in a different thread. It also has some helper
functions for various thread related synchronization
issues.
* `struct pw_data_loop`: a helper that can run and stop a `pw_loop`
in a real-time thread along with some useful helper
functions.
### `struct pw_context`
The main context for PipeWire resources. It keeps track of the mainloop, The main context for PipeWire resources. It keeps track of the mainloop,
loaded modules, the processing graph and proxies to remote PipeWire loaded modules, the processing graph and proxies to remote PipeWire
@ -113,8 +113,7 @@ when creating a context.
The context has methods to create the various objects you can use to The context has methods to create the various objects you can use to
build a server or client application. build a server or client application.
## struct pw_core
### `struct pw_core`
A proxy to a remote PipeWire instance. This is used to send messages A proxy to a remote PipeWire instance. This is used to send messages
to a remote PipeWire daemon and to receive events from it. to a remote PipeWire daemon and to receive events from it.
@ -125,63 +124,63 @@ or to perform a roundtrip message to flush out pending requests.
Other core methods and events are used internally for the object Other core methods and events are used internally for the object
life cycle management. life cycle management.
### `struct pw_registry` ## struct pw_registry
A proxy to a PipeWire registry object. It emits events about the A proxy to a PipeWire registry object. It emits events about the
available objects on the server and can be used to bind to those available objects on the server and can be used to bind to those
objects in order to call methods or receive events from them. objects in order to call methods or receive events from them.
### `struct pw_module` ## struct pw_module
A proxy to a loadable module. Modules implement functionality such A proxy to a loadable module. Modules implement functionality such
as provide new objects or policy. as provide new objects or policy.
### `struct pw_factory` ## struct pw_factory
A proxy to an object that can create other objects. A proxy to an object that can create other objects.
### `struct pw_device` ## struct pw_device
A proxy to a device object. Device objects model a physical hardware A proxy to a device object. Device objects model a physical hardware
or software device in the system and can create other objects or software device in the system and can create other objects
such as nodes or other devices. such as nodes or other devices.
### `struct pw_node` ## struct pw_node
A Proxy to a processing node in the graph. Nodes can have input and A Proxy to a processing node in the graph. Nodes can have input and
output ports and the ports can be linked together to form a graph. output ports and the ports can be linked together to form a graph.
### `struct pw_port` ## struct pw_port
A Proxy to an input or output port of a node. They can be linked A Proxy to an input or output port of a node. They can be linked
together to form a processing graph. together to form a processing graph.
### `struct pw_link` ## struct pw_link
A proxy to a link between in output and input port. A link negotiates A proxy to a link between in output and input port. A link negotiates
a format and buffers between ports. A port can be linked to many other a format and buffers between ports. A port can be linked to many other
ports and PipeWire will manage mixing and duplicating the buffers. ports and PipeWire will manage mixing and duplicating the buffers.
## High level helper objects # High Level Helper Objects
Some high level objects are implemented to make it easier to interface Some high level objects are implemented to make it easier to interface
with a PipeWire graph. with a PipeWire graph.
### `struct pw_filter` ## struct pw_filter
A `struct pw_filter` allows you implement a processing filter that can A `struct pw_filter` allows you implement a processing filter that can
be added to a PipeWire graph. It is comparable to a JACK client. be added to a PipeWire graph. It is comparable to a JACK client.
### `struct pw_stream` ## struct pw_stream
a `struct pw_stream` makes it easy to implement a playback or capture A `struct pw_stream` makes it easy to implement a playback or capture
client for the graph. It takes care of format conversion and buffer client for the graph. It takes care of format conversion and buffer
sizes. It is comparable to Core Audio AudioQueue or a PulseAudio sizes. It is comparable to Core Audio AudioQueue or a PulseAudio
stream. stream.
## Security # Security
With the default native protocol, clients connect to PipeWire using With the default native protocol, clients connect to PipeWire using
a named socket. This results in a client socket that is used to a named socket. This results in a client socket that is used to
@ -215,13 +214,14 @@ PipeWire uses memfd (`memfd_create(2)`) or DMA-BUF for sharing media
and data between clients. Clients can thus not look at other clients and data between clients. Clients can thus not look at other clients
data unless they can see the objects and connect to them. data unless they can see the objects and connect to them.
## Implementation
# Implementation
PipeWire also exposes an API to implement the server side objects in PipeWire also exposes an API to implement the server side objects in
a graph. a graph.
## Error reporting # Error Reporting
Functions return either NULL with errno set or a negative int error Functions return either NULL with errno set or a negative int error
code when an error occurs. Error codes are used from the SPA plugin code when an error occurs. Error codes are used from the SPA plugin
@ -237,6 +237,4 @@ signal the completion of the async operation (with, for example, a
callback). The sequence number can be used to see which operation callback). The sequence number can be used to see which operation
completed. completed.
*/ */

View file

@ -2,41 +2,43 @@
This document explains how MIDI is implemented. This document explains how MIDI is implemented.
# Use cases
### MIDI devices are made available as processing nodes/ports # Use Cases
## MIDI Devices Are Made Available As Processing Nodes/Ports
Applications need to be able to see a port for each stream of a Applications need to be able to see a port for each stream of a
MIDI device. MIDI device.
### MIDI devices can be plugged and unplugged ## MIDI Devices Can Be Plugged and Unplugged
When devices are plugged and unplugged the associated nodes/ports When devices are plugged and unplugged the associated nodes/ports
need to be created and removed. need to be created and removed.
### Applications can connect to MIDI devices ## Applications Can Connect To MIDI Devices
Applications can create ports that can connect to the MIDI ports Applications can create ports that can connect to the MIDI ports
so that data can be provided to or consumed from them. so that data can be provided to or consumed from them.
### Some MIDI devices are sinks or sources for midi data ## Some MIDI Devices Are Sinks Or Sources For MIDI Data
It should be possible to create a MIDI sink or source that routes the It should be possible to create a MIDI sink or source that routes the
midi events to specific midi ports. MIDI events to specific MIDI ports.
One example of such a sink would be in front of a software midi One example of such a sink would be in front of a software MIDI
renderer. renderer.
An example of a MIDI source would be after a virtual keyboard or An example of a MIDI source would be after a virtual keyboard or
as a mix from many midi input devices. as a mix from many MIDI input devices.
### Applications should autoconnect to MIDI sinks or sources ## Applications Should Auto-connect To MIDI Sinks Or Sources
An application should be able to be connected to a MIDI sink when An application should be able to be connected to a MIDI sink when
it wants to play midi data. it wants to play MIDI data.
An application should be able to connect to a MIDI source when it An application should be able to connect to a MIDI source when it
wants to capture midi data. wants to capture MIDI data.
# Design # Design
@ -48,7 +50,7 @@ control input and output Ports. These ports have a media type of
are of type \ref spa_pod_sequence with the \ref spa_pod_control type set to are of type \ref spa_pod_sequence with the \ref spa_pod_control type set to
\ref SPA_CONTROL_Midi. \ref SPA_CONTROL_Midi.
This means that every midi event is timestamped with the sample This means that every MIDI event is timestamped with the sample
offset against the current graph clock cycle to get sample accurate offset against the current graph clock cycle to get sample accurate
midi events that can be aligned with the corresponding sample data. midi events that can be aligned with the corresponding sample data.
@ -56,13 +58,13 @@ Since the MIDI events are embedded in the generic control stream,
they can be interleaved with other control message types, such as they can be interleaved with other control message types, such as
property updates or OSC messages. property updates or OSC messages.
## The PipeWire daemon ## The PipeWire Daemon
Nothing special is implemented for MIDI. Negotiation of formats Nothing special is implemented for MIDI. Negotiation of formats
happens between `"application/control"` media types and buffers are happens between `"application/control"` media types and buffers are
negotiated in the same way as any generic format. negotiated in the same way as any generic format.
## The session manager ## The Session Manager
The session manager needs to create the MIDI nodes/ports for the available The session manager needs to create the MIDI nodes/ports for the available
devices. devices.
@ -76,10 +78,10 @@ in order to route MIDI streams to them from applications that want this.
# Implementation # Implementation
## pipewire-media-session ## PipeWire Media Session
PipeWire media session uses the \ref SPA_NAME_API_ALSA_SEQ_BRIDGE plugin for PipeWire media session uses the \ref SPA_NAME_API_ALSA_SEQ_BRIDGE plugin for
the midi features. This creates a single SPA Node with ports per the MIDI features. This creates a single SPA Node with ports per
MIDI client/stream. MIDI client/stream.
The media session will check the permissions on `/dev/snd/seq` before The media session will check the permissions on `/dev/snd/seq` before
@ -88,7 +90,7 @@ until the sequencer device node is accessible.
## JACK ## JACK
JACK assumes all `"application/control"` ports are midi ports. JACK assumes all `"application/control"` ports are MIDI ports.
The control messages are converted to the JACK event format by The control messages are converted to the JACK event format by
filtering out the \ref SPA_CONTROL_Midi types. On output ports, the JACK filtering out the \ref SPA_CONTROL_Midi types. On output ports, the JACK
@ -98,5 +100,4 @@ There is a 1 to 1 mapping between the JACK events and control
messages so there is no information loss or need for complicated messages so there is no information loss or need for complicated
conversions. conversions.
*/ */

View file

@ -1,6 +1,4 @@
/** /** \page page_pipewire_modules PipeWire Modules
\page page_pipewire_modules PipeWire Modules
A PipeWire module is effectively a PipeWire client in an `.so` file that A PipeWire module is effectively a PipeWire client in an `.so` file that
shares the \ref pw_context with the loading entity. Usually modules are shares the \ref pw_context with the loading entity. Usually modules are
@ -28,7 +26,7 @@ context.modules = [
... ...
] ]
``` ```
And the matching libraries are: The matching libraries are:
``` ```
$ ls -1 /usr/lib64/pipewire-0.3/libpipewire-module* $ ls -1 /usr/lib64/pipewire-0.3/libpipewire-module*
... ...
@ -49,7 +47,6 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args).`
See the \ref page_module_example_sink and \ref page_module_example_source See the \ref page_module_example_sink and \ref page_module_example_source
modules for a general oveview of how modules look like. modules for a general oveview of how modules look like.
List of known modules: List of known modules:
- \subpage page_module_access - \subpage page_module_access
@ -79,5 +76,4 @@ List of known modules:
- \subpage page_module_x11_bell - \subpage page_module_x11_bell
- \subpage page_module_zeroconf_discover - \subpage page_module_zeroconf_discover
*/ */

View file

@ -1,11 +1,12 @@
/** \page page_objects_design Objects Design /** \page page_objects_design Objects Design
This document is a design reference on the various objects that exist This document is a design reference on the various objects that exist
in the PipeWire media and session management graphs, explaining what these in the PipeWire media and session management graphs. Explaining what these
objects are, how they are meant to be used and how they relate to other objects are, how they are meant to be used, and how they relate to other
kinds of objects and concepts that exist in subsystems or other libraries. kinds of objects and concepts that exist in subsystems or other libraries.
## The media graph
# The Media Graph
The media graph represents and enables the media flow inside the PipeWire The media graph represents and enables the media flow inside the PipeWire
daemon and between the daemon and its clients. It consists of nodes, ports daemon and between the daemon and its clients. It consists of nodes, ports
@ -21,7 +22,7 @@ and links.
+------------+ +------------+ +------------+ +------------+
``` ```
### Node ## Node
A **node** is a media processing element. It consumes and/or produces buffers A **node** is a media processing element. It consumes and/or produces buffers
that contain data, such as audio or video. that contain data, such as audio or video.
@ -33,26 +34,28 @@ client using the PipeWire protocol.
In an analogy to GStreamer, a _node_ is similar (but not equal) to a In an analogy to GStreamer, a _node_ is similar (but not equal) to a
GStreamer _element_. GStreamer _element_.
### Port ## Port
A **port** is attached on a **node** and provides an interface for input A **port** is attached on a **node** and provides an interface for input
or output of media on the node. A node may have multiple ports. or output of media on the node. A node may have multiple ports.
A port always has a direction, input or output: A port always has a direction, input or output:
- Input: it allows media input into the node (in other terms, it is a _sink_) - Input: it allows media input into the node (in other terms, it is a _sink_)
- Output: it outputs media out of the node (in other terms, it is a _source_) - Output: it outputs media out of the node (in other terms, it is a _source_)
In an analogy to GStreamer, a _port_ is similar (but not equal) to a In an analogy to GStreamer, a _port_ is similar (but not equal) to a
GStreamer _pad_. GStreamer _pad_.
### Link ## Link
A **link** connects 2 ports of opposite direction, making media flow from A **link** connects two ports of opposite direction, making media flow from
the output port to the input port. the output port to the input port.
## The session management graph
The session management graph is a virtual, higher-level representation of the # The Session Management Graph
The session management graph is a virtual, higher level representation of the
media flow. It is created entirely by the session manager and it can affect media flow. It is created entirely by the session manager and it can affect
the routing on the media graph only through the session manager's actions. the routing on the media graph only through the session manager's actions.
@ -70,28 +73,31 @@ codebase.
+---------------------+ +----------------------+ +---------------------+ +----------------------+
``` ```
### Endpoint ## Endpoint
An **endpoint** is a session management object that provides a representation An **endpoint** is a session management object that provides a representation
of user-conceivable places where media can be routed to/from. of user conceivable places where media can be routed to/from.
Examples of endpoints associated with hardware on a desktop-like system: Examples of endpoints associated with hardware on a desktop-like system:
- Laptop speakers
- USB webcam - Laptop speakers.
- Bluetooth headset microphone - USB webcam.
- Line out stereo jack port - Bluetooth headset microphone.
- Line out stereo jack port.
Examples of endpoints associated with hardware in a car: Examples of endpoints associated with hardware in a car:
- Speakers amplifier
- Front right seat microphone array - Speakers amplifier.
- Rear left seat headphones - Front right seat microphone array.
- Bluetooth phone voice gateway - Rear left seat headphones.
- Hardware FM radio device - Bluetooth phone voice gateway.
- Hardware FM radio device.
Examples of endpoints associated with software: Examples of endpoints associated with software:
- Desktop screen capture source
- Media player application - Desktop screen capture source.
- Camera application - Media player application.
- Camera application.
In most cases an endpoint maps to a node on the media graph, but this is not In most cases an endpoint maps to a node on the media graph, but this is not
always the case. An endpoint may be backed by several nodes or no nodes at all. always the case. An endpoint may be backed by several nodes or no nodes at all.
@ -107,7 +113,7 @@ be able to represent the *CD player endpoint* and the _endpoint link_ between
it and the amplifier, so that it can apply audio policy that takes into account it and the amplifier, so that it can apply audio policy that takes into account
whether the CD player is playing or not. whether the CD player is playing or not.
#### Target ### Target
An **endpoint** may be grouping together targets that can be reached by An **endpoint** may be grouping together targets that can be reached by
following the same route and they are mutually exclusive with each other. following the same route and they are mutually exclusive with each other.
@ -121,7 +127,7 @@ In this case, a session manager may choose to group these two targets into the
same endpoint, using a parameter on the _endpoint_ object to allow the user same endpoint, using a parameter on the _endpoint_ object to allow the user
to choose the target (if the hardware allows configuring this at all). to choose the target (if the hardware allows configuring this at all).
### Endpoint Stream ## Endpoint Stream
An **endpoint stream** is attached to an **endpoint** and represents a logical An **endpoint stream** is attached to an **endpoint** and represents a logical
path that can be taken to reach this endpoint, often associated with path that can be taken to reach this endpoint, often associated with
@ -129,45 +135,48 @@ a _use case_.
For example, the "Speakers amplifier" endpoint in a car might have the For example, the "Speakers amplifier" endpoint in a car might have the
following streams: following streams:
- _Music_: a path to play music;
the implementation will output this to all speakers, using the volume - _Music_: A path to play music;
that has been configured for the "Music" use case the implementation will output this to all speakers, using the volume
- _Voice_: a path to play a voice message, such as a navigation message or that has been configured for the "Music" use case.
feedback from a voice assistant; the implementation will output this - _Voice_: A path to play a voice message; such as a navigation message or
to the front speakers only, lowering the volume of the music (if any) feedback from a voice assistant, the implementation will output this
on these speakers at the same time to the front speakers only. Lowering the volume of the music (if any)
- _Emergency_: a path to play an emergency situation sound (a beep, on these speakers at the same time.
or equivalent); the implementation will output this on all speakers, - _Emergency_: A path to play an emergency situation sound (a beep,
increasing the volume to a factory-defined value if necessary (to ensure or equivalent); the implementation will output this on all speakers.
that it is audible) while muting audio from all other streams at the Increasing the volume to a factory defined value if necessary (to ensure
same time that it is audible) while muting audio from all other streams at the
same time.
In another example, a microphone that can be used for activating a voice In another example, a microphone that can be used for activating a voice
assistant might have the following streams: assistant might have the following streams:
- _Capture_: a path to capture directly from the microphone; this can be used
by an application that listens for the assistant's wake-word in order - _Capture_: A path to capture directly from the microphone; this can be used
to activate the full voice recognition engine by an application that listens for the assistant's wake-word in order
- _CaptureDelayed_: a path to capture with a constant delay (meaning that to activate the full voice recognition engine.
starting capturing now will actually capture something that was spoken - _CaptureDelayed_: A path to capture with a constant delay (meaning that
a little earlier); this can be used by the full voice recognition engine, starting capturing now will actually capture something that was spoken
allowing it to start after the wake-word has been spoken while capturing a little earlier); this can be used by the full voice recognition engine,
audio that also includes the wake-word allowing it to start after the wake-word has been spoken while capturing
audio that also includes the wake-word.
Endpoint streams may be mutually exclusive or they may used simultaneously, Endpoint streams may be mutually exclusive or they may used simultaneously,
depending on the implementation. depending on the implementation.
Endpoint streams may be implemented in many ways: Endpoint streams may be implemented in many ways:
- By plugging additional nodes in the media graph that link to the device node
(ex. a simple buffering node linked to an alsa source node could implement
the _CaptureDelayed_ stream in the above microphone example)
- By using a different device node (ex. different ALSA device on the same card)
that has a special meaning for the hardware
- By triggering switches on the hardware (ex. modify ALSA controls on the
same device)
### Endpoint Link - By plugging additional nodes in the media graph that link to the device node
(ex. a simple buffering node linked to an alsa source node could implement
the _CaptureDelayed_ stream in the above microphone example).
- By using a different device node (ex. different ALSA device on the same card)
that has a special meaning for the hardware.
- By triggering switches on the hardware (ex. modify ALSA controls on the
same device).
An **endpoint link** connects 2 streams from 2 different endpoints, creating ## Endpoint Link
An **endpoint link** connects two streams from two different endpoints, creating
a logical representation of media flow between the endpoints. a logical representation of media flow between the endpoints.
An **endpoint link** may be implemented by creating one or more _links_ in the An **endpoint link** may be implemented by creating one or more _links_ in the
@ -175,7 +184,7 @@ underlying media graph, or it may be implemented by configuring hardware
resources to enable media flow, in case the flow does not pass through the resources to enable media flow, in case the flow does not pass through the
media graph. media graph.
#### Constructing ### Constructing
Constructing an **endpoint link** is done by asking the _endpoint stream_ Constructing an **endpoint link** is done by asking the _endpoint stream_
objects to prepare it. First, the source stream is asked to provide linking objects to prepare it. First, the source stream is asked to provide linking
@ -185,40 +194,43 @@ When this is done, the session manager is asked to create the link using the
provided information. provided information.
This mechanism allows stream implementations: This mechanism allows stream implementations:
- to prepare for linking, adjusting hardware paths if necessary
- to check for stream linking compatibility; not all streams can be connected
to all others (ex. streams with media flow in the hardware cannot be linked
to streams that are backed by nodes in the media graph)
- to provide implementation-specific information for linking; in the standard
case this is going to be a list of _ports_ to be linked in the media graph,
but in a hardware-flow case it can be any kind of hardware-specific detail
## Other related objects - To prepare for linking, adjusting hardware paths if necessary.
- To check for stream linking compatibility; not all streams can be connected
to all others (ex. streams with media flow in the hardware cannot be linked
to streams that are backed by nodes in the media graph).
- To provide implementation specific information for linking; in the standard
case this is going to be a list of _ports_ to be linked in the media graph,
but in a hardware-flow case it can be any kind of hardware-specific detail.
### Device
# Other Related Objects
## Device
A **device** represents a handle to an underlying API that is used to create A **device** represents a handle to an underlying API that is used to create
higher level objects, such as nodes, or other devices. higher level objects, such as nodes, or other devices.
Well-known devices include: Well-known devices include:
| Device API | Description | | Device API | Description |
| :--- | :--- | | :--- | :--- |
| alsa.pcm.device | A handle to an ALSA card (ex. `hw:0`, `hw:1`, etc) | | alsa.pcm.device | A handle to an ALSA card (ex. `hw:0`, `hw:1`, etc). |
| alsa.seq.device | A handle to an ALSA Midi device | | alsa.seq.device | A handle to an ALSA Midi device. |
| v4l2.device | A handle to a V4L2 device (`/dev/video0`, `/dev/video1`, etc..) | | v4l2.device | A handle to a V4L2 device (`/dev/video0`, `/dev/video1`, etc..). |
| jack.device | A JACK client, allowing PipeWire to slave to JACK for audio input/output | | jack.device | A JACK client, allowing PipeWire to slave to JACK for audio input/output. |
A device may have a _profile_, which allows the user to choose between A device may have a _profile_, which allows the user to choose between
multiple configurations that the device may be capable of having, or to simply multiple configurations that the device may be capable of having, or to simply
turn the device _off_, which means that the handle is closed and not used turn the device _off_, which means that the handle is closed and not used
by PipeWire. by PipeWire.
### Session ## Session
The **session** represents the session manager and can be used to expose The **session** represents the session manager and can be used to expose
global properties or methods that affect the session management. global properties or methods that affect the session management.
#### Default endpoints ### Default Endpoints
The session is responsible for book-keeping the default device endpoints (one The session is responsible for book-keeping the default device endpoints (one
for each kind of device) that is to be used to link new clients when for each kind of device) that is to be used to link new clients when
@ -227,17 +239,18 @@ device preferences.
For example, a system may have both "Speakers" and "HDMI" endpoints on the For example, a system may have both "Speakers" and "HDMI" endpoints on the
"Audio Output" category and the user may be offered to make a choice within "Audio Output" category and the user may be offered to make a choice within
the UI to select which endpoint she wants to use by default for audio output. the UI to select which endpoint they want to use by default for audio output.
This preference is meant to be stored in the session object. This preference is meant to be stored in the session object.
#### Multiple sessions ### Multiple Sessions
It is not currently defined whether it is allowed to have multiple sessions It is not currently defined whether it is allowed to have multiple sessions
or not and how the system should behave if this happens. or not and how the system should behave if this happens.
## Mappings to underlying subsystem objects
### ALSA UCM # Mappings To Underlying Subsystem Objects
## ALSA UCM
This is a ***proposal*** This is a ***proposal***
@ -252,15 +265,15 @@ This is a ***proposal***
In UCM mode, an ALSA card is represented as a PipeWire device, with the In UCM mode, an ALSA card is represented as a PipeWire device, with the
available UCM verbs listed as profiles of the device. available UCM verbs listed as profiles of the device.
Activating a profile (i.e. a verb) will create the necessary nodes for the Activating a profile (ie. a verb) will create the necessary nodes for the
available PCM streams and at the same time it will also create one endpoint available PCM streams and at the same time it will also create one endpoint
for each UCM device. Optionally, conflicting UCM devices can be grouped in for each UCM device. Optionally conflicting UCM devices can be grouped in
the same endpoint, listing the conflicting options as targets of the endpoint. the same endpoint, listing the conflicting options as targets of the endpoint.
The available UCM modifiers for each UCM device will be added as streams, plus The available UCM modifiers for each UCM device will be added as streams, plus
one "default" stream for accessing the device with no modifiers. one "default" stream for accessing the device with no modifiers.
### ALSA fallback ## ALSA Fallback
| ALSA | PipeWire | | ALSA | PipeWire |
| :--- | :--- | | :--- | :--- |
@ -268,15 +281,15 @@ one "default" stream for accessing the device with no modifiers.
| PCM stream | node + endpoint | | PCM stream | node + endpoint |
In the case where UCM (or another similar mechanism) is not available, In the case where UCM (or another similar mechanism) is not available,
ALSA cards are represented as PipeWire devices with only 2 profiles: On/Off ALSA cards are represented as PipeWire devices with only two profiles on/off.
When the On profile is activated, a node and an associated endpoint are created When the on profile is activated, a node and an associated endpoint are created
for every available PCM stream. for every available PCM stream.
Endpoints in this case have only one "default" stream, unless they are extended Endpoints in this case have only one "default" stream, unless they are extended
by the session manager to have software-backed streams. by the session manager to have software-backed streams.
### V4L2 ## V4L2
***FIXME*** ***FIXME***
@ -284,11 +297,12 @@ by the session manager to have software-backed streams.
| :--- | :--- | | :--- | :--- |
| device | device + node | | device | device + node |
## Relationship to other APIs
### PulseAudio # Relationship To Other API's
#### Mapping PipeWire objects for access by PulseAudio clients ## PulseAudio
### Mapping PipeWire Objects For Access By PulseAudio Clients
| PipeWire | PulseAudio | | PipeWire | PulseAudio |
| :--- | :--- | | :--- | :--- |
@ -297,21 +311,21 @@ by the session manager to have software-backed streams.
| endpoint (associated with a device) | sink / source | | endpoint (associated with a device) | sink / source |
| endpoint (associated with a client) | sink-input / source-output | | endpoint (associated with a client) | sink-input / source-output |
| endpoint target | port | | endpoint target | port |
| endpoint stream | N/A, pa clients will be limited to the default stream | | endpoint stream | N/A, PA clients will be limited to the default stream |
#### Mapping PulseAudio clients to PipeWire ### Mapping PulseAudio Clients To PipeWire
| PulseAudio | PipeWire | | PulseAudio | PipeWire |
| :--- | :--- | | :--- | :--- |
| stream | client + node + endpoint (no targets, 1 default stream) | | stream | client + node + endpoint (no targets, 1 default stream) |
### Jack ## Jack
Note: This section is about JACK clients connecting to PipeWire through the Note: This section is about JACK clients connecting to PipeWire through the
JACK compatibility library. The scenario where PipeWire connects to another JACK compatibility library. The scenario where PipeWire connects to another
JACK server as a client is out of scope here. JACK server as a client is out of scope here.
#### Mapping PipeWire objects for access by JACK clients ### Mapping PipeWire Objects For Access By JACK Clients
| PipeWire | JACK | | PipeWire | JACK |
| :--- | :--- | | :--- | :--- |
@ -320,7 +334,7 @@ JACK server as a client is out of scope here.
| device | N/A | | device | N/A |
| endpoint | N/A | | endpoint | N/A |
#### Mapping JACK clients to PipeWire ### Mapping JACK Clients To PipeWire
| JACK | PipeWire | | JACK | PipeWire |
| :--- | :--- | | :--- | :--- |
@ -328,6 +342,6 @@ JACK server as a client is out of scope here.
| port | port | | port | port |
JACK clients do not create endpoints. A session manager should be JACK aware JACK clients do not create endpoints. A session manager should be JACK aware
in order to anticipate direct node linking in order to anticipate direct node linking.
*/ */

View file

@ -12,13 +12,14 @@ connects to PipeWire on behalf of the client, informing PipeWire that this
client is a portal-managed client. PipeWire can detect and enforce client is a portal-managed client. PipeWire can detect and enforce
extra permission checks on the portal managed clients. extra permission checks on the portal managed clients.
Once such portal is the [Camera Once such portal is the [camera
portal](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Camera) portal](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Camera)
that provides a PipeWire session to stream video from a camera. that provides a PipeWire session to stream video from a camera.
# Use cases
### new portal managed clients need device permissions configured # Use Cases
## New Portal Managed Clients Need Device Permissions Configured
When a new client is detected, the available objects need to be When a new client is detected, the available objects need to be
scanned and permissions configured for each of them. scanned and permissions configured for each of them.
@ -26,7 +27,7 @@ scanned and permissions configured for each of them.
Only the devices belonging to the media_roles given by the Only the devices belonging to the media_roles given by the
portal are considered. portal are considered.
### new devices need to be made visible to portal managed clients ## New Devices Need To Be Made Visible To Portal Managed Clients
Newly created objects are made visible to a client when the client Newly created objects are made visible to a client when the client
is allowed to interact with it. is allowed to interact with it.
@ -34,7 +35,7 @@ is allowed to interact with it.
Only the devices belonging to the media_roles given by the Only the devices belonging to the media_roles given by the
portal are considered. portal are considered.
### permissions for a device need to be revoked ## Permissions For A Device Need To Be Revoked
The session manager listens to changes in the permissions of devices The session manager listens to changes in the permissions of devices
and will remove the client permissions accordingly. and will remove the client permissions accordingly.
@ -46,7 +47,7 @@ where these permissions can be managed.
# Design # Design
## The portal ## The Portal
A sandboxed client cannot connect to PipeWire directly. Instead, it connects A sandboxed client cannot connect to PipeWire directly. Instead, it connects
to the sandbox side of the portal which then connects the PipeWire daemon to to the sandbox side of the portal which then connects the PipeWire daemon to
@ -59,7 +60,7 @@ client object:
- `"pipewire.access.portal.is_portal" = true` for the connection of the - `"pipewire.access.portal.is_portal" = true` for the connection of the
portal itself (as opposed to a client managed by the portal). portal itself (as opposed to a client managed by the portal).
- `"pipewire.access.portal.app_id"` the [application id](https://docs.flatpak.org/en/latest/conventions.html#application-ids) of the client. - `"pipewire.access.portal.app_id"` the [application ID](https://docs.flatpak.org/en/latest/conventions.html#application-ids) of the client.
- `"pipewire.access.portal.media_roles"` media roles of the client. - `"pipewire.access.portal.media_roles"` media roles of the client.
Currently only `"Camera"` is defined. Currently only `"Camera"` is defined.
@ -69,9 +70,9 @@ the task of the \ref page_session_manager to make the objects in the graph
visible, depending on the client's `media_roles` (see also \ref visible, depending on the client's `media_roles` (see also \ref
PW_KEY_MEDIA_ROLE). PW_KEY_MEDIA_ROLE).
## The PipeWire portal module ## The PipeWire Portal Module
The pipewire daemon uses the \ref page_module_portal to find the PID of the The PipeWire daemon uses the \ref page_module_portal to find the PID of the
processes that owns the DBus name `org.freedesktop.portal.Desktop` processes that owns the DBus name `org.freedesktop.portal.Desktop`
(see the [XDG Desktop Portal](https://github.com/flatpak/xdg-desktop-portal)). (see the [XDG Desktop Portal](https://github.com/flatpak/xdg-desktop-portal)).
@ -99,7 +100,7 @@ digraph pw {
} }
\enddot \enddot
## The client ## The Client
A client can ask the portal for a connection to the PipeWire daemon. A client can ask the portal for a connection to the PipeWire daemon.
@ -145,7 +146,6 @@ digraph pw {
} }
\enddot \enddot
The file descriptor for this restricted connection is passed back to the The file descriptor for this restricted connection is passed back to the
client which can now make use of the resources it has been permitted to client which can now make use of the resources it has been permitted to
access. access.
@ -169,7 +169,7 @@ digraph pw {
} }
\enddot \enddot
## The session manager ## The Session Manager
The session manager listens for new clients to appear. It will use the The session manager listens for new clients to appear. It will use the
\ref PW_KEY_ACCESS property to find portal connections. For client connections \ref PW_KEY_ACCESS property to find portal connections. For client connections

View file

@ -6,38 +6,41 @@ applications to exchange data.
It provides the mechanism to do so but the policy deciding which components It provides the mechanism to do so but the policy deciding which components
can talk to each other and when is controlled by the session manager. As can talk to each other and when is controlled by the session manager. As
outlined in \ref page_objects_design, PipeWire provides a media graph outlined in \ref page_objects_design, PipeWire provides a media graph
consistent of Devices, Nodes and Ports. The session manager is the one that consisting of devices, nodes and ports. The session manager is the one that
decides on the links between those elements. decides on the links between those elements.
Two prominent session managers currently exist: Two prominent session managers currently exist:
- [PipeWire Media Session](https://gitlab.freedesktop.org/pipewire/media-session), the - [PipeWire Media Session](https://gitlab.freedesktop.org/pipewire/media-session), the
example session manager example session manager.
- [WirePlumber](https://gitlab.freedesktop.org/pipewire/wireplumber), a - [WirePlumber](https://gitlab.freedesktop.org/pipewire/wireplumber), a
modular session manager based on GObject modular session manager based on GObject.
[Documentation](https://pipewire.pages.freedesktop.org/wireplumber/)
This page describes some of the requirements for session managers in general. This page describes some of the requirements for session managers in general.
## Client management
# Client Management
PipeWire provides a \ref page_access "permission system" to limit client's PipeWire provides a \ref page_access "permission system" to limit client's
access to resources but only \ref page_module_access "basic permission access to resources but only \ref page_module_access "basic permission
handling". The session manager is expected to decide whether clients may handling". The session manager is expected to decide whether clients may
access specific resources. access specific resources.
## Device management
# Device Management
PipeWire's responsibility is to open devices, however the decision on which PipeWire's responsibility is to open devices, however the decision on which
devices should be opened is the job of a session manager, including the devices should be opened is the job of a session manager, including the
configuration of those devices. configuration of those devices.
## Endpoint grouping # Endpoint Grouping
An endpoint is, effectively, a group of Nodes that are a logical unit that can An endpoint is, effectively, a group of nodes that are a logical unit that can
consume or produce media data. For example, a Bluetooth speaker may present as consume or produce media data. For example, a Bluetooth speaker may present as
several Nodes but is only one logical unit to stream audio to. several nodes but is only one logical unit to stream audio to.
See \ref page_objects_design for details on Endpoints. See \ref page_objects_design for details on Endpoints.
*/ */

View file

@ -1,6 +1,6 @@
/** \page page_pipewire PipeWire Design /** \page page_pipewire PipeWire Design
## Internals # Internals
- \subpage page_design - \subpage page_design
- \subpage page_audio - \subpage page_audio
@ -11,13 +11,15 @@
- \subpage page_library - \subpage page_library
- \subpage page_dma_buf - \subpage page_dma_buf
## Components
# Components
- \subpage page_daemon - \subpage page_daemon
- \subpage page_tools - \subpage page_tools
- \subpage page_session_manager - \subpage page_session_manager
## Backends
# Backends
- \subpage page_pulseaudio - \subpage page_pulseaudio

View file

@ -1,18 +1,18 @@
/** \page page_pulseaudio PulseAudio compatibility /** \page page_pulseaudio PulseAudio Compatibility
# Internals - Mapping between ALSA and streams # Internals - Mapping Between ALSA and Streams
This explains the mapping between alsa cards and streams and session manager This explains the mapping between alsa cards and streams and session manager
objects. objects.
## ALSA Cards ## ALSA Cards
An ALSA card is exposed as a PipeWire device An ALSA card is exposed as a PipeWire device.
## Streams ## Streams
Each alsa PCM is opened and a Node is created for each PCM stream. Each ALSA PCM is opened and a node is created for each PCM stream.
# Session Manager # Session Manager
@ -22,8 +22,8 @@ The mapping of the PipeWire object hierarchy to the ALSA object hierarchy is the
One PipeWire device is created for every ALSA card. One PipeWire device is created for every ALSA card.
For each UCM verb, a Node is created for the associated PCM devices. - For each UCM verb, a node is created for the associated PCM devices.
For each UCM verb, an Endpoint is created. - For each UCM verb, an endpoint is created.
In a first step: For each available combination of UCM device and modifier, In a first step: For each available combination of UCM device and modifier,
a stream is created. Streams are marked with compatible other streams. a stream is created. Streams are marked with compatible other streams.
@ -31,26 +31,23 @@ a stream is created. Streams are marked with compatible other streams.
Streams with the same modifier and mutually exclusive devices are grouped Streams with the same modifier and mutually exclusive devices are grouped
into one stream and the UCM devices are exposed on the endpoint as destinations. into one stream and the UCM devices are exposed on the endpoint as destinations.
## ALSA Fallback
## ALSA fallback
Each PCM stream (node) becomes an endpoint. The endpoint references the Each PCM stream (node) becomes an endpoint. The endpoint references the
alsa device id ALSA device ID.
Each endpoint has 1 stream (for now) called HiFi Playback / HiFi Capture. Each endpoint has one stream (for now) called HiFi Playback / HiFi Capture.
More streams can be created depending on the format of the node. More streams can be created depending on the format of the node.
## ALSA Pulse UCM
## ALSA pulse UCM Using the ALSA backend of PulseAudio we can create the following streams.
Using the alsa backend of pulseaudio we can create the following streams ## ALSA Pulse Fallback
The pulse ALSA backend will use the mixer controls and some probing to
## ALSA pulse fallback create the following nodes and endpoints.
The pulse alsa backend will use the mixer controls and some probing to
create the following nodes and endpoints
# PulseAudio # PulseAudio
@ -58,14 +55,14 @@ create the following nodes and endpoints
PulseAudio uses the session manager API to construct cards with profiles PulseAudio uses the session manager API to construct cards with profiles
and sink/source with ports. and sink/source with ports.
If an Endpoint references a Device, a card object is created for the device. If an endpoint references a device, a card object is created for the device.
Each Endpoint becomes a sink/source. Each endpoint becomes a sink/source.
Each Stream in the endpoint becomes a profile on the PulseAudio card. Because Each Stream in the endpoint becomes a profile on the PulseAudio card. Because
only one profile is selected on the device, only 1 stream is visible on only one profile is selected on the device, only one stream is visible on
the endpoint. This clashes with the notion that multiple streams can be the endpoint. This clashes with the notion that multiple streams can be
active at the same time but is a pulseaudio limitation. active at the same time but is a PulseAudio limitation.
Each Endpoint destination becomes a port on the sink/source. Each Endpoint destination becomes a port on the sink/source.

View file

@ -6,7 +6,7 @@ A \ref spa_buffer "SPA Buffer" contains metadata and data. There can be many met
> What is the `void*` data pointer in `spa_data`? > What is the `void*` data pointer in `spa_data`?
The data information either has a file descriptor or a data pointer. The type of the `spa_data` tells you what to expect. For a file descriptor, the data pointer can optionally be set when the fd is mapped into memory. Otherwise the user has to mmap the data herself. The data information either has a file descriptor or a data pointer. The type of the `spa_data` tells you what to expect. For a file descriptor, the data pointer can optionally be set when the FD is mapped into memory. Otherwise the user has to mmap the data themselves.
Also associated with each `spa_data` is a chunk, which is read/write and contains the valid region in the `spa_data` (offset, size, stride and some flags). Also associated with each `spa_data` is a chunk, which is read/write and contains the valid region in the `spa_data` (offset, size, stride and some flags).

View file

@ -7,7 +7,7 @@
Types are generally divided into two categories: Types are generally divided into two categories:
- String types: They identify interfaces and highlevel object types. - String types: They identify interfaces and highlevel object types.
- integer types: These are enumerations used in the parts where high - Integer types: These are enumerations used in the parts where high
performance/ease of use/low space overhead is needed. performance/ease of use/low space overhead is needed.
The SPA type is system is statis and very simple but still allows you The SPA type is system is statis and very simple but still allows you
@ -15,7 +15,7 @@ to make and introspect complex object type hierarchies.
See the type system docs for more info. See the type system docs for more info.
## Error codes ## Error Codes
SPA uses negative integers as errno style error codes. Functions that return an SPA uses negative integers as errno style error codes. Functions that return an
int result code generated an error when < 0. `spa_strerror()` can be used to int result code generated an error when < 0. `spa_strerror()` can be used to
@ -27,9 +27,9 @@ in the lower bits. This result is normally identified as a positive success
result code and the sequence number can later be matched to the completion result code and the sequence number can later be matched to the completion
event. event.
## Useful macros ## Useful Macros
SPA comes with some useful macros defined in `<spa/utils/defs.h>` and a SPA comes with some useful macros defined in `<spa/utils/defs.h>` and a
number of utility functions, see \ref spa_utils number of utility functions, see \ref spa_utils.
*/ */

View file

@ -5,30 +5,34 @@ plugins.
It is inspired by many other plugin APIs, mostly LV2 and It is inspired by many other plugin APIs, mostly LV2 and
GStreamer. SPA provides two parts: GStreamer. SPA provides two parts:
- a header-only API with no external dependencies
- a set of support libraries ("plugins") for commonly used functionality - A header-only API with no external dependencies.
- A set of support libraries ("plugins") for commonly used functionality.
The usual approach is that PipeWire and PipeWire clients can use the The usual approach is that PipeWire and PipeWire clients can use the
header-only functions to interact with the plugins. Those plugins are header-only functions to interact with the plugins. Those plugins are
usually loaded at runtime (through `dlopen(3)`. usually loaded at runtime (through `dlopen(3)`).
## Motivation
# Motivation
SPA was designed with the following goals in mind: SPA was designed with the following goals in mind:
- No dependencies, SPA is shipped as a set of header files that have no dependencies except for the standard c library.
- No dependencies, SPA is shipped as a set of header files that have no dependencies except for the standard C library.
- Very efficient both in space and in time. - Very efficient both in space and in time.
- Very configurable and usable in many different environments. All aspects - Very configurable and usable in many different environments. All aspects
of the plugin environment can be configured and changed, like logging, of the plugin environment can be configured and changed, like logging,
poll loops, system calls etc. poll loops, system calls, etc.
- Consistent API - Consistent API.
- Extensible, new API can be added with minimal effort, existing API can be updated and versioned. - Extensible; new API can be added with minimal effort, existing API can be updated and versioned.
The original user of SPA is PipeWire, which uses SPA to implement the The original user of SPA is PipeWire, which uses SPA to implement the
low-level multimedia processing plugins, device detection, mainloops, CPU low-level multimedia processing plugins, device detection, mainloops, CPU
detection and logging, among other things. SPA however can be used outside detection, logging, among other things. SPA however can be used outside
of PipeWire with minimal problems. of PipeWire with minimal problems.
## The SPA header-only API
# The SPA Header-Only API
A very simple example on how SPA headers work are the \ref spa_utils, a set A very simple example on how SPA headers work are the \ref spa_utils, a set
of utilities commonly required by C projects. SPA functions use the `spa_` of utilities commonly required by C projects. SPA functions use the `spa_`
@ -53,7 +57,7 @@ int main(int argc, char **argv) {
\endcode \endcode
## SPA Plugins # SPA Plugins
SPA plugins are shared libraries (`.so` files) that can be loaded at SPA plugins are shared libraries (`.so` files) that can be loaded at
runtime. Each library provides one or more "factories", each of which may runtime. Each library provides one or more "factories", each of which may
@ -68,7 +72,7 @@ between the two logging facilities.
Please see \ref page_spa_plugins for the details on how to use SPA plugins. Please see \ref page_spa_plugins for the details on how to use SPA plugins.
## Further details # Further details
- \ref api_spa - \ref api_spa
- \subpage page_spa_design - \subpage page_spa_design

View file

@ -3,19 +3,21 @@
\ref spa_handle "SPA plugins" are dynamically loadable objects that contain objects and interfaces that \ref spa_handle "SPA plugins" are dynamically loadable objects that contain objects and interfaces that
can be introspected and used at runtime in any application. This document can be introspected and used at runtime in any application. This document
introduces the basic concepts of SPA plugins. It first covers using the API introduces the basic concepts of SPA plugins. It first covers using the API
and then talks about implementing new Plugins. and then talks about implementing new plugins.
## Outline # Outline
To use a plugin, the following steps are required: To use a plugin, the following steps are required:
- **load** the shared library
- **enumerate** the available factories - **Load** the shared library.
- **enumerate** the interfaces in each factory - **Enumerate** the available factories.
- **instantiate** the desired interface - **Enumerate** the interfaces in each factory.
- **use** the interface-specific functions - **Instantiate** the desired interface.
- **Use** the interface-specific functions.
In pseudo-code, loading a logger interface looks like this: In pseudo-code, loading a logger interface looks like this:
\code{.py} \code{.py}
handle = dlopen("$SPA_PLUGIN_PATH/support/libspa-support.so") handle = dlopen("$SPA_PLUGIN_PATH/support/libspa-support.so")
factory_enumeration_func = dlsym(handle, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME) factory_enumeration_func = dlsym(handle, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)
@ -71,18 +73,18 @@ factory interfaces:
\endverbatim \endverbatim
## Open a plugin # Open A Plugin
A plugin is opened with a platform specific API. In this example we use A plugin is opened with a platform specific API. In this example we use
`dlopen()` as the method used on Linux. `dlopen()` as the method used on Linux.
A plugin always consists of 2 parts, the vendor path and then the .so file. A plugin always consists of two parts, the vendor path and then the .so file.
As an example we will load the "support/libspa-support.so" plugin. You will As an example we will load the "support/libspa-support.so" plugin. You will
usually use some mapping between functionality and plugin path, as we'll see usually use some mapping between functionality and plugin path as we'll see
later, instead of hardcoding the plugin name. later, instead of hardcoding the plugin name.
To dlopen a plugin we then need to prefix the plugin path like this: To `dlopen` a plugin we then need to prefix the plugin path like this:
\code{.c} \code{.c}
#define SPA_PLUGIN_PATH /usr/lib64/spa-0.2/" #define SPA_PLUGIN_PATH /usr/lib64/spa-0.2/"
@ -105,7 +107,8 @@ enum_func = dlsym(hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME));
If this symbol is not available, the library is not a valid SPA plugin. If this symbol is not available, the library is not a valid SPA plugin.
## Enumerating factories
# Enumerating Factories
With the `enum_func` we can now enumerate all the factories in the plugin: With the `enum_func` we can now enumerate all the factories in the plugin:
@ -126,7 +129,7 @@ actual new object from it.
We can enumerate the interfaces that we will find on this new object with We can enumerate the interfaces that we will find on this new object with
the `spa_handle_factory_enum_interface_info()` method. Interface types the `spa_handle_factory_enum_interface_info()` method. Interface types
are simple strings that uniquely define the interface (See also the type are simple strings that uniquely define the interface (see also the type
system). system).
The name of the factory is a well-known name that describes the functionality The name of the factory is a well-known name that describes the functionality
@ -142,7 +145,8 @@ definitions for common functionality, for example:
Usually the name will be mapped to a specific plugin. This way an Usually the name will be mapped to a specific plugin. This way an
alternative compatible implementation can be made in a different library. alternative compatible implementation can be made in a different library.
## Making a handle
# Making A Handle
Once we have a suitable factory, we need to allocate memory for the object Once we have a suitable factory, we need to allocate memory for the object
it can create. SPA usually does not allocate memory itself but relies on it can create. SPA usually does not allocate memory itself but relies on
@ -173,10 +177,11 @@ The info parameter should contain the same extra properties given in
The support parameter is an array of `struct spa_support` items. They The support parameter is an array of `struct spa_support` items. They
contain a string type and a pointer to extra support objects. This can contain a string type and a pointer to extra support objects. This can
be a logging API or a main loop API, for example. Some plugins require be a logging API or a main loop API for example. Some plugins require
certain support libraries to function. certain support libraries to function.
## Retrieving an interface
# Retrieving An Interface
When a SPA handle is made, you can retrieve any of the interfaces that When a SPA handle is made, you can retrieve any of the interfaces that
it provides: it provides:
@ -195,7 +200,7 @@ spa_log_warn(log, "Hello World!\n");
\endcode \endcode
## Clearing an object # Clearing An Object
After you are done with a handle you can clear it with After you are done with a handle you can clear it with
`spa_handle_clear()` and you can unload the library with `dlclose()`. `spa_handle_clear()` and you can unload the library with `dlclose()`.
@ -215,7 +220,7 @@ will just call the appropriate method in the implementation.
Interfaces are defined in a header file (for example see Interfaces are defined in a header file (for example see
`<spa/support/log.h>` for the logger API). It is a self contained `<spa/support/log.h>` for the logger API). It is a self contained
definition that you can just use in your application after you dlopen() definition that you can just use in your application after you `dlopen()`
the plugin. the plugin.
Some interfaces also provide extra fields in the interface, like the Some interfaces also provide extra fields in the interface, like the
@ -223,7 +228,8 @@ log interface above that has the log level as a read/write parameter.
See \ref spa_interface for some implementation details on interfaces. See \ref spa_interface for some implementation details on interfaces.
## SPA Events
# SPA Events
Some interfaces will also allow you to register a callback (a hook or Some interfaces will also allow you to register a callback (a hook or
listener) to be notified of events. This is usually when something listener) to be notified of events. This is usually when something
@ -270,7 +276,8 @@ You can remove your listener with:
spa_hook_remove(&listener); spa_hook_remove(&listener);
\endcode \endcode
## API results
# API Results
Some interfaces provide API that gives you a list or enumeration of Some interfaces provide API that gives you a list or enumeration of
objects/values. To avoid allocation overhead and ownership problems, objects/values. To avoid allocation overhead and ownership problems,
@ -280,8 +287,7 @@ stack and push this to the application without allocation or ownership
problems. The application can look at the pushed result and keep/copy problems. The application can look at the pushed result and keep/copy
only what it wants to keep. only what it wants to keep.
## Synchronous Results
### Synchronous results
Here is an example of enumerating parameters on a node interface. Here is an example of enumerating parameters on a node interface.
@ -319,8 +325,7 @@ supported format. After this completes, remove the listener again:
spa_hook_remove(&listener); spa_hook_remove(&listener);
\endcode \endcode
## Asynchronous Results
### Asynchronous results
Asynchronous results are pushed to the application in the same way as Asynchronous results are pushed to the application in the same way as
synchronous results, they are just pushed later. You can check that synchronous results, they are just pushed later. You can check that
@ -342,9 +347,9 @@ sequence number of the async result code, which can be obtained with:
expected_seq = SPA_RESULT_ASYNC_SEQ(res); expected_seq = SPA_RESULT_ASYNC_SEQ(res);
\endcode \endcode
# Implementing a new plugin # Implementing A New Plugin
FIXME ***FIXME***

View file

@ -3,52 +3,54 @@
\ref spa_pod (plain old data) is a sort of data container. It is comparable to \ref spa_pod (plain old data) is a sort of data container. It is comparable to
DBus Variant or LV2 Atom. DBus Variant or LV2 Atom.
A POD can express nested structures of Objects (with properties), Vectors, A POD can express nested structures of objects (with properties), vectors,
Arrays, sequences and various primitives types. All information in the POD arrays, sequences and various primitives types. All information in the POD
is laid out sequentially in memory and can be written directly to is laid out sequentially in memory and can be written directly to
storage or exchanged between processes or threads without additional storage or exchanged between processes or threads without additional
marshalling. marshalling.
Each POD is made of a 32 bits size followed by a 32 bits type field, Each POD is made of a 32 bits size followed by a 32 bits type field,
followed by the pod contents. This makes it possible to skip over unknown followed by the POD contents. This makes it possible to skip over unknown
POD types. The POD start is always aligned to 8 bytes. POD types. The POD start is always aligned to 8 bytes.
PODs can be efficiently constructed and parsed in real-time threads without POD's can be efficiently constructed and parsed in real-time threads without
requiring memory allocations. requiring memory allocations.
PODs use the SPA type system for the basic types and containers. See POD's use the SPA type system for the basic types and containers. See
the SPA types for more info. the SPA types for more info.
## Types
PODs can contain a number of basic SPA types: # Types
- `SPA_TYPE_None`: no value or a NULL pointer. POD's can contain a number of basic SPA types:
- `SPA_TYPE_Bool`: a boolean value
- `SPA_TYPE_Id`: an enumerated value
- `SPA_TYPE_Int`, `SPA_TYPE_Long`, `SPA_TYPE_Float`, `SPA_TYPE_Double`:
- various numeral types, 32 and 64 bits.
- `SPA_TYPE_String`: a string
- `SPA_TYPE_Bytes`: a byte array
- `SPA_TYPE_Rectangle`: a rectangle with width and height
- `SPA_TYPE_Fraction`: a fraction with numerator and denominator
- `SPA_TYPE_Bitmap`: an array of bits
PODs can be grouped together in these container types: - `SPA_TYPE_None`: No value or a NULL pointer.
- `SPA_TYPE_Bool`: A boolean value.
- `SPA_TYPE_Id`: An enumerated value.
- `SPA_TYPE_Int`, `SPA_TYPE_Long`, `SPA_TYPE_Float`, `SPA_TYPE_Double`:
various numeral types, 32 and 64 bits.
- `SPA_TYPE_String`: A string.
- `SPA_TYPE_Bytes`: A byte array.
- `SPA_TYPE_Rectangle`: A rectangle with width and height.
- `SPA_TYPE_Fraction`: A fraction with numerator and denominator.
- `SPA_TYPE_Bitmap`: An array of bits.
- `SPA_TYPE_Array`: an array of equal sized objects POD's can be grouped together in these container types:
- `SPA_TYPE_Struct`: a collection of types and objects
- `SPA_TYPE_Object`: an object with properties
- `SPA_TYPE_Sequence`: a timed sequence of PODs
PODs can also contain some extra types: - `SPA_TYPE_Array`: An array of equal sized objects.
- `SPA_TYPE_Struct`: A collection of types and objects.
- `SPA_TYPE_Object`: An object with properties.
- `SPA_TYPE_Sequence`: A timed sequence of POD's.
- `SPA_TYPE_Pointer`: a typed pointer in memory POD's can also contain some extra types:
- `SPA_TYPE_Fd`: a file descriptor
- `SPA_TYPE_Choice`: a choice of values
- `SPA_TYPE_Pod`: a generic type for the POD itself
# Constructing a POD - `SPA_TYPE_Pointer`: A typed pointer in memory.
- `SPA_TYPE_Fd`: A file descriptor.
- `SPA_TYPE_Choice`: A choice of values.
- `SPA_TYPE_Pod`: A generic type for the POD itself.
# Constructing A POD
A POD is usually constructed with a `struct spa_pod_builder`. The builder A POD is usually constructed with a `struct spa_pod_builder`. The builder
needs to be initialized with a memory region to write into. It is needs to be initialized with a memory region to write into. It is
@ -59,7 +61,7 @@ not require any memory allocations. The size of the POD can be
estimated pretty easily and if the buffer is not large enough, an estimated pretty easily and if the buffer is not large enough, an
appropriate error will be generated. appropriate error will be generated.
The code fragment below initializes a pod builder to write into The code fragment below initializes a POD builder to write into
the stack allocated buffer. the stack allocated buffer.
\code{.c} \code{.c}
@ -96,7 +98,7 @@ pod = spa_pod_builder_pop(&b, &f);
`spa_pod_builder_pop()` returns a reference to the object we completed `spa_pod_builder_pop()` returns a reference to the object we completed
on the stack. on the stack.
## Using varargs builder. ## Using varargs Builder
We can also use the following construct to make POD objects: We can also use the following construct to make POD objects:
@ -116,10 +118,10 @@ pod = spa_pod_builder_add_struct(&b,
SPA_POD_Float(3.1415f)); SPA_POD_Float(3.1415f));
\endcode \endcode
It's not possible to use the varargs builder to make a Sequence or It's not possible to use the varargs builder to make a sequence or
Array, use the normal builder methods for that. array, use the normal builder methods for that.
## Making objects ## Making Objects
POD objects are containers for properties and are comparable to JSON POD objects are containers for properties and are comparable to JSON
objects. objects.
@ -131,7 +133,7 @@ spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
\endcode \endcode
An object requires an object type (`SPA_TYPE_OBJECT_Props`) and a context An object requires an object type (`SPA_TYPE_OBJECT_Props`) and a context
id (`SPA_PARAM_Props`). The object type defines the properties that can be ID (`SPA_PARAM_Props`). The object type defines the properties that can be
added to the object and their meaning. The SPA type system allows you to added to the object and their meaning. The SPA type system allows you to
make this connection (See the type system). make this connection (See the type system).
@ -163,23 +165,23 @@ pod = spa_pod_builder_add_object(&b,
SPA_PROP_frequency, SPA_POD_Float(440.0f)); SPA_PROP_frequency, SPA_POD_Float(440.0f));
\endcode \endcode
## Choice values ## Choice Values
It is possible to express ranges or enumerations of possible It is possible to express ranges or enumerations of possible
values for properties (and to some extend structs). This is achieved values for properties (and to some extend structs). This is achieved
with Choice values. with choice values.
Choice values are really just a choice type and an array of choice values Choice values are really just a choice type and an array of choice values
(of the same type). Depending on the choice type, the array values are (of the same type). Depending on the choice type, the array values are
interpreted in different ways: interpreted in different ways:
* `SPA_CHOICE_None`: no choice, first value is current - `SPA_CHOICE_None`: No choice, first value is current.
* `SPA_CHOICE_Range`: range: default, min, max - `SPA_CHOICE_Range`: Range: default, min, max.
* `SPA_CHOICE_Step`: range with step: default, min, max, step - `SPA_CHOICE_Step`: Range with step: default, min, max, step.
* `SPA_CHOICE_Enum`: enum: default, alternative,... - `SPA_CHOICE_Enum`: Enum: default, alternative,...
* `SPA_CHOICE_Flags`: bitmask of flags - `SPA_CHOICE_Flags`: Bitmask of flags.
Let's illustrate this with a Props object that specifies a range of Let's illustrate this with a props object that specifies a range of
possible values for the frequency: possible values for the frequency:
\code{.c} \code{.c}
@ -195,8 +197,8 @@ pod = spa_pod_builder_pop(&b, &f2);
pod = spa_pod_builder_pop(&b, &f); pod = spa_pod_builder_pop(&b, &f);
\endcode \endcode
As you can see, first push the choice as a Range, then the values. A Range As you can see, first push the choice as a range, then the values. A range
choice expects at least 3 values, the default value, minimum and maximum choice expects at least three values, the default value, minimum and maximum
values. There is a shortcut for this as well using varargs: values. There is a shortcut for this as well using varargs:
\code{.c} \code{.c}
@ -205,7 +207,7 @@ pod = spa_pod_builder_add_object(&b,
SPA_PROP_frequency, SPA_POD_CHOICE_RANGE_Float(440.0f, 110.0f, 880.0f)); SPA_PROP_frequency, SPA_POD_CHOICE_RANGE_Float(440.0f, 110.0f, 880.0f));
\endcode \endcode
## Choice examples ## Choice Examples
This is a description of a possible `SPA_TYPE_OBJECT_Format` as used when This is a description of a possible `SPA_TYPE_OBJECT_Format` as used when
enumerating allowed formats (`SPA_PARAM_EnumFormat`) in SPA objects: enumerating allowed formats (`SPA_PARAM_EnumFormat`) in SPA objects:
@ -253,16 +255,17 @@ pod = spa_pod_builder_add_object(&b,
SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2)); SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2));
\endcode \endcode
# Parsing a POD
Parsing a POD usually consists of # Parsing A POD
* validating if raw bytes + size can contain a valid pod Parsing a POD usually consists of:
* inspecting the type of a pod
* looping over the items in an object or struct
* getting data out of PODs.
## Validating bytes - Validating if raw bytes + size can contain a valid POD.
- Inspecting the type of a POD.
- Looping over the items in an object or struct.
- Getting data out of POD's.
## Validating Bytes
Use `spa_pod_from_data()` to check if maxsize of bytes in data contain Use `spa_pod_from_data()` to check if maxsize of bytes in data contain
a POD at the size bytes starting at offset. This function checks that a POD at the size bytes starting at offset. This function checks that
@ -273,7 +276,7 @@ struct spa_pod *pod;
pod = spa_pod_from_data(data, maxsize, offset, size); pod = spa_pod_from_data(data, maxsize, offset, size);
\endcode \endcode
## Checking the type of POD ## Checking The Type Of POD
Use one of `spa_pod_is_bool()`, `spa_pod_is_int()`, etc to check Use one of `spa_pod_is_bool()`, `spa_pod_is_int()`, etc to check
for the type of the pod. For simple (non-container) types, for the type of the pod. For simple (non-container) types,
@ -283,9 +286,9 @@ extract the value of the pod.
`spa_pod_is_object_type()` can be used to check if the POD contains `spa_pod_is_object_type()` can be used to check if the POD contains
an object of the expected type. an object of the expected type.
## Struct fields ## Struct Fields
To iterate over the fields of a Struct use: To iterate over the fields of a struct use:
\code{.c} \code{.c}
struct spa_pod *pod, *obj; struct spa_pod *pod, *obj;
@ -294,7 +297,7 @@ SPA_POD_STRUCT_FOREACH(obj, pod) {
} }
\endcode \endcode
For parsing Structs it is usually much easier to use the parser For parsing structs it is usually much easier to use the parser
below. below.
## Object Properties ## Object Properties
@ -363,7 +366,7 @@ And finally exit the container again:
spa_pod_parser_pop(&p, &f); spa_pod_parser_pop(&p, &f);
\endcode \endcode
## Parser with variable arguments ## Parser With Variable Arguments
In most cases, parsing objects is easier with the variable argument In most cases, parsing objects is easier with the variable argument
functions. The parse function look like the mirror image of the builder functions. The parse function look like the mirror image of the builder
@ -408,15 +411,15 @@ spa_pod_parser_get_object(&p,
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&channels)); SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&channels));
\endcode \endcode
It is not possible to parse a Sequence or Array with the parser. It is not possible to parse a sequence or array with the parser.
Use the iterator for this. Use the iterator for this.
## Choice values ## Choice Values
The parser will handle Choice values as long as they are of type The parser will handle choice values as long as they are of type
None. It will then parse the single value from the choice. When `none`. It will then parse the single value from the choice. When
dealing with other choice values, it's possible to parse the dealing with other choice values, it's possible to parse the
property values into a `struct spa_pod` and then inspect the Choice property values into a `struct spa_pod` and then inspect the choice
manually, if needed. manually, if needed.
Here is an example of parsing the format values as a POD: Here is an example of parsing the format values as a POD:
@ -432,9 +435,9 @@ spa_pod_parser_get_object(&p,
\endcode \endcode
`spa_pod_get_values()` is a useful function. It returns a `spa_pod_get_values()` is a useful function. It returns a
`struct spa_pod*` with and array of values. For normal PODs `struct spa_pod*` with and array of values. For normal POD's
and Choice None values, it simply returns the POD and 1 value. and choice none values, it simply returns the POD and one value.
For other Choice values it returns the Choice type and an array For other choice values it returns the choice type and an array
of values: of values:
\code{.c} \code{.c}
@ -464,15 +467,16 @@ default:
} }
\endcode \endcode
# Filter # Filter
Given 2 pod objects of the same type (Object, Struct, ..) one can Given two POD objects of the same type (object, struct, ..) one can
run a filter and generate a new pod that only contains values that run a filter and generate a new POD that only contains values that
are compatible with both input pods. are compatible with both input POD's.
This is, for example, used to find a compatible format between two ports. This is, for example, used to find a compatible format between two ports.
As an example we can run a filter on two simple PODs: As an example we can run a filter on two simple POD's:
\code{.c} \code{.c}
pod = spa_pod_builder_add_object(&b, pod = spa_pod_builder_add_object(&b,
@ -511,7 +515,7 @@ result = spa_pod_builder_add_object(&b,
SPA_FORMAT_AUDIO_format, SPA_AUDIO_FORMAT_S16); SPA_FORMAT_AUDIO_format, SPA_AUDIO_FORMAT_S16);
\endcode \endcode
# POD layout # POD Layout
Each POD has a 32 bits size field, followed by a 32 bits type field. The size Each POD has a 32 bits size field, followed by a 32 bits type field. The size
field specifies the size following the type field. field specifies the size following the type field.

View file

@ -10,7 +10,8 @@ PipeWire API step-by-step with simple short examples.
- \subpage page_tutorial5 - \subpage page_tutorial5
- \subpage page_tutorial6 - \subpage page_tutorial6
## More example programs
# More Example Programs
- \ref audio-src.c "": \snippet{doc} audio-src.c title - \ref audio-src.c "": \snippet{doc} audio-src.c title
- \ref audio-dsp-filter.c "": \snippet{doc} audio-dsp-filter.c title - \ref audio-dsp-filter.c "": \snippet{doc} audio-dsp-filter.c title

View file

@ -1,4 +1,4 @@
/** \page page_tutorial1 Tutorial - Part 1: Getting started /** \page page_tutorial1 Tutorial - Part 1: Getting Started
\ref page_tutorial "Index" | \ref page_tutorial2 \ref page_tutorial "Index" | \ref page_tutorial2
@ -7,7 +7,8 @@ In this tutorial we show the basics of a simple PipeWire application.
Use this tutorial to get started and help you set up your development Use this tutorial to get started and help you set up your development
environment. environment.
## Initialization
# Initialization
Let get started with the simplest application. Let get started with the simplest application.
@ -15,10 +16,11 @@ Let get started with the simplest application.
Before you can use any PipeWire functions, you need to call `pw_init()`. Before you can use any PipeWire functions, you need to call `pw_init()`.
## Compilation
# Compilation
PipeWire provides a pkg-config file named `libpipewire-0.3` (note: the version PipeWire provides a pkg-config file named `libpipewire-0.3` (note: the version
suffix may change with future releases of pipewire). suffix may change with future releases of PipeWire).
To compile the simple test application, copy it into a test1.c file and To compile the simple test application, copy it into a test1.c file and
use pkg-config to provide the required dependencies: use pkg-config to provide the required dependencies:

View file

@ -1,4 +1,4 @@
/** \page page_tutorial2 Tutorial - Part 2: Enumerating objects /** \page page_tutorial2 Tutorial - Part 2: Enumerating Objects
\ref page_tutorial1 | \ref page_tutorial "Index" | \ref page_tutorial3 \ref page_tutorial1 | \ref page_tutorial "Index" | \ref page_tutorial3
@ -125,4 +125,5 @@ continue forever. In the next tutorial we'll see how we can nicely
exit our application after we received all server objects. exit our application after we received all server objects.
\ref page_tutorial1 | \ref page_tutorial "Index" | \ref page_tutorial3 \ref page_tutorial1 | \ref page_tutorial "Index" | \ref page_tutorial3
*/ */

View file

@ -1,4 +1,4 @@
/** \page page_tutorial3 Tutorial - Part 3: Forcing a roundtrip /** \page page_tutorial3 Tutorial - Part 3: Forcing A Roundtrip
\ref page_tutorial2 | \ref page_tutorial "Index" | \ref page_tutorial4 \ref page_tutorial2 | \ref page_tutorial "Index" | \ref page_tutorial4

View file

@ -1,4 +1,4 @@
/** \page page_tutorial4 Tutorial - Part 4: Playing a tone /** \page page_tutorial4 Tutorial - Part 4: Playing A Tone
\ref page_tutorial3 | \ref page_tutorial "Index" | \ref page_tutorial5 \ref page_tutorial3 | \ref page_tutorial "Index" | \ref page_tutorial5
@ -57,13 +57,12 @@ and `struct pw_core` automatically.
In the properties we need to give as much information about the stream as we In the properties we need to give as much information about the stream as we
can so that the session manager can make good decisions about how and where can so that the session manager can make good decisions about how and where
to route this stream. There are 3 important properties to configure: to route this stream. There are three important properties to configure:
* `PW_KEY_MEDIA_TYPE` The media type, like Audio, Video, Midi - `PW_KEY_MEDIA_TYPE`: The media type; like Audio, Video, MIDI.
* `pw_KEY_MEDIA_CATEGORY` The category, like Playback, Capture, Duplex, Monitor - `PW_KEY_MEDIA_CATEGORY`: The category; like Playback, Capture, Duplex, Monitor.
* `PW_KEY_MEDIA_ROLE` The media role, like Movie, Music, Camera, Screen, - `PW_KEY_MEDIA_ROLE`: The media role; like Movie, Music, Camera, Screen,
Communication, Game, Notification, DSP, Communication, Game, Notification, DSP, Production, Accessibility, Test.
Production, Accessibility, Test
The properties are owned by the stream and freed when the stream is destroyed The properties are owned by the stream and freed when the stream is destroyed
later. later.
@ -122,15 +121,14 @@ Now we're ready to connect the stream and run the main loop:
To connect we specify that we have a `PW_DIRECTION_OUTPUT` stream. `PW_ID_ANY` To connect we specify that we have a `PW_DIRECTION_OUTPUT` stream. `PW_ID_ANY`
means that we are ok with connecting to any consumer. Next we set some flags: means that we are ok with connecting to any consumer. Next we set some flags:
* `PW_STREAM_FLAG_AUTOCONNECT` automatically connect this stream. This instructs - `PW_STREAM_FLAG_AUTOCONNECT`: Automatically connect this stream. This instructs
the session manager to link us to some consumer. the session manager to link us to some consumer.
* `PW_STREAM_FLAG_MAP_BUFFERS` mmap the buffers for us so we can access the - `PW_STREAM_FLAG_MAP_BUFFERS`: mmap the buffers for us so we can access the
memory. If you don't set these flags you have memory. If you don't set these flags you have either work with the fd or mmap
either work with the fd or mmap yourself. yourself.
* `PW_STREAM_FLAG_RT_PROCESS` Run the process function in the realtime thread. - `PW_STREAM_FLAG_RT_PROCESS`: Run the process function in the realtime thread.
Only use this if the process function only Only use this if the process function only uses functions that are realtime
uses functions that are realtime safe, this means safe, this means no allocation or file access or any locking.
no allocation or file access or any locking.
And last we pass the extra parameters for our stream. Here we only have the And last we pass the extra parameters for our stream. Here we only have the
allowed formats (`SPA_PARAM_EnumFormat`). allowed formats (`SPA_PARAM_EnumFormat`).
@ -140,11 +138,11 @@ Running the mainloop will then start processing and will result in our
The main program flow of the process function is: The main program flow of the process function is:
* `pw_stream_dequeue_buffer()` to obtain a buffer to write into. - `pw_stream_dequeue_buffer()` to obtain a buffer to write into.
* Get pointers in buffer memory to write to - Get pointers in buffer memory to write to.
* write data into buffer - Write data into buffer.
* adjust buffer with number of written bytes, offset, stride, - Adjust buffer with number of written bytes, offset, stride.
* `pw_stream_queue_buffer()` to queue the buffer for playback. - `pw_stream_queue_buffer()` to queue the buffer for playback.
\snippet tutorial4.c on_process \snippet tutorial4.c on_process

View file

@ -1,4 +1,4 @@
/** \page page_tutorial5 Tutorial - Part 5: Capturing video frames /** \page page_tutorial5 Tutorial - Part 5: Capturing Video Frames
\ref page_tutorial4 | \ref page_tutorial "Index" | \ref page_tutorial6 \ref page_tutorial4 | \ref page_tutorial "Index" | \ref page_tutorial6
@ -141,7 +141,6 @@ stream mmap the data for us.
And last we pass the extra parameters for our stream. Here we only have the And last we pass the extra parameters for our stream. Here we only have the
allowed formats (`SPA_PARAM_EnumFormat`). allowed formats (`SPA_PARAM_EnumFormat`).
Running the mainloop will start the connection and negotiation process. Running the mainloop will start the connection and negotiation process.
First our `param_changed` event will be called with the format that was First our `param_changed` event will be called with the format that was
negotiated between our stream and the camera. This is always something that negotiated between our stream and the camera. This is always something that
@ -160,7 +159,7 @@ static void on_param_changed(void *userdata, uint32_t id, const struct spa_pod *
return; return;
\endcode \endcode
First check if there is a param. A NULL param means that it is cleared. The id First check if there is a param. A NULL param means that it is cleared. The ID
of the param tells you what param it is. We are only interested in Format of the param tells you what param it is. We are only interested in Format
param (`SPA_PARAM_Format`). param (`SPA_PARAM_Format`).

View file

@ -1,4 +1,4 @@
/** \page page_tutorial6 Tutorial - Part 6: Binding objects /** \page page_tutorial6 Tutorial - Part 6: Binding Objects
\ref page_tutorial5 | \ref page_tutorial "Index" \ref page_tutorial5 | \ref page_tutorial "Index"