Since 14.0, filter streams would be killed if the master sink or source disappeared. This
patch changes the behavior to allow rescuing of filter streams.
If the output implements a process_rewind() callback, the resampler delay is
not taken into account. This leads to glitches during volume changes when
source and source output rates differ.
This patch fixes the problem.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/120>
The pa_resampler_get_delay() function allows to retrieve the current resampler
delay in input samples for all supported resamplers. The return value is a double
to maintain precision when using variable rate resamplers. Because in many places
the delay is needed in usec, pa_resampler_get_delay_usec() was also supplied.
The speex resampler now skips leading zero samples to provide meaningful delay values.
In the next patch, the pa_resampler_prepare() function will be used to train the
resampler after a rewind. It takes data from a history memblockq and runs it through
the resampler. The output data is discarded.
To make this logic possible, the soxr resampler had to be converted to use variable
rate. The fixed rate version has a variable delay, therefore the logic above could
not be applied. Additionally, with fixed rate, the delay is larger than 150ms in
some situations, while with variable rate the delay is fixed and comparable to the
other resamplers.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/120>
The hooks are fired when the preferred device changes. This is useful
for module-stream-restore.
I added new set_preferred_sink/source() functions for firing the hooks.
The functions also log the preferred device changes.
There was already pa_sink_input_set_preferred_sink(), but that had a
side effect of moving the stream, so I needed a new function. Since it
can be confusing when the two similarly named functions should be
called, I added a comment for pa_sink_input_set_preferred_sink() that
explains the different situations.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/535>
When the source-output of a virtual source with volume sharing disabled is moved,
the source output volume is reset to 100%. This patch fixes the problem by
applying the virtual source volume to the source-output after the move.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/509>
When the user moves a stream to the current default source, the
preferred_source should be set to NULL and module-stream-restore
should clear the routing for that stream in the stream database. From
that point on the stream will be always routed to the default source.
Signed-off-by: Hui Wang <hui.wang@canonical.com>
If the source here is NULL, that means users want to clear the
preferred_source and move the source-output to the default_source,
otherwise set the preferred_source to the source->name and move the
source-output to the source. After that fire the source_output_change
event.
After adding this API, we can use this API to simplify the entry_apply
in the module-stream-restore.c.
Signed-off-by: Hui Wang <hui.wang@canonical.com>
The finial objective is to store the preferred source name in the
source-output struct, and use module-stream-restore to save and
restore it.
This patch just replaces the save_source with preferred_source, and
tries to keep the original logic.
Signed-off-by: Hui Wang <hui.wang@canonical.com>
remixing-produce-lfe controls upmixing, and remixing-consume-lfe
controls downmixing. The motivation is that a user might want to
synthesize LFE while playing stereo audio on his/her 5.1 speakers,
but at the same time follow the industry recommendation to omit
the LFE channel when producting a stereo downmix (e.g. for headphones)
from 5.1 content. Or the other way round.
Fixes: #753.
Currently the rewind logic for the source output is broken if the output
does not implement a process_rewind() callback. In that case, the read
index of the delay memblockq is rewound. This is wrong, because the data
that is going to be re-written was not yet read. Instead the write index
should be rewound and the read index left untouched. This is the reason
for the rewind glitches of monitor sources.
Sample format(e.g. 16 bit, 24 bit) was not considered even if the
avoid-resampling option is set or the passthrough mode is used.
This patch checks both sample format and rate of a stream to
determine whether to avoid resampling in case of the option is set.
In other word, it is possble to use the stream's original sample
format and rate without resampling as long as these are supported
by the device.
pa_sink_input_update_rate() and pa_source_output_update_rate() are
renamed to pa_sink_input_update_resampler() and pa_source_output
_update_resampler() respectively.
functions are added as below.
pa_sink_set_sample_format(), pa_sink_set_sample_rate(),
pa_source_set_sample_format(), pa_source_set_sample_rate()
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
pa_sink_get_state() and pa_source_get_state() just return the state
variable. We can as well access the state variable directly.
There are no behaviour changes, except that module-virtual-source
accessed the main thread's sink state variable from its push() callback.
I fixed the module so that it uses the thread_info.state variable
instead. Also, the compiler started to complain about comparing a sink
state variable to a source state enum value in protocol-esound.c. The
underlying bug was that a source pointer was assigned to a variable
whose type was a sink pointer (somehow using the pa_source_get_state()
macro confused the compiler enough so that it didn't complain before).
I fixed the variable type.
pa_sink_input_get_state() and pa_source_output_get_state() just return
the state variable. We can as well access the state variable directly.
There are no behaviour changes, except that some filter sources accessed
the main thread's state variable from their push() callbacks. I fixed
them so that they use the thread_info.state variable instead.
The volume_map variable was initialized only for PCM streams, but the
variable was passed to pa_cvolume_remap() also for non-PCM streams. The
volume remapping is never necessary for passthrough streams (PCM or
not), because no volume will be applied anyway, so let's skip the
pa_cvolume_remap() call for all passthrough streams.
When a stream is created, and the stream creator specifies which device
should be used, that can affect automatic routing policies.
Specifically, module-device-manager shouldn't apply its priority list
routing when a stream has been routed by the application that created
the stream.
A stream that was initially routed by the application may be moved for
some valid reason (e.g. user requesting a move, or the original device
disappearing). When the stream is moved away from its initial device,
the "device requested by application" flag isn't relevant any more, so
it's set to false and never reset to true again.
The change in module-device-manager's routing logic will be done in the
following patch.
Coverity complained about data->sink being possibly NULL when it's
dereferenced later. It was difficult for me to figure out whether that
was a false positive or not. Hopefully the comments make it a bit
easier to reason about the code in the future.
CID: 1323591
This rejigs the update_rate() logic to encompass changes to the sample
spec as a whole, as well as passthrough status. As a result,
sinks/sources provide a reconfigure() method which allows
reconfiguration as required.
The behaviour itself is currently unchanged -- alsa-sink/-source do not
actually implement anything other than rate updates for now (nor are
they ever requested to). This can be modified in the future, to allow,
for example 24-bit output when incoming media supports it, as well as
channel count changes for passthrough sinks.
Another related change is that passthrough status is now part of
sink/source reconfiguration, and we can stop doing a suspend/unsuspend
when entering/leaving passthrough state. So that part is now divided
in two -- pa_sink_reconfigure() sets the sink in passthrough mode if
required, and pa_sink_enter_passthrough() sets up everything else
(this currently means only volumes, but could disable other processing)
for passthrough mode.
the comment /* Fall through. */ fixes the warning, but gcc-7 seems to be more
picky about the position in the code
pulsecore/sink-input.c: In function ‘pa_sink_input_update_proplist’:
pulsecore/sink-input.c:1531:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
for (state = NULL; (key = pa_proplist_iterate(i->proplist, &state));) {
^~~
pulsecore/sink-input.c:1539:9: note: here
case PA_UPDATE_REPLACE: {
^~~~
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
When a filter sink is moving, it's not connected to any master sink, and
therefore it's not connected to any IO thread either. In this situation
trying to move a stream that is connected to the filter sink is likely
to result in crashing, because starting the move involves sending a
message to the IO thread. Sometimes this works by accident (the
asyncmsgq of the filter sink still points to the old master sink's
asyncmsgq), but we really should never attempt it. This patch blocks all
moves where the moving stream is connected to a filter sink that itself
is in the middle of a move.
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=100277
The reported latency of source or sink is based on measured initial conditions.
If the conditions contain an error, the estimated latency values may become negative.
This does not indicate that the latency is indeed negative but can be considered
merely an offset error. The current get_latency_in_thread() calls and the
implementations of the PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY messages truncate negative
latencies because they do not make sense from a physical point of view. In fact,
the values are truncated twice, once in the message handler and a second time in
the pa_{source,sink}_get_latency_within_thread() call itself.
This leads to two problems for the latency controller within module-loopback:
- Truncating leads to discontinuities in the latency reports which then trigger
unwanted end to end latency corrections.
- If a large negative port latency offsets is set, the reported latency is always 0,
making it impossible to control the end to end latency at all.
This patch is a pre-condition for solving these problems.
It adds a new flag to pa_{sink,source}_get_latency_within_thread() to allow
negative return values. Truncating is also removed in all implementations of the
PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY message handlers. The allow_negative flag
is set to false for all calls of pa_{sink,source}_get_latency_within_thread()
except when used within PA_{SINK,SOURCE}_MESSAGE_GET_LATENCY. This means that the
original behavior is not altered in most cases. Only if a positive latency offset
is set and the message returns a negative value, the reported latency is smaller
because the values are not truncated twice.
Additionally let PA_SOURCE_MESSAGE_GET_LATENCY return -pa_sink_get_latency_within_thread()
for monitor sources because the source gets the data before it is played.
If pa_sink_input_cork() or pa_source_output_cork() were called without a sink
or source attached, the calls would crash pulseaudio.
This patch fixes the problem, so that a source output or sink input can still
be corked or uncorked while source or sink are invalid. This is needed to
correct the corking logic in module-loopback.
At the time the "unlink post" hook is fired, the stream is not any more
connected to its old device, so it makes sense to reset the sink/source
pointer to NULL before firing the hook. If this is not done, the pointer
may become stale during the "unlink post" hook, because
module-bluetooth-policy does a card profile change in its "unlink post"
callback, so even if the pointer is valid when module-bluetooth-policy's
callback is called, it will be invalid in subsequent callbacks.
Sink(-input) and source(-output) called unlink function when reference
count dropped to zero. This would result in unlink hooks being called
with an object having a reference count of zero, and this is not a
situation we want modules to have to deal with. It is better to just
remove the redundant unlinking code from sink(-input) and
source(-output) and assert on reference count in unlink functions as well.
It is expected that in well behaving code the owner of an object will
always unlink the object before unreferencing.
Signed-off-by: Arun Raghavan <arun@arunraghavan.net>
pa_sink_input_update_proplist() is inconvenient in many cases, because
it requires allocating a new proplist, even if the goal is to just set
one property. pa_sink_input_update_properties also can't properly log
property changes, because it has to assume that all values are
arbitrary binary data.
This patch adds pa_sink_input_set_property() for setting a string
value for a single property, and pa_sink_input_set_property_arbitrary()
for setting a binary value for a single property.
pa_sink_input_update_properties() is reimplemented as a wrapper around
pa_sink_input_set_property_arbitrary() to centralize logging and
sending change notifications.
(The above mentions only sink input functions for brevity, but the
same changes are implemented for source outputs too.)
Before a device is unlinked, the unlink hook is fired, and it's
possible that a routing module tries to move streams to the unlinked
device in that hook, because it doesn't know that the device is being
unlinked. Of course, the unlinking is obvious when the code is in an
unlink hook callback, but it's possible that some other module does
something in the unlink hook that in turn triggers some other hook,
and it's this second hook where the routing module may get confused.
This patch adds an "unlink_requested" flag that is set before the
unlink hook is fired, and moving streams to a device with that flag
set is prevented.
This patch is motivated by seeing module-device-manager moving a
stream to a sink that was being unlinked. It was a complex case where
an alsa card was changing its profile, while an echo-cancel sink was
connected to the old alsa sink. module-always-sink loaded a null sink
in the middle of the profile change, and after a stream had been
rescued to the null sink, module-device-manager decided to move it
back to the old alsa sink that was being unlinked. That move made no
sense, so I came up with this patch.
This gets rid of an error message from the debug log. If
volume_factor_source would actually be used somewhere, this bug would
have caused more severe problems.
volume_factor_source should have the source's channel map. When moving
the stream, the volume needs to be remapped from the old source's
channel map to the new source's map. However, when the stream is being
moved, there is a period where the old source has already been
forgotten and the new source isn't yet known, so the remapping can't
be done directly between the two channel maps. Instead, the volume is
remapped from the old source's map to the stream's own map when the
move starts, and again remapped from the stream's map to the new
source's map when the move finishes.
The first remapping was missing, causing the second remapping fail and
print an error to the log.
(I checked the sink input code as well. It didn't have this bug.)
Applying the volume after resampling means mismatch between the volume
channel map and the data channel map.
volume_factor_source is not currently used anywhere, so this bug
hasn't been causing any problems. I noticed it while reading the code.
The resampler framework just forwards the request to the lfe filter.
There are no resampler impl that can rewind yet, so just reset the
resampler impl instead of properly rewinding yet.
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Add a user defined parameter lfe-crossover-freq for the lfe-filter,
to pass this parameter to the lfe-filter, we need to change the
pa_resampler_new() API as well.
Signed-off-by: Hui Wang <hui.wang@canonical.com>
FSF addresses used in PA sources are no longer valid and rpmlint
generates numerous warnings during packaging because of this.
This patch changes all FSF addresses to FSF web page according to
the GPL how-to: https://www.gnu.org/licenses/gpl-howto.en.html
Done automatically by sed-ing through sources.
supresses a warning when compiling with NDEBUG:
pulsecore/aupdate.c: In function 'pa_aupdate_read_end':
pulsecore/aupdate.c:82:14: warning: variable 'n' set but not used [-Wunused-but-set-variable]
unsigned n;
pulsecore/sink-input.c: In function 'pa_sink_input_unlink':
pulsecore/sink-input.c:648:27: warning: variable 'p' set but not used [-Wunused-but-set-variable]
pa_source_output *o, *p = NULL;
pulsecore/sink-input.c: In function 'find_filter_sink_input':
pulsecore/sink-input.c:1523:14: warning: unused variable 'i' [-Wunused-variable]
unsigned i = 0;
pulsecore/sink-input.c: In function 'pa_sink_input_start_move':
pulsecore/sink-input.c:1569:27: warning: variable 'p' set but not used [-Wunused-but-set-variable]
pa_source_output *o, *p = NULL;
CC pulsecore/libpulsecore_5.0_la-sink.lo
pulsecore/sink.c: In function 'pa_sink_unlink':
pulsecore/sink.c:673:24: warning: variable 'j' set but not used [-Wunused-but-set-variable]
pa_sink_input *i, *j = NULL;
pulsecore/source-output.c: In function 'find_filter_source_output':
pulsecore/source-output.c:1179:9: warning: unused variable 'i' [-Wunused-variable]
int i = 0;
CC pulsecore/libpulsecore_5.0_la-source.lo
pulsecore/source.c: In function 'pa_source_unlink':
pulsecore/source.c:616:27: warning: variable 'j' set but not used [-Wunused-but-set-variable]
pa_source_output *o, *j = NULL;
Signed-off-by: Peter Meerwald <pmeerw@pmeerw.net>
This makes it easy to log a message every time the reference ratio
changes. I also need to add a hook for reference ratio changes, but
that need will go away if the stream relative volume controls will be
created by the core in the future.
Forcing all volume changes to go through set_volume_direct() makes
it easier to check where the stream volume is changed, and it also
allows us to have only one place where notifications for changed
volume are sent.