447ad35585 broken the default volume
controls because there were no instances of the nodes yet.
Fix this by always storing the control value in the first instance and
then duplicating it when we make other instances.
See #3434
Don't directly update the offset when not running. The running time
is position - offset and stays constant when not running.
Instead keep an extra elapsed variable that is updated when the state
is running. The offset is then always posision - elapsed. This is more
reliable and can compensate for jumps in the position timestamps.
Fixes#3544
See #3189
Do the volume settings after we have parsed all the properties.
Sync softMute with mute and set softVolume to 0.0 when the channelVolume
is zero (or muted).
See #3434
Scale the volume with min/max values.
Actually set the softMute and softVolume to false/1.0 and proxy the mute
and channelVolumes as they are.
Don't do anything special when we don't have custom volume ports.
See #3434
Use both the volume and mute to decide what volume to send.
Don't let the mute state overwrite the volume. Also never mute the
stream.
Pressing mute and unmute restores the previous volume this way.
The volume interval that RAOP devices understand is [-30,0],
where -30.0 equals min vol, and 0.0 equals max. vol.
The local system volume is represented as a cubic (volumetric)
value in the [0,1] interval.
So cube root system volume value, scale by 30 and
translate -30 to map to target output range.
The special value -144 denotes volume mute. Send a corresponding RTSP
message when mute is not already toggled on.
Set `pulse.module.id` on every node that libpipewire-module-echo-cancel
creates so that one can see in the output of `pactl list {sinks,sources}`
which nodes were created by a particular instance of module-echo-cancel.
Fixes#3541
Add nofail flags to some filter-chain examples to avoid aborting on
startup and leaving the system in a silent state.
Add some more comments to guide people to change the paths to the
filters and config files where needed.
When we are operating in passthrough, let the Start command pass through
to the follower in all cases. Only do the negotiate/buffers when not in
passthrough.
This fixes a case where the buffers are cleared on the alsa node and it
Pauses but then never resumes in a Start because the node is already
started. The real problem is probably somewhere else (in PipeWire) but
for now this will improve things in passthrough.
We only start the ALSA pcm after we get our first buffer.
We still need to do the sync through (and get the number of prefilled
samples) to make sure we set our new timeout and don't keep on waking
up quickly while the graph fetches the first buffer.
To find the largest rate, we need to select the smallest fraction.
This fixes the case where 44100Hz was selected when there are 2 nodes,
one suggesting 44.1Khz and another 48Khz. After this, 48KHz is
selected.
There is no need to have an extra pointer in the struct that is
set to right after the object at initialization and is never modified
because a flexible array member can be used instead.
This has advantages: `struct message` is now smaller, and there is
no extra load when accessing `struct message::data`.
When we duplicate the filter, also duplicate the control values instead
of reusing the same value for all copies. We then duplicate the value
ourselves when setting a control. This makes it possible to later use
this for volume control.
This will call the process function as soon as a new buffer is dequeued.
This can be used to keep the buffer at a certain fill level instead of
the minimal fill level without the flag.
Fixes#3480
If remote supports both HFP HF and AG, both may get connected, which
occurs with Pipewire<->Pipewire connection. In this case, Pipewire on
both sides may pick the audio-gateway profile.
To avoid both sides being audio-gateway, if remote is both A2DP sink and
HF, use lower priority for the audio-gateway profile. Generally, BlueZ
won't connect both A2DP Source and Sink between same devices at the same
time, so we use that to determine which side should be the receiver.
It may occur that we have RFCOMM connected as both HF and AG. The codec
switching and support checks should in this case always use the remote
HF RFCOMM.
Fix by finding the RFCOMM with the correct profile, remote as HF.