Commit graph

7512 commits

Author SHA1 Message Date
Wim Taymans
60062432b8 module-rtp: handle the send_packet/feedback as callbacks
They are emited from the streaming thread and therefore can be emitted
concurrently with the events on the main thread. This can cause crashes
when the hook list is iterated.

Instead, make those events into callbacks that are more efficient,
and threadsafe.
2026-03-26 09:34:45 +01:00
Wim Taymans
50fcf64058 tools: add -C | --monitor to pw-cat
It sets the stream.capture.sink property which makes a record stream
capture from a sink monitor instead.
2026-03-25 18:06:17 +01:00
Wim Taymans
9eeb2f1930 mixer: handle control.ump property
Add a control.ump port property. When true, the port wants UMP and the
mixer will convert to it. When false, the port supports both UMP and
Midi1 and no conversions will happen. When unset, the mixer will always
convert UMP to midi1.

Remove the CONTROL_types property from the filter. This causes problems
because this is the format negotiated with peers, which might not
support the types but can still be linked because the mixer will
convert.

The control.ump port property is supposed to be a temporary fix until we
can negotiate the mixer ports properly with the CONTROL_types.

Remove UMP handling from bluetooth midi, just use the raw Midi1 events
now that the mixer will give those and we are supposed to output our
unconverted format.

Fix midi events in-place in netjack because we can.

Update docs and pw-mididump to note that we are back to midi1 as the
default format.

With this, most of the midi<->UMP conversion should be gone again and we
should be able to avoid conversion problems in ALSA and PipeWire.

Fixes #5183
2026-03-25 11:59:43 +01:00
Wim Taymans
7fe191bc10 buffers: handle 0 result from Buffers param enumeration
Since abf37dbdde the param enumeration in
the client-node can return 0 when the parameter is supported but there
are no params uploaded.

When negotiating buffers we need to assume a 0 result as a NULL filter
as well or else we will error.
2026-03-25 11:59:43 +01:00
Wim Taymans
ea28343166 midi: don't convert Midi in nodes
Avoid doing conversions in the nodes between Midi formats, just assume
the imput is what we expect and output what we naturally produce.

For ALSA this means we produce and consume Midi1 or Midi2 depending on the
configurtation.

All of the other modules (ffado, RTP, netjack and VBAN) really only
produce and consume MIDI1.

Set the default MIDI format to MIDI1 in ALSA.

Whith this change, almost everything now produces and consumes MIDI1
again (previously the buffer format was forced to MIDI2).

The problem is that MIDI2 to and from MIDI1 conversion has problems in
some cases in PipeWire and ALSA and breaks compatibility with some
hardware.

The idea is to let elements produce their prefered format and that the
control mixer also negotiates and converts to the node prefered format.
There is then a mix of MIDI2 and MIDI1 on ports but with the control
port adapting, this should not be a problem.

There is one remaining problem to make this work, the port format is
taken from the node port and not the mixer port, which would then expose
the prefered format on the port and force negotiation to it with the
peer instead of in the mixer.

See #5183
2026-03-25 11:59:43 +01:00
Wim Taymans
d47b4974ce impl-node: add () around &&
To fix a compiler warning.
2026-03-23 11:55:05 +01:00
Martin Geier
52b23384e0 impl-node: correctly synchronize suspend state with remote node
Previously, if a remote node was set to running and immediately reverted
to suspended state, the remote node stayed in running state. This occurred
because suspend_node sent suspend command only when the locally cached
state was "idle" or "running."

Modified to send suspend to a node whenever its pending state is not
"suspended," ensuring the command is sent during state transitions.

Fixes #5026

Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
2026-03-23 11:41:09 +01:00
Wim Taymans
b16a2e41e8 scheduler: remove sync group from runnable calculations
The sync group is only to group nodes when sync is enabled.
2026-03-18 13:19:04 +01:00
Wim Taymans
6bf81ebe59 modules: align rtp_timestamps for sender
When the driver changes, the clock position can also change and there
would be a discont in the rtp_timestamp.

This is not usually a problem except in RAOP mode where the base rtp
timestamp is negotiated and anything that deviates too much is to be
discarded.

If we are not using direct_timestamp for the sender, make sure we always
keep the rtp_time aligned to avoid this problem.

See #5167
2026-03-17 14:05:09 +01:00
Wim Taymans
f4587ea434 modules: improve debug in RTP 2026-03-17 14:05:09 +01:00
Wim Taymans
8db1153519 modules: remove some unused fields 2026-03-17 14:05:09 +01:00
Robert Rosengren
e5809ee052 pipewiresrc: fix wait_negotiated from change_state
Going from PLAYING to PAUSED will have basesrc calling unlock and
setting flushing to false. Going back to PLAYING may then fail in
wait_negotiated, as unlock_stop will be called after change_state.

Fix by remove the flushing check, since already in that "state".
2026-03-16 17:08:44 +00:00
Wim Taymans
b1b5653393 sendspin: negotiate the first raw format
Flac and Opus are not supported yet.
2026-03-13 12:03:11 +01:00
Wim Taymans
95eac7b4e5 scheduler: add comment about the FOLLOW_SUSPEND special case 2026-03-12 18:12:42 +01:00
Wim Taymans
e4e5f62d44 impl-node: accept more node.passive values
So that we can set separate values for in and out ports.

The node.passive=follow mode is a good idea for a filter.
2026-03-12 17:25:36 +01:00
Wim Taymans
3e209f6d20 modules: try to improve code readability some more 2026-03-12 14:57:23 +01:00
Wim Taymans
41520f1022 modules: remove a warning 2026-03-12 14:44:34 +01:00
Wim Taymans
ca91b368c1 impl-port: make a follow-suspend port mode
It's like the follow mode but when you link 2 follow-suspend ports
together, they will activate eachother.

This is to make Source -> Sink links work.
2026-03-12 14:40:04 +01:00
Wim Taymans
45e3af5cdc impl-port: make passive mode as an enum
Hopefully easier to understand.
2026-03-12 13:46:49 +01:00
Wim Taymans
ad195b289a modules: try to document the passive ports better 2026-03-12 12:13:43 +01:00
Siva Mahadevan
9495e2b8a9 pipewire/thread.c: only handle reset_on_fork if SCHED_RESET_ON_FORK is defined
This fixes a missing definition error in thread.c:

../src/pipewire/thread.c:129:30: error: use of undeclared identifier 'SCHED_RESET_ON_FORK'
  129 |         SPA_FLAG_UPDATE(new_policy, SCHED_RESET_ON_FORK, reset_on_fork);
2026-03-12 09:18:41 +00:00
Siva Mahadevan
283052c15a examples: fix includes for makedev() macro
On non-linux, the makedev() macro comes from <sys/types.h>.
2026-03-11 21:49:48 +00:00
Siva Mahadevan
d17e68c43f network-utils: add missing #include <netinet/in.h>
As stated in https://pubs.opengroup.org/onlinepubs/9799919799//basedefs/netinet_in.h.html,

> The <netinet/in.h> header shall define the sockaddr_in structure [...]

This fixes the following build error:

In file included from ../src/modules/module-protocol-native.c:44:
../src/modules/network-utils.h:96:35: error: incomplete definition of type 'struct sockaddr_in'
   96 |                 if (inet_ntop(sa->ss_family, &in->sin_addr, ip, len) == NULL)
      |                                               ~~^
2026-03-11 17:20:12 -04:00
Siva Mahadevan
469929d4f6 pipewire: guard linux-specific RLIMIT_* inside #ifdef __linux__ 2026-03-11 14:20:48 -04:00
Wim Taymans
9c7aa4d423 impl-port: don't send NULL tag to clear
NULL tags are never handled and so tags just keeps configured on the
ports. It's also hard to know the direction from the NULL data.

Instead, send an empty Tag with the direction to clear everything.
2026-03-11 18:18:49 +01:00
Wim Taymans
2f65cf7124 modules: return the error of getsockopt instead of -EPIPE 2026-03-11 18:18:49 +01:00
Wim Taymans
00f1d6c3d8 modules: improve debug in profiler
Also log the node that we are inspecting.
2026-03-11 12:42:06 +01:00
Wim Taymans
7ecd51dc80 client-node: avoid using invalid fd or mem in clear_data
Don't close an -1 fd in clear_data.

If we let the client allocate buffer, set our fd and data to invalid
values. If the client decides to renegotiate before we get the buffer
data we might otherwise try to clear the mem_id (default 0) or
close the fd (also default 0).

Fixes #5162
2026-03-10 14:25:07 +01:00
Wim Taymans
6a3ac7f7b0 examples: support REQUEST like video-src 2026-03-10 12:30:03 +01:00
Barnabás Pőcze
5c67ab2a7a pipewire: mem: log if close() fails
If a file descriptor is expected to be closed by the associated `pw_memblock`,
and closing fails, then that usually signals a more serious issue in the memory
accounting. So add a log message when that happens.
2026-03-10 12:27:44 +01:00
Barnabás Pőcze
d33066cdd7 pipewire: module-client-node: use pw_log_*()
Use the `pw_log_*()` macros instead of the `spa_log_*()` ones since
this is a pipewire module, and otherwise not the expected log topic
would be used.
2026-03-10 12:09:36 +01:00
Barnabás Pőcze
abf37dbdde pipewire: module-client-node: use pw_param_info_find() to check validity
Previously when parameters were enumarated, it was checked if at least one
param was known for `id`. If not, `-ENOENT` was returned to signal that
this param id is not supported.

This is not necessarily true, since a param id might be supported, but it
might have zero params at the moment, in which case an unexpected error
would be returned.

Fix that by using `pw_param_info_find()` with the underlying impl object
to check if the param id is actually supported.
2026-03-09 21:34:19 +01:00
Barnabás Pőcze
5e37d43881 pipewire: impl-{node,port}: do not cache failed param enumerations
If the param enumeration fails, do not set `spa_param_info::user` to 1
indicating that the result is cached. Doing so can lead to the first
(uncached) call failing, while the rest will succeed (with 0 params).
2026-03-09 20:04:22 +00:00
Jonas Ådahl
c745582ef5 pipewire/capabilities: Remove left-over macro defiition
This was used for a previous iteration, that used tags, and was replaced
with PW_CAPABILITY_DEVICE_ID_NEGOTIATION.
2026-03-09 15:54:08 +00:00
Jonas Ådahl
f7bb4c95ed pipewire/capabilities: Update device ID negotation according to API docs
It was was documenting a previous iteration of the protocol which used a
boolean and a base64 encoded list.
2026-03-09 15:54:08 +00:00
Wim Taymans
231a41a22f impl-link: fix shared mem test
We can only use non-shared memory when both nodes live in the same
process _and_ we can be sure the output port is never going to be linked
to a remote node because it is exclusive.

This fixes the case where a null-sink is loaded inside the process space
of the server and linked to the ALSA sink. This would create a link
without shared mem and then as soon as something else (out of process)
wants to link to the null-sink output, it would get a -22 EINVAL
negotiation error because the memory can't be shared.

Fixes #5159
2026-03-09 16:18:58 +01:00
Wim Taymans
48c22e2aa7 pw-dump: place key before None choice values
See #5161
2026-03-09 13:19:43 +01:00
Wim Taymans
70b7b42f5d pw-cat: fix encoded format playback
We keep a mapping between the sndfile formats and the format we would
like to decode them to for encoded formats. Make sure we don't mix up
the sample widths between them.

Make sure we don't send encoded formats as raw.

Debug the uncompressed format name correctly.

Fixes #5155
2026-03-06 17:03:20 +01:00
Wim Taymans
a179e8c695 sendspin: implement parsing of client state 2026-03-06 11:24:21 +01:00
Wim Taymans
784ad934a4 impl-node: remove the can_suspend boolean
Sink and Sources can now be implemented as the follow passive mode,
they won't activate anything themselves but follow the state of the
peer.
2026-03-06 10:42:00 +01:00
Wim Taymans
118d8574c8 impl-port: support mode port.passive values
Add a port.passive = follow mode and the node.passive equivalents
out-follow, in-follow, follow.

This makes it possible to control how a port influences the state of
the peer and how the peer influences the state of the node independently.

In passive mode, the port will not make the peer runnable and will also
not become runnable when the peer activates.

In the follow mode, the port will not make the peer runnable but it will
become runnable when the peer is active.

This makes it possible to do new things like (f for follow):

  Source -> (f)loopback1-in|loopback1-out(f) -> Sink

It will not make the source and sink run but when one of them start, all
will become runnable.

Or you can now better do the leak node hack that was previously used:

  Source -> (f)pw-record

That will only start running when the source is activated by something
else.

With port.passive = true|false|follow there is a potential 4th case
which would activate the peer but not be activated by the peer, which is
not something that makes sense.
2026-03-06 09:35:17 +01:00
Wim Taymans
437a8d32f2 impl-node: remove the leaf node check
This was a hack around some scheduler issues that we should be able to
handle better now.

One of the cases is:

  Source -> (p)pw-record

Which would never work otherwise because pw-record does not activate the
Source and when the Source is activated in any other way, pw-record
would not follow.

This will still fail with the current scheduler, but the leaf check is
not so great because it doesn't work in this case:

  Source -> (p)loopback-in|loopback-out(p) -> Sink

What is probably required is a passive mode that doesn't activate but
does follows the peer.
2026-03-05 15:03:30 +01:00
Wim Taymans
106b4a37d4 node: remove node.link-group from drivers
Sink/Source pairs should not have the same link-group otherwise the
session manager will not be able to autoconnect them with a loopback or
some other internally linked stream.
2026-03-05 14:32:41 +01:00
Wim Taymans
e6a5951a47 gst: fix compilation on older GStreamer
These functions are since 1.28, which is a little too new.
2026-03-04 17:55:53 +01:00
Robert Mader
efd1526423 pipewiresrc: Use clock time difference to update last_buffer time
Setting the current clock time when resending buffers is often wrong.
Especially for pseudo-live sources - the default mode - it discards
the original buffer time, which again is used by the base-class to
adjust the timestamps further, ultimately resulting in very wrong
timestamps.

Instead, try to calculate the delta between when we originally got the
buffer and now.
2026-03-03 22:52:52 +01:00
Robert Mader
49300d8ee0 pipewiresrc: Take a copy instead of a reference for last_buffer
Buffer timestamps get adjusted by the base class, GstBaseSrc, even if we
take an additional ref. Arguably the base class should check if buffers
are writable (gst_buffer_make_writable()), which would trigger a buffer
copy. That is currently not the case, though, thus do so on our side.

Notes:
1. Usually a buffer copy doesn't copy the underlying memory, i.e.
copying is cheap.
2. The copy holds a reference to the copied buffer, preventing the
buffer from getting recycled as before.
2026-03-03 22:51:04 +01:00
Wim Taymans
a3853c2c3d scheduler: activate links also in make_runnable
Also make sure we unset the preparing flag when the port state
changes.
2026-03-03 11:56:35 +01:00
Elliot Chen
95e89f786a pipewiresrc: update per-plane stride and offset according to chunk info 2026-03-03 09:16:51 +00:00
Wim Taymans
ea21281f38 scheduler: skip checking runnable from suspendable nodes
We used to skip the runnable state from driver nodes because we assume
that they will be activated from other nodes. We however need to make
this more general to all suspendable nodes.

This makes pw-play -> loopback1-sink loopback1-out -> loopback2-sink
loopback-out -> sink also work correctly because the loopback2-sink does
not activate loopback1-out then.
2026-03-02 17:22:05 +01:00
Wim Taymans
797cdbc72f impl-link: link.passive is no longer used 2026-03-02 17:19:41 +01:00