The existing code meant to generate device groups for combination ports
is tightly coupled to port creation. Similar functionality would be
useful to generate nonconflicting device groups for multiple profiles as
well, so this tries to rewrite it into a more reusable state.
Several things (e.g devices, mapping contexts) use idxsets to store a
device selection. This also switches this conformance check and device
group generation to using idxsets to make it easier to work with those,
with the eventual aim to unify device group representations.
Also try to adjust users of these functions to use idxsets these will
need/return, without causing too much interference.
Link: 0f26022843
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Add contains() function that checks if an item is in an idxset. Add
isdisjoint(), issubset(), issuperset() and equals() functions that
element-wise compare two idxsets.
Add complementary functions to the existing idxset search(), first(),
next() functions that work in the reverse direction: reverse_search(),
last() and previous().
Add steal_last() to remove and return the last item in the idxset.
[Alper: original patches for PulseAudio, split from other commit]
Co-developed-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Link: fb63e58931
Link: ec668ac44b
Link: 97d9c28579
To support having multiple profiles per UCM verb, split the profile
creation into two parts based on whether they should run once for each
verb or for each profile (maybe multiple times per verb).
Link: 638574c0b7
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
The ucm_create_mapping() function is not idempotent. It looks like it
was meant to be called once per device for the devices of a UCM verb
and takes a profile argument simply because a verb has generated a
single profile so far.
Make sure creating mappings per device and adding those mappings to the
profiles happens as separate steps to make it easier to split UCM verbs
and profiles as concepts.
Link: aa5ced3887
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
So far each profile had the exact name as their associated UCM verb,
which caused the one to be used where the other should have been.
Explicitly get and use the verb name where that was intended, and make
sure things about profiles aren't named after verbs.
Link: 4527890416
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Currently each UCM verb generates one profile named the same as the
verb, meaning it's trivial to know which verb the profile belongs to.
This will be slightly harder to do when we generate multiple profiles
per UCM verb (e.g. to make use of conflicting devices).
It would still be possible to parse the profile name to get the UCM
verb, but instead let's keep track of the struct instance representing
the profile's associated verb. This also lets us remove a block of code
searching for the verb by its name.
Co-authored-by: Jaroslav Kysela <perex@perex.cz>
[Alper: Reused Jaroslav's UCM profile context changes for UCM verb
instead of combined devices.]
Link: 9fc7064b9a
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
While switching profiles, it's possible that we will want to do more
work besides switching UCM verbs. The alsa-card module already has our
profiles as structs, but passes in only the names instead of the entire
struct. Make things work with the struct instead, so we can add other
things (like a UCM context) to it and use those here.
Co-authored-by: Tanu Kaskinen <tanuk@iki.fi>
[Alper: Split into its own commit and integrated Tanu's snippet.]
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Link: 880ff393f1
[Wim: Apply to acp_card_set_profile() as well]
Co-authored-by: Wim Taymans <wtaymans@redhat.com>
Right now manipulating device status is done inline once while setting a
port. However, we will need to reuse this code to disable conflicting
devices of a device we want to enable. Split it into enable and disable
helper functions.
There is another issue with the device enable logic, where trying to
disabling an already disabled device sometimes fails. To avoid that,
implement a status helper and check if the device we want to enable is
already enabled/disabled before trying to do so.
Link: 9b06e8fef4
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Modifiers currently keep their conflicting and supported devices's
names, and these names are resolved to devices every time we need to use
them. Instead, resolve these device names while creating the modifier
struct and keep track of the resulting device structs in idxsets, same
as how device structs keep track of their support relations.
Link: 9b06e8fef4
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
This is intended to make the current and upcoming code a bit clearer, as
we won't need to constantly check for the existence of these idxsets
before using or operating on them.
Link: d8c89de24d
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
The code that removes the mixer path if probing fails can be called in
the path that sets a non-off device profile on hotplug *before*
card->active_profile is updated, which results in spuriously removing
the mixer path. By this point, context->ucm->active_verb would be set
to the same as the profile name, so we can use that instead to avoid
the issue.
On Apple Silicon machines with the UCM profiles in the Asahi Linux repo,
this manifests as the headphones jack having hardware volume controls
*only* if PA is started with headphones connected and until they are
disconnected. Hotplugs end up triggering the bad codepath, and it falls
back to software volume (which is particularly a problem when the
hardware volume happens to be very low or 0 at that point).
Signed-off-by: Hector Martin <marcan@marcan.st>
Link: 3e038c6d88
Looks like original intention was to scan over sample formats supported by PA,
but code does the scan by list of alsa formats. Reverse the map and adjust
fallback case which now can use the same map.
Link: 5ab2b9cb0e
Perform detection of supported sample format and rates just after device is
opened, before `snd_pcm_hw_params()` is called for the first time. This fixes a
problem where device restricts available sample rates after HW params are set
preventing sample rate detection (seen with UAC2 devices and kernel 6.1.9)
Bug: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1414
Bug: https://github.com/alsa-project/alsa-lib/issues/119
Link: aed52c507f
[Wim: Apply to acp add_pro_profile(), enable pa_alsa_supported_*()]
The full identifier check must be executed for the new melem
creation, otherwise the duplicate control element code check
is reached.
Example (using the snd-aloop driver):
numid=56,iface=PCM,name='PCM Notify',device=1,subdevice=1
numid=62,iface=PCM,name='PCM Notify',device=1,subdevice=2
Link: 81a051089f
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
The new helem must be tracked and old helem must be cleared
to make the code work properly. Introduce the pointer to helem
as the private value for melem and add the necessary code.
Also, add a check for the duplicate mixer elements. The duplicate
mixer element invokes the abort check in alsa-lib. Print a warning
instead and handle the exit gracefully.
Link: d1675df0cd
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
It may be possible that the ALSA control element appears
again. Allow this combination by checking, if the pulseaudio
mixer element already exists. Do not create the duplicate
mixer element in this case.
Link: def8eb074e
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
sync_mixer() calls d->set_volume(d, &d->real_volume);
which makes v and &dev->real_volume point to the same memory area
and valgrind complains:
Source and destination overlap in memcpy(0xcc53e2c, 0xcc53e2c, 260)
at 0x488CFA0: __GI_memcpy (vg_replace_strmem.c:1121)
by 0xBB0803F: set_volume (acp.c:1143)
by 0xBB0EDCB: acp_device_set_port (acp.c:1897)
by 0xBA9CD87: impl_set_param (alsa-acp-device.c:757)
because the compiler apparently implicitly converts this into a memcpy()
and memcpy(3) explicitly says "The memory areas must not overlap."
api.acp.hidden-ports and api.acp.hidden-profiles can be used to pass
a json array of ports and profiles to hide. They will not show and
will not be selectable.
Don't try to multiple the max_buffer_size with the frame scale or else
we might try to set a min_buffer_size larger than the max_buffer_size.
Instead, use the frame_scale only to scale the quantum_limit and then
clamp against the max_buffer size.
See #3000
When the period events are enabled, we need to wake up whenver there is
a period elapsed. Otherwise, we only wake up when there is avail_min.
Fixes#3676
Executable memfds can be a security issue.
The kernel warns about them like the following:
pipewire: memfd_create() called without MFD_EXEC or MFD_NOEXEC_SEAL set
Explicitly create all memfds a non-executable as they are not meant to
be executed, similar to the other possible backing filetypes.
As reported in #3217, PTP driver has to have the highest priority for packets to arrive in time
Everything connected to AES67 should be clocked by the Grandmaster clock
Convert capture and playback streams to any global channel position that
has been set. This can then be used to implement an upmix sink and add
such an example config.
When we get a Format update during a Format set_param, return > 0 to the
caller so that it knows we modified the param to something else.
This can be used to fixate or deny updates to Format params in the
stream and have the adapter adapt to this.
Keep the target and source fd in sync when we get the new fd from the
server in remote-node.
This makes it possible to refactor some things and only schedule nodes
by triggering the target.
Some JACK clients place OSC messages in MIDI buffers. Try to detect the
OSC messages and mark the control as OSC.
Also allow OSC control to be converted to JACK MIDI.
This should make things work better with native PipeWire clients that
handle MIDI and OSC.
We place the currently configured runtime settings in the properties but
clear the values when not negotiated. Don't do that but place the
defaults (when set) instead.
When we don't have the thread id yet, don't add the pollfds yet
but wait until we do our first wait operation.
Use flags for eventfd. We can use this to communicate between all kinds
of threads with read/write.
Use evl_init() in the init function, don't attach the main loop, just
the thread that dos the first poll.