Make a new softVolume property that contains only the soft volume
to apply.
In the case of HW/SW volume, we pass the real volume in the
channelVolume and the leftover volume in softVolume. We don't
use the monitorVolume for this anymore because it is a completely
separate volume handled by the merger node.
This way, channelVolume always represents the effective volume
set on routes, channelmix and merger and only the softVolume (when
available) is applied as software volume by channelmix.
This makes things map a bit better to what is actually happening with
the real volume and leftover software volumes after applying the
hardware volumes in the device.
With this change, the volume on the monitor is not affected by the
sink volume anymore and we can use the monitorVolume for this later.
This also means that the monitor volume in pavucontrol of the sinks
does not change when the sink volume changes. PulseAudio is inconsistent
here: If the volume is HW, the monitor volume is not affected, if the
volume is SW, it is. In PipeWire there is an option in merger to
let the volume affect the monitor with monitor.channel-volumes = true.
To set the io on the mixer ports, we need to use the same id that
was used to add the port, not the id we use to identify the mixer
structure.
Fixes#759
Only implement the null echo cancel implementation for now.
And skeleton webrtc echo cancel implementation
It uses 4 streams arranged as:
input ---+---> source
^
|
sink ---+---> output
The output of the source is the filtered input of the input stream
(linked a master source) based on the data going from sink to
the output (linked to a master sink).
All streams are arranged in the same group so that the echo canceler
does not have to deal with clock drift. For echo cancelers that can
handle clock drift we might want place the source and sink chains
in different groups.
Pass properties as global properties so that they are applied
to both streams. Make sure node.name is set on both streams so that
they look good in tools like carla.
Do not return an error immediately if connect() fails with EAGAIN. Check
if it completed successfully with getsockopt() when the socket becomes
writable instead.
This is the way to handle non-blocking connect() by the book but after
testing it seems that the case when connect() fails with EAGAIN is when
the listen backlog is full on the server side and in that case the
server socket is closed. So even though connect() completes successfully
according to getsockopt() the client socket is no longer usable
(on_remote_data() will get both SPA_IO_OUT and SPA_IO_HUP in mask on the
first call after connect() returned EAGAIN).
Make it possible to specify different channels and positions
per stream so that we can do remapping as well.
Make sure we only copy available input channels and set the remaining
channels empty.
Handle error when loading and fix leaks.
Mark streams as virtual if nothing else is specified.
Try to reuse an existing core connection if possible.
unload the module when the core is in error or when it is destroyed.
When deciding on the number of channels to use for the node,
ignore parsing the sample rate. This makes it possible to activate the
node with a missing rate property, like when the node can do all
possible rates.
Use the default backlog size, SOMAXCONN (128), which is the same as for
the unix socket in module-protocol-native. If the backlog queue gets
full incoming connections will be closed before they can be accepted.
This causes connect() to fail with EAGAIN on the client side and since
the server socket is closed it will not be possible to use the client
socket further.
Use the context work queue to schedule destroys from callbacks.
This is better because we can pass the destroyed object around and
implement just the action we need to do on it.
Make a method to get a work-queue from the context. There is one
work-queue to use and the context will allocate it when requested
and free when destroyed.
The work queue is handy to delay execution of some logic for later,
either in the next iteration of the main-loop or when an async
operation completed.
Export some work-queue methods.
Make a null-sink with monitor.channel-volumes=true by default if not
defined otherwise. This ensures the volume of the null-sink is
always transfered to the monitor ports.
Also only set the object.linger flag when undefined.
If we have channels and channelmap, make sure they match.
If we have only channel_map, use this to derive channels instead of
taking the default number of channels and then ending up with a
mismatch.
If we have only channels, use this to generate a channelmap from
predefined maps or just unknown channels instead of taking the default
channel map.
If neither channels or channelmap is defined, use the defaults.
Move the icon we get from bluez to a separate property, it is not
a good icon to show.
Copy form factor from device to node properties.
Set device.bus in the device properties and copy it to the node
properties.
Use form factor and bus to make a nice icon-name for the node and
device.
Fixes#1064