| 
									
										
										
										
											2021-05-07 09:09:45 +10:00
										 |  |  | # PipeWire Architecture
 | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | There are 2 main components that make up the PipeWire library: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-07 09:09:45 +10:00
										 |  |  | 1. An implementation of a graph based media processing engine. | 
					
						
							|  |  |  | 2. An asynchronous IPC mechanism to manipulate and introspect | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  |     a graph in another process. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 13:49:33 +02:00
										 |  |  | There is usually a daemon that implements the global graph and | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | clients that operate on this graph. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The IPC mechanism in PipeWire is inspired by wayland in that it | 
					
						
							|  |  |  | follows the same design principles of objects and methods/events | 
					
						
							|  |  |  | along with how this API is presented to the user. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PipeWire has a plugin architecture that allows new features to | 
					
						
							|  |  |  | be added (or removed) by the user. Plugins can hook into many | 
					
						
							|  |  |  | aspects of PipeWire and change the behaviour or number of | 
					
						
							|  |  |  | features dynamically. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Principles
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 09:15:21 +00:00
										 |  |  | The PipeWire API is an object oriented asynchronous protocol. | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | All requests and replies are method invocations on some object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Objects are identified with a unique ID. Each object implements an | 
					
						
							| 
									
										
										
										
											2020-07-22 20:54:06 +02:00
										 |  |  | interface and requests result in invocations of methods on the | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | interface. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The protocol is message based. A message sent by a client to the | 
					
						
							|  |  |  | server is called a method. A message from the server to the client | 
					
						
							|  |  |  | is called an event. Unlike Wayland, these messages are not (yet) | 
					
						
							|  |  |  | described in an external protocol file but implemented directly in | 
					
						
							|  |  |  | a protocol plugin. Protocol plugins can be added to add new | 
					
						
							|  |  |  | objects or even protocols when required. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-11 11:33:29 +00:00
										 |  |  | Messages are encoded with [SPA PODs](spa/pod.md), which make it | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | possible to encode complex objects with right types. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-22 20:54:06 +02:00
										 |  |  | Events from the server can be a reply to a method or can be emitted | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | when the server state changes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Upon connecting to a server, it will broadcast its state. Clients | 
					
						
							|  |  |  | should listen for these state changes and cache them. There is no | 
					
						
							|  |  |  | need (or mechanism) to query the state of the server. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 20:00:59 +02:00
										 |  |  | The server also has a registry object that, when listening to, | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | will broadcast the presence of global objects and any changes in | 
					
						
							|  |  |  | their state. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | State about objects can be obtained by binding to them and listening | 
					
						
							|  |  |  | for state changes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Versioning
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | All interfaces have a version number. The maximum supported version | 
					
						
							|  |  |  | number of an interface is advertized in the registry global event. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A client asks for a specific version of an interface when it binds | 
					
						
							|  |  |  | to them. It is the task of the server to adapt to the version of the | 
					
						
							|  |  |  | client. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Interfaces increase their version number when new methods or events | 
					
						
							|  |  |  | are added. Methods or events should never be removed or changed for | 
					
						
							|  |  |  | simplicity. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Proxies and resources
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 09:15:21 +00:00
										 |  |  | When a client connects to a PipeWire daemon, a new `struct pw_proxy` | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | object is created with ID 0. The `struct pw_core` interface is | 
					
						
							|  |  |  | assigned to the proxy. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | On the server side there is an equivalent `struct pw_resource` with | 
					
						
							|  |  |  | ID 0. Whenever the client sends a message on the proxy (by calling | 
					
						
							|  |  |  | a method on the interface of the proxy) it will transparently result | 
					
						
							|  |  |  | in a callback on the resource with the same ID. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Likewise if the server sends a message (an event) on a resource, it | 
					
						
							|  |  |  | will result in an event on the client proxy with the same ID. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PipeWire will notify a client when a resource ID (and thus also proxy | 
					
						
							|  |  |  | ID) becomes unused. The client is responsible for destroying the | 
					
						
							|  |  |  | proxy when it no longer wants to use it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Interfaces
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_loop`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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_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_context`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The main context for PipeWire resources. It keeps track of the mainloop, | 
					
						
							|  |  |  | loaded modules, the processing graph and proxies to remote PipeWire | 
					
						
							|  |  |  | instances. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | An application has to select an implementation of a `struct pw_loop` | 
					
						
							|  |  |  | when creating a context. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The context has methods to create the various objects you can use to | 
					
						
							|  |  |  | build a server or client application. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_core`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A proxy to a remote PipeWire instance. This is used to send messages | 
					
						
							|  |  |  | to a remote PipeWire daemon and to receive events from it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A core proxy can be used to receive errors from the remote daemon | 
					
						
							|  |  |  | or to perform a roundtrip message to flush out pending requests. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Other core methods and events are used internally for the object | 
					
						
							| 
									
										
										
										
											2020-08-02 20:13:29 +02:00
										 |  |  | life cycle management. | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_registry`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2020-09-14 20:00:59 +02:00
										 |  |  | objects in order to call methods or receive events from them. | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_module`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A proxy to a loadable module. Modules implement functionality such | 
					
						
							|  |  |  | as provide new objects or policy. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_factory`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A proxy to an object that can create other objects. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_device`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A proxy to a device object. Device objects model a physical hardware | 
					
						
							|  |  |  | or software device in the system and can create other objects | 
					
						
							|  |  |  | such as nodes or other devices. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_node`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_port`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A Proxy to an input or output port of a node.  They can be linked | 
					
						
							|  |  |  | together to form a processing graph. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_link`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | ports and PipeWire will manage mixing and duplicating the buffers. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## High level helper objects
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Some high level objects are implemented to make it easier to interface | 
					
						
							|  |  |  | with a PipeWire graph. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_filter`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ### `struct pw_stream`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | sizes. It is comparable to Core Audio AudioQueue or a PulseAudio | 
					
						
							|  |  |  | stream. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Security
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | With the default native protocol, clients connect to PipeWire using | 
					
						
							|  |  |  | a named socket. This results in a client socket that is used to | 
					
						
							|  |  |  | send messages. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For sandboxed clients, it is possible to get the client socket via | 
					
						
							|  |  |  | other ways, like using the portal. In that case, a portal will | 
					
						
							|  |  |  | do the connection for the client and then hands the connection socket | 
					
						
							|  |  |  | to the client. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | All objects in PipeWire have per client permission bits, currently | 
					
						
							| 
									
										
										
										
											2020-09-14 20:00:59 +02:00
										 |  |  | READ, WRITE, EXECUTE and METADATA. A client can not see an object | 
					
						
							| 
									
										
										
										
											2020-08-02 20:13:29 +02:00
										 |  |  | unless it has READ permissions. Similarly, a client can only execute | 
					
						
							|  |  |  | methods on an object when the EXECUTE bit is set and to modify the | 
					
						
							|  |  |  | state of an object, the client needs WRITE permissions. | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | A client (the portal after it makes a connection) can drop permissions | 
					
						
							|  |  |  | on an object. Once dropped, it can never reacquire the permission. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Clients with WRITE/EXECUTE permissions on another client can | 
					
						
							|  |  |  | add and remove permissions for the client at will. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-02 20:13:29 +02:00
										 |  |  | Clients with MODIFY permissions on another object can set or remove | 
					
						
							|  |  |  | metadata on that object. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | Clients that need permissions assigned to them can be started in | 
					
						
							| 
									
										
										
										
											2021-04-28 20:29:44 +02:00
										 |  |  | blocked mode and resume when permissions are assigned to them by | 
					
						
							| 
									
										
										
										
											2020-06-11 13:29:30 +02:00
										 |  |  | a session manager or portal, for example. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PipeWire uses memfd (`memfd_create(2)`) or DMA-BUF for sharing media | 
					
						
							|  |  |  | and data between clients. Clients can thus not look at other clients | 
					
						
							|  |  |  | data unless they can see the objects and connect to them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Implementation
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PipeWire also exposes an API to implement the server side objects in | 
					
						
							|  |  |  | a graph. |