Let device module figure out the priority based on the state of the
profiles.
Note that most likely all profiles will be in PA_BT_AUDIO_STATE_CONNECTED
state so 'Off' will be the initial profile then it is up to the policy
module to switch to the most suitable profile.
Add support for hfgw card profile in module-bluetooth-policy, just like
a2dp_source is handled.
In this case also the sink needs to be connected using module-loopback.
Instead of focusing on a2dp_source only, prepare the module to support
several profiles. It will be possible to enable/disable each of them
using module arguments.
Property bluetooth.protocol did make a distinction between A2DP sink and
source roles but on the contrary did not separate HFP roles (headset vs
gateway). For consistency, they should both behave similarly.
This automatically fixes another incosistency: the HFGW (or HSP) sink
was set to bluetooth.protocol="sco", while the source was set to "hsp".
There is no use for this distinction, since the protocol (including the
role) is the same.
Profile a2dp_source, just like any other card profile, should have
state guards when the profile is being changed. If the BlueZ interface
is not connected, the profile should be set to "off".
The return value of dbus_message_iter_next() doesn't need to be checked
since the while condition will be false anyway (arg type will be
DBUS_TYPE_INVALID).
The method ListDevices() in org.bluez.Adapter was deprecated in BlueZ
4.61, and is going to be removed in future releases. Instead, a property
was introduced for this purpose in BlueZ 4.7.
The method ListAdapters() in org.bluez.Manager was deprecated in BlueZ
4.61, and is going to be removed in future releases. Instead, a property
was introduced for this purpose in BlueZ 4.22.
The module module-bluetooth-device should never be given parameter
'profile' twice, even if both HFGW and A2DP are playing. This patch
proposed to consider HFGW first.
This simplifies the code a lot, in favour of the D-Bus Media interface
in BlueZ. The old socket-based IPC mechanism has been deprecated and is
about to be removed soon.
I know that pa_streq() is defined with an extra parenthesis, but everytime I
look at it, it makes me nervous. :D
So it's better to add the parenthesis here.
This is a basic module for enabling loopback as soon as a new bluetooth A2DP
source is created. The module is given a source and a media role using command
line. This allows module-intended-roles or module-device-manager to choose a
target sink for the stream.
In practice there is always at least one profile, and I
don't think there will ever be cards without profiles.
Therefore, I added assertions to pa_card_new() stating that
the card new data must always contain at least one profile.
Now a lot of code can be simplified, because it's guaranteed
that the profiles hashmap and the active_profile field are
always non-NULL.
PropertyChanged signal of org.BlueZ.MediaTransport is processed in
pa_bluetooth_transport_parse_property() which updates t->nrec.
This is called by :
- First by filter_cb() of bluetooth-util.c
- Then by filter_cb() of module-bluetooth-device.c which retrieve value
of t->nrec before calling parse function, then it checks if t->nrec
has changed before updating bluetooth.nrec property.
As t->nrec has alreday been changed during first process, property
update is never performed.
This patch creates a new hook in pa_bluetooth_transport called
PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED.
The hook is fired by bluetooth-util.c when the transport's NREC
property changes.
module-bluetooth-device.c won't listen the PropertyChanged signal of
MediaTransport anymore. Instead, it will use the hook in
pa_bluetooth_transport to get a notification when the NREC property
changes, and update the sink or source proplist accordingly.
const qualifier for returned pointer of
pa_bluetooth_discovery_get_transport() is removed.
The bluetooth device should have ports so we can attach a latency to
the ports.
Every profile (a2dp, hsp...) has his own set of ports depending on the
number of sinks and sources it provides.
When a Bluetooth headset is connected only to HFP profile (not connected
to A2DP) and host streams to it, a crash occurs if host disconnects.
When HFP disconnects, audio thread will fail on POLLHUP then generate
a message to set PA profile to Off before ending.
If this message is managed before PA unload bluetooth device module,
all works fine.
But, if this message is managed during module unload, this finish by
re-entrance in release code (stop_thread) and a crash.
This fix prevents to process profile change when module is unloading.
pa_bool_t and dbus_bool_t cannot be used interchangably since their size
might (and do) vary. This caused a crash on some systems which was
reported and root caused by: Aidan Thornton <makosoft@googlemail.com>.
Ref: https://bugs.gentoo.org/show_bug.cgi?id=398097
The original intention of this code was probably that if
adding filter1 succeeded but adding filter2 failed, then
filter1 should be removed so that either both or none of the
filters get added.
We didn't do anything anyway in case of failures. When we
give NULL as the error, dbus_bus_remove_match() can act
asynchronously, so it becomes faster. Also, the bus daemon
can avoid sending any replies, which reduces the amount of
traffic.
Allow module-bluetooth-device to listens to HandsfreeGateway state
changes using DBUS signals. When an handsfree connects, module-bluetooth-device
is loaded and goes to playing state. When the handsfree disconnect audio,
the card profile is set to "off". If the headset connects audio again after
that, the card profile should switch to "hfgw" again to match state of audio
connection.
If card profile is set to "off", the audio stream should be released.
Current implementation releases the stream when the card profile
is changed to "hsp" or "hfgw" again and immediatly reconnects after that.
This happens in the following scenario :
An HandsfreeGateway connects RFCOMM and then SCO. A card appears in
PA and can be used. If for some reason, SCO is disconnected,
module-bluetooth-device is unloaded. The card will disappear, even
if RFCOMM is still connected. After that, it is not possible to
connect SCO again from PA.
This patch will add the necessary quirks so that pulseaudio can register
an endpoint on the /MediaEndpoint/HFPHS path. This endpoint is to be
used for HFP Handsfree profile.
The "(((audio_sample << 1) | 1) << frame->scale_factor[ch][sb])"
part of expression
"frame->sb_sample[blk][ch][sb] =
(((audio_sample << 1) | 1) << frame->scale_factor[ch][sb]) /
levels[ch][sb] - (1 << frame->scale_factor[ch][sb])"
in "sbc_unpack_frame" function can sometimes overflow 32-bit signed int.
This problem can be reproduced by first using bitpool 128 and encoding
some random noise data, and then feeding it to sbc decoder. The obvious
thing to do would be to change "audio_sample" variable type to uint32_t.
However the problem is a little bit more complicated. According
to the section "12.6.2 Scale Factors" of A2DP spec:
scalefactor[ch][sb] = pow(2.0, (scale_factor[ch][sb] + 1))
And according to "12.6.4 Reconstruction of the Subband Samples":
sb_sample[blk][ch][sb] = scalefactor[ch][sb] *
((audio_sample[blk][ch][sb]*2.0+1.0) / levels[ch][sb]-1.0);
Hence the current code for calculating "sb_sample[blk][ch][sb]" is
not quite correct, because it loses one least significant bit of
sample data and passes twice smaller sample values to the synthesis
filter (the filter also deviates from the spec to compensate this).
This all has quite a noticeable impact on audio quality. Moreover,
it makes sense to keep a few extra bits of precision here in order
to minimize rounding errors. So the proposed patch introduces a new
SBCDEC_FIXED_EXTRA_BITS constant and uses uint64_t data type
for intermediate calculations in order to safeguard against
overflows. This patch intentionally addresses only the quality
issue, but performance can be also improved later (like replacing
division with multiplication by reciprocal).
Test for the difference of sbc encoding/decoding roundtrip vs.
the original audio file for joint stereo, bitpool 128, 8 subbands
and http://media.xiph.org/sintel/sintel-master-st.flac sample
demonstrates some quality improvement:
=== before ===
--- comparing original / sbc_encoder.exe + sbcdec ---
stddev: 4.64 PSNR: 82.97 bytes:170495708/170496000
=== after ===
--- comparing original / sbc_encoder.exe + sbcdec ---
stddev: 1.95 PSNR: 90.50 bytes:170495708/170496000
The header files with constants and structures for audio specific
interaction with Pulseaudio are suppose to be under LGPL license.
For some odd reason a2dp-codecs.h ended up being under GPL license
which is against the intention of this being shared and re-used by
non-GPL programs. Fix this now to avoid any future confusion.