Use a global lock to serialize concurrent pw_init calls.
Use a global lock to protect the global registry. With the alsa api,
multiple threads could open the device and create streams and
load/unload plugins.
See !942
The previous code had alsa optional if pipewire-alsa was on
auto/disabled bug failed later with missing alsa if media-session was in
the session manager array. Which it is by default.
Fixes#1632
If the device doesn't have an active Route, also check the EnumRoute to
see if there is something available. If nothing is available, also avoid
selecting this node.
Fixes#1624
For default nodes, that are explicitly configured, skip the route check.
This makes it possible for the user to select a non-available node
as the default still.
Fixes#1624
When we need to remove all items, copy the storage to a temporary
array and clear the storage.
When one of the callbacks would add a new item to the storage it would
operate on the new empty storage and the loop to iteratively clear
subjects would be able to complete.
Fixes#1622
It seems not uncommon that people have not properly configured ofono
running, which results to loss of HFP/HSP functionality. It's less
surprising if the backend selection is fixed in the configuration file,
and (by default) does not depend on running services.
Add a configuration file option for selecting HFP/HSP backend, and set
the default value to the native backend. Emit warnings if conflicting
backend services are detected to be running.
Also cleanup hfp/hsp backend handling a bit, now that it's mostly
abstracted behind an interface.
It's not really the responsibility of the session manager to load the
bluez5 device quirks, and it's easier for eg. Wireplumber if it doesn't
need to do it.
Move loading bluez-hardware.conf to be the responsibility of the bluez5
spa plugin, similarly as the alsa plugin deals with the ACP database.
Put the configuration to share/spa-0.2/bluez5, mirroring the plugin
directory structure in lib/spa-0.2/bluez5.
When the memory is removed, clear the node io areas so that it doesn't
accidentally get reused.
Fixes a crash in cheese when the node is stopped and then resumed.
This makes it easier to figure out if a particular module was missing
from the build. Example output:
Optional Modules
rt : YES
rtkit : YES
portal : YES
pulse-tunnel : YES
zeroconf-discover : YES
roc-sink : NO
roc-source : NO
When the node support transport sync. That is, when it will clear the
pending_sync flag from its activation area when it completed a new
seek.
Before this patch, the pending sync was always automatically cleared,
which broke some applications that are time masters such as bitwig.
Fixes#1589
Use the core.info clock rate as the default sample rate as soon as the
manager exposes the core object. Otherwise the default sample rate is 0
until someone calls GET_SERVER_INFO, which as a side effect sets the
default sample rate.
Fixes issues with sinks not appearing right away.
Fixes#1588
Allow one of "XEWIDT" to refer to none, errors, warnings, info, debug
and trace, respectively because they're immediately recognizable. Well,
except maybe the X.
PIPEWIRE_DEBUG="I" is equivalent to PIPEWIRE_DEBUG="3" for example.
When none of the nodes have a valid passthrough format, don't check if
passthrough is possible.
Without the check, it is possible that a node has a common format with
the peer that is not a passthrough format, like a raw audio format.
Fixes#1587
Some applications might expect the process function to run concurrently
with the callbacks. PipeWire tries to avoid this by using a lock for the
duration of the process callback. Make an option to disable this.
See #1576
When the node is suspended, don't take into account the lock-quantum
settings or else the graph would not want to change to the requested
quantum of the node.
Say we have a jack node with node.lock-quantum = true and
node.latency=256/48000. When it joins the graph and is suspended, the
lock-quantum is ignored and the node.latency is set on the graph.
After that, the lock-quantum ensures the graph quantum doesn't change
anymore until the node is suspended.
When we move a node from one driver to another, move the quantum and
rate if the target driver was idle so that we can mostly continue
uninterupted until a quantum/rate change is calculated.
When the driver is going to be idle or not running, avoid updating
the quantum.
This is mostly when a node is moved to another driver. Changing the
quantum of the old driver would have the clients briefly see the useless
quantum before being moved to the new driver.
default-session-manager is only used in the pw-uninstalled.sh developer
script. c25cec230c added the ability to
use the system-installed wireplumber but other than that this option is
largely superfluous.
Drop it and pick whichever the first entry to session-manager is. For
the vast use-case of either MS or WP this will just work fine and for
the niche case of building both SMs one just needs to make sure the
order is as desired.
And in the case of no session manager, the config line to start the SM
is now commented out.
The sources are used by the documentation, so rather than duplicating
the checks for whether to build it or not, just define it as
always-present empty array and fill it when needed.
Otherwise we get a meson error if media-session is disabled but
documentation is enabled.
Right now, meson -Dsession-managers=wireplumber will fail the build
because the default session manager option is set to media-session - and
if that isn't being built we error out.
Use an 'auto' value instead, selecting the first session-manager in the
list as the default one.
We have -Dsession-managers and -Ddefault-session-manager, the latter is
currently only used for pw-uninstalled.sh. Let's adjust the error
message to use "default" so it's a bit easier to understand by this may
fail with -Dsession-managers=wireplumber.
When multiple links are created at the same time for the same port, we
get into a race where multiple links will try to set a format
asynchronously and eventually break the links. Avoid this by marking the
port as busy for as long as an async format or buffer is pending and
avoid starting new link negotiation when one of the ports is busy.
This problem was observed when ardour6 tries to link all device capture
ports to its single monitor port.
For the stream group, we break into the three components we write out
and print those.
For the IPv6 address printing inside [], we can make this a condition on
the printf statement.
Change codec factory names to api.codec.bluez5.*, so that they won't
conflict with old config file lib name rules for api.bluez5.*
Specify the fallback library name when loading the codecs, so that it
works without the rules in config files.
Each dictionary needs to fully match but out of the dicts we have, only
one needs to match to apply. Reword that for clarity.
Also document regex vs normal string comparison vs the magic null
string.
Make easier to package A2DP codecs separately, by splitting each to a
separate SPA plugin. Adjust the code to not use a global variable for
the codec list.
The A2DP SPA interface API is in the bluez5 private headers, and not
exposed in installed SPA headers, as it's too close to the
implementation.
Instruct the policy to not configure audio adapter nodes in DSP mode. Instead,
Device nodes will always be configured in passthrough mode, and client nodes
will be configured in convert or passthrough mode depending on whether the
client format matches the device format or not.
The current _info_update() methods will always reset the change_mask in
the new info structure.
This causes problems if multiple updates are applied to the info before
the rescan in the session manager of pulse-server is excuted. The first
update is cleared and this causes the session manager to sometimes miss
the state changes of nodes and fail to suspend them.
Add a new method to merge with optional reset of the various
introspection info structures. We can use this instead and simply
accumulate all changes until the rescan code has processed all changes.
When we destroy a node that still has another driver, recalculate the
graph so that the driver has a chance to idle.
This can happen when we add an inactive node to the driver and then
destroy the node, like for jack clients.
Make sure we always suspend before reconfiguring a device.
Put the node and the device in passthrough mode when requested. Move
back to DSP mode after the node is unlinked.
Parse the exclusive flag of a stream once when the node info changes.
Use a new variable 'passthrough' to remember the current state of
a node and the peer.
Parse non-raw formats as well.
Check if two nodes can passthrough by intersecting the EnumFormat
params. If it is possible, configure the node for passthrough.
Don't try to reconnect nodes in passthrough.
Fail if we can't find a node compatible with passthrough.
See #629
Just like the latency, move the codecs to the device Route param.
This way, it is easier for the session manager to save and restore
the codecs as part of the Route settings.
If a program using pipewire-alsa calls snd_pcm_close() immediately after
snd_pcm_prepare() without reading or writing any data the client node
may be removed before the session manager can link it, which would
result in the following log warnings:
can't link 35:40 -> 43:48: link-factory: unknown input port 48
error id:25 seq:11467 res:-22 (Invalid argument): link-factory: unknown input port 48
can't link 35:41 -> 43:46: link-factory: unknown input port 46
error id:16 seq:11468 res:-22 (Invalid argument): link-factory: unknown input port 46
We start with setting the visitied flag on the driver. Still follow the
links to other visited nodes because it might make them active. for
example, adding a link between two midi ports should make the midi
driver running so that data flows between the ports.
See #1559
Actually set the right properties on the source and sink.
Not quite right because the pulseaudio ROC has a sink-input or a
playback stream in pipewire.
See #1538
Make the streams passive so that things can suspend.
Use a differend node.name for the input and output streams so that
autoconnect can actually remember the right target.
Make the media.name and description nicer.
See #1557
Audio with big frame sizes (especially audio with multiple channels) needs more
buffer size than the one calculated with the current formula. This patch uses
the frame size to calculate the buffer size, fixing playback issues for clients
configured in passthrough mode.
When the client adapter is configured in passthrough mode, the stream param
changed event in pipewire-pulse is emitted before the session manager creates
the link, and not after. Therfore, the peer can never be found when replying
create stream, and the pulseaudio application receives a stream error.
This patch delays the create stream reply until the link is added if the peer
cannot be found, fixing the above race conditon to allow passthrough mode to
work with pulseaudio applications.
When we inactivate the stream, clear the draining/drained state.
Otherwise, the stream stays in the drained state and won't call the
process function anymore when we activate it again.
This used to work before because we called the process function from the
Start command, which would queue a buffer and unset the drained flag.
Calling the process function from Start was however not right when the
process function needed to be called from the RT thread or when the
stream is a driver.
Fixes the issue where speaker-test would only play one channel.
Make the input buffer a little larger and leave the top blockSize
samples zero. That way we can fill up the lower part, leave the upper
part zero padded and feed this to the fft directly. Also only clear
the lower part when we can't fill it completely.
This removes some memcpy and memset operations.
Virtual devices tend to start with partial fields set in the EnumFormat
param (usually rate is missing). This causes virtual devices to be
invisible until they are used in some way.
Fix this by relaxing the parsing of EnumFormat and by falling back to
the server defaults for the unspecified fields.
Fixes#1413
When we send a Play request to the client but it deactivates before
sending the reply, make sure we send a Pause request as well so that
Play/Pause is always matched up.
Fixes#1548
When the allowed rates does not contain the default rate, also
fall back to only the default rate.
See the configured rates in the properties so it can be inspected.
Add option to set NULL data as the port data so that plugins can
skip processing.
Add 8 mixer ports and skip NULL data.
Move silence and discard samples to static area.
Improve the virtual sink examples. use the correct mixing for the HRIR
channels.
For hdmi and iec958 devices, enumerate the iec958 formats and
codecs. Initially only PCM is supported as a codec but with
a property or an init option, the list of codecs can be dynamically
configured.
We only need an info update to restore the stream so check for that
in addition to a param update.
The info update can be used to restore the stream and the param update
to update the stored value.
When switching back from the recording mode, save currently selected
profile as the default headset profile to use in future.
This allows users to select a specific profile they want to use for
input, and to avoid autoswitching to HFP/HSP if they want to use a
different microphone, without needing to edit configuration files.
aptX-LL sink devices may send back mSBC encoded data corresponding to
microphone input. It appears to be enabled when the bidirectional link
is set in the caps, and the device also supports this.
Implement mSBC decoding in the duplex channel.
Tested to be working on Avantree Aria Pro.
Support the low-latency variant of the aptx codec.
The magic mostly seems to be on the device side, since the stream is the
same as standard aptx, but latency is smaller even if stream/packet
sizes are the same.
Sound output latency is noticeably less than with the standard aptx.
Tested on Sennheiser HD 250 / Avantree Aria Pro.
The codec in principle also supports bidirectional duplex streams,
but that is not implemented here.
Enable SBC-XQ by default, and move it at the end of the codecs list, so
that bluez does not connect to it automatically except when it is the
codec used previously.
When the codec is disabled by quirks, it won't appear in the codecs
list, and so can't be selected by user (and so won't be connected
automatically).
However, since SelectConfiguration does not carry information which
device is in question, we cannot prevent BlueZ connecting to the codec
even if it's disabled for a specific device. If the "impossible" occurs
regardless, we won't reject the connection and the profile will be shown
as the generic "A2DP" one. If the sound is garbled, the user can select
some other profile that works.
If a log message is rate limited, we only need to know about it if we
are actually interested in that log level. We therefore add an argument
to the ratelimit_test function to set the log level of the message
printed if a message is skipped
Change-Id: I5ccd4a78bf7e972fe8b0e7133cd7e08c1e38835f
Set node.target metadata to "-1" instead of deleting it to direct nodes
to the default device.
Deleting the metadata, as done previously, does not work for nodes for
which the client has node.target set.
Handle all node.target behavior in rescan_node.
Make distinction between target nodes set in session manager via
metadata or via restore-stream; priorities are
metadata > client's node.target > restore-stream.
Allow metadata override to also remove the target node setting.
For nodes that have node.target set, when the target is not available,
media-session links them to any available node. If the target node
appears afterward, media-session would not re-link them, leading to
output being directed to wrong place (e.g. pavucontrol input monitor)
even though the intended target or a better fallback is available.
This occurs e.g. when devices are removed and re-added.
Fix this by (i) for reconnectable nodes, reconnect them if target
appears later, and (ii) for non-reconnectable nodes, raise error to the
client if node.target is set but not found (but proceed to fallback if
obj->target_node is set).
Also slightly reorganize policy-node.c:rescan_node for clarity.
Also set the driver on an inactive node when it wants a driver.
Fixes the case where xjadeo does not activate itself but still wants
to poll the transport state of the driver.
See #1491
When XDG_STATE_HOME is unset, we save in $HOME/.local/state/pipewire,
so try to first load the state file from there as well before we
try to fall back to the old XDG_CONFIG_HOME location.
Defaulting to $HOME/.local/state, this is the directory that state
information is to be kept.
As with the configuration loading, where a caller requests an absolute
path, that path will be honored, we only fall back to XDG_STATE_HOME for
relative paths.
This adds a new PIPEWIRE_STATE_DIR environment variable to override this
directory.
If a reconnecting node was linked at least once successfully, and a
re-link ends up not finding any node to link to, don't raise an error.
Instead, just unlink the node, and wait for a suitable sink to appear
later.
This fixes the issue that some Pulseaudio apps have to be restarted
if all devices go away, before they start working.
It also seems like the right thing to do, because if you remove links
manually, this does not cause errors to occur.
When `val` was used, it was always a true-ish since the
address of an array on the stack was assigned to it.
Remove this variable altogether, and use `name` directly.
Only use `name` when it is valid - when `key && value`.
`impl->default_sink` is dynamically allocated, but previously
it was not freed when the containing struct was being destroyed.
Fix that by freeing it in `session_destroy()`.
There's no particular problem to have default.configured to point to a
non-existent device, it will be ignored. This was left over when
default and configured default were made separate things.
default-nodes also doesn't need to track the id of the configured
default, so remove also other stuff that's no longer necessary. It can
simply load the values to metadata on startup, and save them to a file
when they are changed, without needing to understand what the values
mean.
Also fixes commit 7071562334 causing defaults to be forgotten when
nodes are removed.
We only want to call process() from Start when we are not a driver and
not realtime.
When we are a driver, the user will need to call _trigger_process()
to kick things of.
When we are asked to schedule process from the realtime thread, we
need to wait until the RT thread is scheduled.
In all other cases we can call _process() from the mainloop so that
the RT thread has something to collect when it gets scheduled.
When the node is driving, we need to call trigger_process()
otherwise we don't and we simply need to wait for the process() to
be called, triggered by the driver node.
See #1484
It has the DRIVER flag set and sets a PW_KEY_PRIORITY_DRIVER value
to something higher than the source so that it becomes the driver.
Every timeout it does pw_stream_drive() to start the graph, which
will eventually call the process function with a pulled buffer to
display.
The framerate is set to something lower (80ms between frames) to
show the pull effect.
fixes#1484
This method is meant for driver streams when they have data or need
data.
Previously only source (output) streams could drive the graph and
indirectly by doing pw_stream_queue_buffer(). This behaviour is now
deprecated (but will still work) in favour of calling
pw_stream_drive() explicitly.
pw_stream_drive() will call the process function immediately (if
driver) or later (when not a driver) so that the same code paths
can be used when running as a driver or not.
In a similar way, a consumer (input) driver stream can now be
written. It will call pw_stream_drive() when it wants data and the
process function will be called when the data is ready.
See #1484
We need to check the position vs the clock to see if we are currently
driving the graph. We can only call the node ready callback when
we are actually driving the graph.
"restored" describes a state but the only case we actually set this
value if we want to restore our previously saved profile. Rename a
variable to indicate this, makes it easier to understand.
Add module that switches bluez device profile to HFP/HSP if an input
stream (non-monitor, autoconnect) appears, and the current default
output device is bluez one that does not have input route.
When all input streams are gone, switch all changed profiles back.
Pending restore state is saved to session manager state files, in order
to restore it if e.g. devices get disconnected. This usually is not
currently necessary since the bluez5 plugin prefers to connect to A2DP
over HFP, but might matter in future with backchannel-enabled A2DP
codecs.
This test needs an environment set up to load everything correctly,
running it directly results in a segfault. Let's make sure we assert on
a NULL loop to make this look slightly more planned.
Add a new client-node port_set_mix_info event. bump the interface
version to 4 and the event version to 1.
The event is used to send information about the peer object to the
port mixer. This can be used to track what buffers belong to what
peer.
Reevaluate the graph again after we potentially suspend because of a
rate change because links might become unprepared and need to be
prepared again before the node becomes active.
We call setup_alsa_ucm_endpoint() before the
setup_alsa_fallback_endpoint(), but this function always returns
-ENOTSUP. Add a FIXME comment to make this more obvious.
spa_strstartswith() is more immediately understandable.
Coccinelle spatch file:
@@
expression E1, E2;
@@
- strstr(E1, E2) != E1
+ !spa_strstartswith(E1, E2)
@@
expression E1, E2;
@@
- strstr(E1, E2) == E1
+ spa_strstartswith(E1, E2)
Applied to the tree except for alsa/acp/compat.h because it looks like
that header is still mostly as-is from PA.
Add a default.clock.allowed-rates property that lists the possible
rates for the graph.
Add node.rate and node.lock-rate properties to suggest a graph rate
and lock the rate.
Collect the largest clock rate from the nodes and if it is allowed,
try to configure it as the graph rate. Only switch rates when the
driver is IDLE or suspended or when we force a rate.
No alternative samplerates are specified because we first need to
work around a common driver bug (cards with 1 cristal need the same
rate for capture as playback) for this to work.
Rework the quantum and max_quantum handling. Work directly with the
latency fractions and calculate the final quantum size until we know
the samplerate.
The graph will not switch quantums when there is an active node
with the node.lock-quantum property set to true.
It can be used to stop certain jack clients from crashing when the
quantum changes.
Hard rate changes (the default now) makes the graph suspend so that the
driver reopens the device with the new sample rate if possible. This
causes a glitch.
Soft rate changes works as before and just changes the clock rate of
the position area, which makes everything resample things to the new
rate without a glitch.
Sample rate changes can currently still only be triggered by
configuring the settings metadata clock.force-rate
We don't need to follow nodes that we already visited or that are
inactive so skip them early.
Always try to prepare the link otherwise, not only for passive links
because non-passive links might also be paused because of a suspended
driver.
We only ever want to prepare a link between active nodes so add the
check in the _prepare() functions instead. This also makes it skip
the prepare step for inactive nodes when recalculating the graph.
This adds a new top-level documentation entry for pipewire-media-session
with a list of modules (currently only one). Similar setup to the
pipewire modules, it allows us to document all modules in-place.
Leaving sockets in the home directories is bad form, so let's not do
this.
This effectively requires XDG_RUNTIME_DIR to be set for pipewire to
work - it is set correctly on most setups anyway and on custom setups
this needs to be addressed with a custom environment.
Fixes#1443
The target signal is called when the peer nodes are ready and this
node needs to be scheduled. It is the in-process version of the
signal.
Remove our custom version that, just like the default version, schedules
the node implementation but doesn't do any accounting.
Makes pw-top report driver stats for bluetooth devices.
Fixes#1450
Make a new PW_KEY_NODE_WANT_DRIVER to assign the node to a running
driver. (does not work yet)
Use a new variable to hold the ALWAYS_PROCESS setting and also
update want_driver.
This makes things it a bit more future proof.
Virtual sinks and sources implemented with streams need to be grouped
with a driver node to be able to schedule. We don't have a way to let it
use a default driver so add it to the pipewire.dummy driver.
This fixes stalled pipe and other streams streams.
Fixes#1407
We always want to clear the provided blocklist from the properties. The
logic tries to only clear when there was a blocklist but it checks this
by comparing the string pointer to the fallback, which gives a compiler
warning.
`getpwuid_r()` puts the strings pointed to from the returned
passwd struct into the specified buffer. Previously, that
buffer technically didn't live long enough to be usable
in the `snprintf()` call - although in practice this didn't
appear to be a problem. A particular version of GCC 11 generates
the same machine code for this function regardless whether
this patch is applied or not. Still, fix this by moving
the buffer to an outer scope.
module-switch-on-connect sets the configured default sink/source
whenever suitable new sink/sources appear.
This should give the same behavior as Pulseaudio's module.
This module exists mainly to provide a workaround e.g. for desktop
environments such as XFCE, whose mixer applications try to manage the
default devices assuming fully PA-like behavior, breaking default
pipewire output switching.
When we remove a default node, remove it from the properties and trigger
a save of the state so that the configured default is also actually
removed from the state file.
- use meson to check for gettid() function, always use if available
- use syscall fallback on linux, if not
- restrict thr_self() fallback to *only* FreeBSD
- error out if there isn't any gettid impl