We should not use nsec from the clock as the current_usec because
current_usec is supposed to be an idealized time when the wakeup would
have happened and nsec is when it actually happened.
Instead use next_nsec and subtract the rate corrected period from it to
get the idealized current_usec.
We can still use nsec to calculate the elapsed time since the wakeup and
be sure that it is always in the past.
The Pro Link 1 replies with Audio-latency=0, patch that up to
1500ms to make it work again.
Previously it configured 1500ms as the default latency but that seems
unnecessary in the usual case.
Fixes#3698
Make sure that NULL params don't cause -EINVAL but ignore them.
Don't add empty param objects. this makes it possible to clear all previous
params by setting an empty object.
We always need to add the Props param because it contains the
debug.aec.wav-path key, which is always available, even when the AEC
implementation has no properties.
Also add the debug.aec.wav-path PropInfo.
We can reuse the same code for setting input and output stream
properties. This also makes it possible to set the debug.aec.wav-path
on all streams, like the properties say.
Don't have separate input route for A2DP and HFP, as it is generally not
necessary.
When in A2DP mode when there's also HFP possible, emit the input route
in SPA_PARAM_Route, even though there is no corresponding input node
emitted.
The host may then emit a loopback microphone node, and switch profiles
according to its status. Having the input route available at all times
allows to retain changes to volume settings made when there is no real
input node.
For params that don't emit change events, the param enumeration does not
start core sync, and its enumeration may be incomplete if a previous
core sync completes first.
Fix by always starting a core sync if we are updating params.
This fixes dev_info.active_port being sporadically SPA_ID_INVALID if
there is event pressure, which causes do_set_volume randomly set the
volume on the node instead of setting it on the device. This can be
triggered e.g. by shaking the volume slider in Pavucontrol with mouse.
Letter codes instead of numbers for log levels are allowed in
PIPEWIRE_DEBUG.
Support them also for log.level in context properties and metadata.
Add a few alias letter codes to harmonize them with what WirePlumber 0.5
supports.
We delay the audio a bit to keep packet intervals equal, which keeps
some data in buffers.
In theory the calculation keeps one buffer free, but it doesn't
explicitly keep "extra" buffer space so in theory might flush too late
and next process() might not have free buffers. However, as we encode
next packet right away this shouldn't really occur...
Try to keep one extra spare buffer free so that the flush time is
certainly early enough.
Tabs and spaces are mixed for indentation in the pipewiresink. Replace
all tabs with 8 spaces although indentation is 2 spaces, since that
looks like the intended indent.
The messages are printed for every buffer. Therefore, they should be log
messages. Also add the bufferpool to the message to be able to identify
the bufferpool that handles the buffers.
The buffers are added to the pipewirepool during setup. Therefore, they
should be debug messages. As at it, use the debug helper to print the
string of the buffer type.
The alsa sequencer rate matching was not actually working correctly.
It would compare the previous queue time with the current time and
compare that to the quantum. This would include uncorrected errors from
jitter and would result in the timeouts being scaled in the wrong
direction forever.
Instead, calculate an ideal queue time and compare our current queue
time against that. We then use the correction to scale the timeout or
the next queue time prediction.
Also use the predicted time as the base time for the event timestamps.
this results in less jitter.
Fixes#3657
While switching to the Pro Audio profile from a UCM profile, the active
UCM profile is not disabled because the devices may need a UCM verb to
be set before being used. Then, switching away from the Pro profile to a
UCM profile is done by passing the Off profile as the old profile,
instead of the actually-still-enabled UCM profile.
This means the devices from the old UCM profile are kept enabled when we
try to switch to another UCM profile. And the devices to enable may be
conflicting with the still-enabled devices, which will cause failures.
To avoid this, we need to tell the UCM code to disable the profile when
switching away from it. Doing so disables UCM devices and the UCM verb.
Existing code sets the highest priority UCM verb before probing the Pro
profile, so manually enable the same one here as well, instead of
relying on unclean state from whatever profile that was last active.
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
The hardware controls we track for volume and mute state can change as
part of enabling or disabling the UCM device. This then triggers a
re-sync of our state with the hardware controls, which can e.g. set our
volume to an unwanted value as the result of enabling the device, or set
a hardware control to a wrong value based on our volume while disabling
the device. So these UCM-triggered changes to enable/disable the device
will at best show up on user interfaces and cause confusion, but maybe
even will push the hardware into an unexpected state.
The volume and mute state we set from user interfaces only make sense
when the devices are enabled. They should not be kept in sync with
hardware for inactive UCM devices [1]. Skip the callbacks for reading
and changing volume and mute state if the UCM device is disabled. This
way, the volume/mute controls for sinks/sources are essentially detached
from the hardware controls until the UCM device is re-enabled.
[1] https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/772#note_1872757
Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/772
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
The pa_alsa_ucm_set_port() function is passed both a mapping context and
a device port, and both of these refer to their respective UCM device.
While switching over to having one port per mapping per UCM device, I
expected both of these to be the same device struct, so added an assert
checking so.
This assertion gets triggered when we have multiple UCM verbs declaring
the same UCM device name. The root cause here is that the ports' UCM
device references are set once while creating the ports for the card, so
they happen to be those of a specific verb and may not match those from
a different UCM verb's profiles' mappings.
Solving the root cause necessitates a larger refactor. What we actually
assume here is that name of the UCM device is same for both the port and
the UCM context, which ends up always true in practice. For now, replace
the assert with a check and error.
Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/802
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Some versions of the ALSA libraries run into a segmentation fault when
we query a UCM device/modifier status without first setting a UCM verb.
It's not a reasonable thing to do anyway, so check for this case and
return an error. Also do the check in other helpers.
Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/801
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
The ucm_get_device_property() function adds to each UCM device's
playback_volumes (or capture_volumes) hash map an associated volume
mixer keyed with the UCM verb. These key-value pairs are then iterated
over in various places which assume the key is a profile name. This
assumption is no longer true since we can generate multiple profiles to
use conflicting devices.
A previous commit 45278904167f ("alsa-ucm: Stop conflating profile name
with UCM verb name") fixes some instances of this assumption, but misses
the relation explained above. Fix more instances of misleading
"profile"s where the UCM verb name is actually meant.
Link: 7005eafee3
Fixes: 57295beee1a6 ("alsa-ucm: Stop conflating profile name with UCM verb name")
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Although it's a valid UCM configuration to have multiple devices using
the same PlaybackPCM or CapturePCM, it's unclear how PulseAudio should
handle the cases where multiple of these devices are enabled. Some
options I can think of are:
- Merge all devices sharing the same PCM into the same mapping, open
only one PCM substream for this mapping, and add 'combination ports'
that enable combinations of the devices. This has been the case until
recently, although the combination port logic was broken. A problem
with this is that we can't independently control device volumes. We
most likely cannot use hardware volumes either.
- Have one mapping for each device in the same profile, and open one PCM
substream for each mapping. This is the current state, and it fails
when there are fewer substreams than devices. Otherwise it works, but
it's still confusing, as sound directed to a device-specific mapping
might end up playing at multiple devices.
- Make multiple profiles each with combinations of upto-substream-count
devices, and have one mapping/substream per device. This still causes
the confusion mentioned above. And it's likely that the substream
count will almost always be one, where this case degenerates into the
last one.
- Have one mapping for each device in the same profile, but open only
one PCM substream. I assume this is possible with software mixing, but
it is still confusing like the above, and probably less performant.
- Generate multiple profiles each with one of the shared-PCM devices,
again with one mapping/substream for that one device. The trade-off
with this is that we can't use multiple of these devices at the same
time. However, this doesn't have the output device confusion,
combination port's volume problems, or the substream count limitation.
This patch takes a short-cut to achieve the last option, by considering
shared-PCM devices implicitly conflicting with each other.
Link: 45509ff9bc
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
While switching profiles of the same UCM verb, existing code first
disables devices that are only on the first profile to avoid conflicts.
However, it only disables devices, not modifiers. Even worse, modifiers
which have PlaybackPCM/CapturePCM are incorrectly treated as devices and
result in a segmentation fault.
Check what we are disabling, and call the appropriate disable function
for both devices and modifiers. Modifiers are disabled before devices,
because _dismod calls fail when the modifier's supported devices are
disabled.
Link: b74269016c
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
These are mostly the same as the device helpers added in c83b34516929
("alsa-ucm: Add enable, disable, status helpers for devices"), but for
modifiers instead.
Link: b382a00f8b
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Right now we try to add all UCM devices of a verb to a single profile.
But if some devices using different PCMs are configured as conflicting
with one another, we will only be able to utilize one of them, chosen
seemingly based on the order in the UCM config file.
This is not a problem with conflicting devices sharing a PCM, as they
are assigned to the same mapping and the ports mechanism only enables
one of them to be active at a time.
To utilize all devices in a UCM verb even when there are conflicting
devices using different PCMs, calculate subsets of devices which
can be simultaneously used and create a profile for each such set.
Link: 5dd411190d
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
While switching profiles, it was enough to switch UCM verbs since that
disables all enabled UCM devices and every profile had a distinct verb.
However, switching to the current verb does not disable any devices.
To support multiple profiles for a verb we need to explicitly disable
the old profile's devices, since they might be conflicting with the new
profile's devices and will prevent them from being enabled. Compare both
profiles' mappings, and disable the devices not in the new mappings.
Link: e49da7bcd6
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
After previous patches, we should be generating no combination ports, so
we don't need to store multiple modifiers per mapping. Simplify the code
based on this.
Link: 4821a0569e
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
After previous patches, we should be generating no combination ports, so
we don't need to store multiple devices per mapping. Simplify the code
based on this.
Link: 084d70a1e2
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
[Wim: Apply to acp add_profiles() and acp_card_set_profile()]
After previous patches, we should be generating no combination ports, so
we don't need to store multiple devices per port. Simplify the code
based on this.
Link: bf1708213b
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
A previous commit makes mapping names depend on the UCM device name.
Since UCM device names are unique, this means a mapping will at most
have one port and thus no combination ports can be generated.
This removes the dead code in the pa_alsa_ucm_add_ports_combination()
function, unrolls the remaining code in its helper functions that it
used, and renames it to pa_alsa_ucm_add_port() to signal that it no
longer generates combinations.
Link: 0789a8fb76
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
[Wim: Apply to acp add_profiles(), acp_card_set_profile(), compat.h]
PulseAudio combines UCM devices that have the same PlaybackPCM or
CapturePCM value into a single mapping with multiple ports. It also
creates ports in the same mapping for each valid combination of those
UCM devices.
Since mappings are the things we put in profiles, we can put in a
profile either all devices of a joint mapping or none of them. This
causes some complications with device conflicts. For example, a
different UCM device might be marked as conflicting with some (but not
all) of the devices in a joint mapping. In this case we can do one of
three things:
- Include all devices in one profile, and hope the conflicting device
isn't chosen as the mapping's active port. We shouldn't do this as it
puts conflicting devices in the same profile.
- Make one profile with the joint group, and one with the other device.
This is somewhat acceptable as we have no conflicts, but we sacrifice
some compatible combinations of devices.
- Do not group the devices into the same mapping, and make one profile
for each compatible combination of devices. This appears to be the
best option, one where we can always have the maximum number of
working devices.
This patch chooses the third option and makes one input and/or output
mapping per UCM device, by using UCM device names instead of PCM device
strings in the mapping names.
Link: a50330a4a5
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Combination port logic calculates some useful properties for device
groups that we could reuse while generating multiple profiles to support
conflicting devices. Split them into their own functions.
Link: e8e2f4320c
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
Right now this check is rejecting devices whose UCM config specifies
neither a conflicting device nor a supported device list, and accepting
devices which specify both. However, a device without neither list is
actually unrestricted, and a device with both lists is a configuration
error. Fix the check to accept the former.
Furthermore, this is missing another case where an already selected
device might have a supported devices list that doesn't have the
candidate device. Make this function also check against that, and also
make it accept devices already in the set.
Link: 5245117781
Signed-off-by: Alper Nebi Yasak <alpernebiyasak@gmail.com>
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>