Make it possible to pass context to plugins and nodes in the
filter-chain.
We can use this to make filters aware of the graph clock or
latency, for example.
Escape <portname>, <tensorname>, <paramname>, <port>, <rules> and
similar angle-bracket placeholders that doxygen interprets as HTML
tags. Also escape @filename (unknown doxygen command) and fix the
pw_stream::process() reference in thread-loop.h.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- modules.dox: remove references to non-existent sendspin modules
- access.dox: remove reference to deprecated pipewire-media-session
- dma-buf.dox: fix \ref EnumFormat to \ref SPA_PARAM_EnumFormat,
fix \ref struct to struct \ref for spa_meta_sync_timeline
- pipewire.conf.5.md: add explicit {#synopsis} anchor for internal links
- pipewire-client.conf.5.md: fix audio_converter to audio_adapter ref
- pipewire-jack.conf.5.md: escape <id> HTML tags
- pipewire-props.7.md: fix monitor-prop__ to props__ for card profiles ref
- pipewire-pulse.1.md: fix pipewire-env ref to full anchor name
- pipewire.1.md: fix \ref CPU to \ref spa_cpu
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prefix all pulse module source files with pulse- to give them unique
basenames, avoiding ambiguous \file suffix matching in doxygen when
identically-named files exist under src/modules/.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When inspecting the loaded modules, actually list the properties that
were used when loading the module instead of the informational generic
ones from the info.
Pulsaudio also does not list the Usage properties when listing modules.
Add some more fields like the type, default value and possible enum
values for the module_args.
Use this to generate the Usage in describe-module and the docs.
This should give more consistent and correct Usage output in all
modules.
This makes it possible to dynamically add / remove receivers, which is
necesary for sending to multiple receivers. Mixed multi- and unicast
receivers are possible. Example pw-cli calls (56 is the ID of the RTP
sink node):
pw-cli c 56 User '{ extra="{ \"command.id\" : \"add-receiver\" , \"destination.ip\" : \"10.42.0.1\", \"destination.port\" : 55001 }" }'
pw-cli c 56 User '{ extra="{ \"command.id\" : \"remove-receiver\", \"destination.ip\" : \"10.42.0.1\" }" }'
pw-cli c 56 User '{ extra="{ \"command.id\" : \"clear-receivers\" }" }'
Commands and their arguments:
* "add-receiver" : Adds a receiver to the sink's list. If the given
IP address <-> port combination was already added, the command is
logged, but otherwise ignored. Arguments:
- "destination.ip" : IP address to send data to. Can be a uni- or
multicast address, but must be a valid address.
- "destination.port" : Port to send data to. Must be valid.
- "local.ifname", "source.ip", "net.ttl", "net.dscp", "net.loop" :
These are all optional, and work just like in the RTP sink
module's properties.
* "remove-receiver" : Removes a receiver from the sink's list. The
receiver is identified by the given IP address. A port can optionally
be specified as well. If it isn't, then the first receiver with that IP
address is removed. If no matching receiver is in the sink's list,
this command does nothing. Arguments:
- "destination.ip" : IP address to send data to. Can be a uni- or
multicast address, but must be a valid address.
- "destination.port" : Port to send data to. This is optional. But, if
it is set, it must be a valid port number.
* "clear-receivers" : Removes all receivers from the sink's list. If the
list is empty, this does nothing. This command has no arguments.
If the RTP sink module is created with the "destination.ip" and
"destination.port" properties set, it behaves as if "add-receiver" were
called right after the module was initialized. This means that if none
of these commands are used, the module behaves just as it did prior to
this patch. Note that the "remove-receivers" command can remove this
initial receiver as well.
If no receivers are added, the module continues to work normally.
Adding and removing receivers mid-operation is supported.
NOTE: "destination.ip") handling in stream_props_changed() is removed,
since it never really did anything other than change the param value.
rtp_stream_new() acquires a data loop with pw_context_acquire_loop() but
the out: error path never calls pw_context_release_loop(), leaking the loop
reference on every failure after acquisition.
Mirror rtp_stream_destroy() and other modules that pair acquire with release.
Add a new pulse.zeroramp.gap property that will enable gap detection and
fade-in/fade-out on gaps on playback streams.
Make a rule to enable this on chrome, which does not do a cork/pause
when a stream is paused but sends out silence. With the gap detection
enabled, this allows the audioconvert to perform fades to avoid pops and
clocks from sudden DC changes at the gaps.
Fixes#4745
Each port mix embedded its buffer table in struct mix as a fixed array
buffers[MAX_BUFFERS] (MAX_BUFFERS == 64), and every struct buffer in turn
embedded datas[MAX_DATAS] (MAX_DATAS == 256) and metas[MAX_METAS]. This
reserved ~674 KB per mix in create_mix() regardless of the actual buffer,
data and meta counts, multiplied by every port mix (one per link end).
Turn buffers, datas and metas into pointers and allocate the buffer table
together with the per-buffer data and meta pools in a single calloc in
do_port_use_buffers(), sized to the real number of buffers and their
n_datas/n_metas, and release it in clear_buffers(). create_mix() now starts
with an empty (NULL) table, so an idle mix costs only the struct header.
This mirrors the dynamic-allocation approach already used for the
audioconvert and audiomixer port buffers and removes the dominant heap and
mmap consumer in the client-node graph.
Co-authored-by: Copilot <copilot@github.com>
In the past, it made no difference whether or not an RTP sink's
sess.ts-direct property was set to true. This changed in commit
6bf81ebe59 . Now, sess.ts-direct must be
set to true if an associated RTP source is using direct timestamp mode.
That's because when the RTP sink's direct timestamp mode is not enabled,
it will set the new internal ts_align offset to a nonzero value, which
then corrupts timestamps and causes out of sync playback in the RTP
sources.
Also, copy the sess.ts-direct property from the global RTP sink props
to the stream props to match the behavior of the RTP source module.
* Rename do_disconnect to do_disconnect_core, since the original name
is ambiguous (it can be interpreted as being about disconnecting
a network socket).
* impl->session_name is not used at all, so remove it.
This fixes code duplication, since the checks are the same regardless
of payload type. hlen is also calculated the same across payload types,
so it is moved as well. The impl->receive_rtp() function pointer then
solely addresses the actual payload processing.
Rename format_info to rtp_format_info to make the purpose of that struct
and the associated variable clearer.
Document what info and stream_info are there for, since their purpose
is not immediately obvious.
Using find_audio_format_info() for Opus and MIDI makes no sense, since
both of these only have one info each, which is always found, so one might
as well just use that single, always-matching RTP format info directly.
This means that the audio_format_info array remains there solely for PCM,
so rename it to rtp_pcm_audio_format_info.
update_delay is called primarily when the stream format or latency changes,
and from playback thread, if stream reports different delay as before.
This function calculates the number of compensate samples for each stream
based on the latencies of other streams (which must be in a streaming state).
During the first playback on a new format, update_delay is called multiple times
due to format or latency changes. The delay is calculated only from streams
that are currently streaming. If some streams are not yet streaming, their
latencies are ignored, and the delay is updated later in the processing
thread. The processing thread also stores the stream delay in a local variable
(accessed only from that thread, thus requiring no locking).
On a subsequent playback using the same format, update_delay is still called a
few times, and the delay is updated based on the currently streaming streams.
If some streams are not streaming, their latencies are ignored.
However, this time, the processing thread fails to update the delay for the
previously non-streaming streams. Because the format didn't change, the streams
delay matches the last stored delay from the previous playback. As a
result, the compensate samples are not recalculated.
To properly update the compensate samples, update_delay must also be called
when a stream's state changes to streaming (avoiding the need to clear the
thread-buffered value, which would require locking in the processing
thread).
In multiple cases the `flags` member of `spa_dict` is left unitialized,
so try to avoid that. For example in `fill_node_info_proplist()` it is
accessed in `spa_dict_lookup_item()`.
This also modifies `collect_props()` to not depend on a partially initialized
`dict` parameter.
Commit b1b565339 ("sendspin: negotiate the first raw format") says that
FLAC and Opus are not supported yet. The receiver also only advertises
PCM formats in its player support.
Reject non-PCM stream/start codecs in the receiver. Otherwise
parse_player() accepts FLAC or Opus without setting client->stride,
while the receive path later uses client->stride as a raw frame size.
Signed-off-by: Wang Yu <wangyu@uniontech.com>