Move the function to the utility library where the enum is defined. At
same time avoid using the default clause in order to make sure the
compiler will complain if the enum type gets extended.
Similarly to the microphone gain, the speaker gain can be abstracted
inside the transport object, even though the actual D-Bus interface in
BlueZ differs.
The microphone gain represents the volume of the incoming audio stream
from the headset. This can be nicely abstracted inside the transport
object in bluetooth-util, so the modules don't have to take care about
the D-Bus details.
Move the connection of sink/source-related hooks to module
initialization and shutdown, to group all of them together. There is
no need to connect them every time the card profile is changed.
The hook is now deprecated so avoid using it and instead use the
recently introduced PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED which also
reports the disconnection event.
Add the transport-handling hooks to the centralized list of hooks in
pa_bluetooth_hook_t. These are intended to replace the now deprecated
transport-specific hook list in pa_bluetooth_transport_hook_t.
Transport objects have an associated state even though it's not
explicitly exposed in BlueZ's D-Bus API (prior to 5.0). Instead, the
state is implicitly represented in the profile-specific D-Bus interface
(i.e. org.bluez.Headset, org.bluez.AudioSink, etc.) but it can be
convenient that bluetooth-util would abstract this separation.
The old implementation is limited to parsing the profile state, but
the D-Bus API actually exposes many more properties that are currently
not being considered, specially within org.bluez.Headset.
Centralize the Bluetooth hooks in one single place, starting with
the device hooks, while removing the duplicated ones (in this case
PA_BLUETOOTH_DEVICE_HOOK_REMOVED).
The hook PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED gets fired also
when a device is being removed, so there is actually no need to have
this duplicated hook.
Devices will have zero or one transports per profile, and besides the
typical lookup is also profile-based. Therefore, replace the old hashmap
(which used the transport path as key) with a simple array which holds
a transport pointer per profile.
Path-based transport lookups are required in a discovery basis, before
the associated device is known. Therefore, it makes more sense to
maintain a hashmap in the discovery structure itself, instead of
iterating all devices.
The code can be simplified since it's just trying to round the result of
the division. Note that the resulting behavior is slightly different,
specially when the volume is 0. In this case, it will remain at 0,
instead of being set to 1.
Transports always have an associated device, so add the pointer as a
member to the structure, and remove the discovery pointer since it
already exists in the device object.
d->hfgw_state is just another profile that should be considered exactly
as the rest inside device_audio_is_ready(), which is being used to
decide if the discovery hook gets triggered.
Therefore, there seems to be no reason to make an exception for this
profile and skip checking if the condition d->audio_state !=
PA_BT_AUDIO_STATE_INVALID holds true.
This change makes no practical difference but delaying the load of the
module also for HFGW until Audio.State is received. The benefit is
that the behavior and the code are more consistent across profiles.
I was looking at a log that showed that a suspend happened (at
a strange time), but the log didn't tell me why the suspend was done.
This patch tries to make sure that that won't happen again.
With BlueZ 5 it is possible to have profile registered by a third party
process which does not share the same bus id as bluetoothd so it is
necessary to store the sender of the transport to be able to talk to it.
Note that this is backward compatible.
In some cases (typically during pairing) UUIDs might be reported by
BlueZ incrementally, that is, as soon as they have been discovered. At
this point module-bluetooth-device might already be loaded, so the late
UUID announcements need to be handled and additional card profiles
might need to be created accordingly.
The sink can be resumed while the source is still in PA_SOURCE_INIT.
This is the case if a module such as module-stream-restore routes the
audio to the sink during pa_sink_put(), leading to an inconsistent
state: the sink stays RUNNING but the transport is not actually
acquired.
When a headset is having a profile switch, we can either leave the
SCO state unmodified (as it was before this patch) or we can
alternatively request it (as older versions of PA).
This patch tries to avoid a potential regression in case a module
such as module-suspend-on-idle is not present, due to the provided
resume-on-running policy. Without this patch, and without such a policy,
the sink and sources would stay suspended until the user manually
performed another profile switch (i.e. hsp->off->hsp).
There are several other solutions currently being discussed as a longer
term solution, some of which require extendind the core. This patch is
therefore proposed as a short-term workaround to avoid the regression.
bt_transport_acquire() might get called from the main thread, in case
the IO thread hasn't been started yet. In this case, we should not call
setup_stream() since this is going to be called in the beginning of
thread_func().
If the transport is already acquired and the stream needs to be started,
call setup_stream() directly instead of bt_transport_acquire(u, TRUE).
Both calls are identical in these conditions, with the exception of the
log trace which has now been moved to setup_stream().
Given that headsets have just one single port exposing whether the
audio is streaming (playing) or not, it's not possible that
module-bluetooth-policy would distinguish A2DP/HSP cases, and thus
the automatic selection of the card profile is not deterministic.
For this reason, disable the policy entirely for headsets and focus
only on HFGW and A2DP source profiles.
Merge the former "hsp-output" and "a2dp-output" ports into one single
port, in order to fix the regression of having several independent
entries in the UI.
Without this patch, device modules will be left around after the
device has been disconnected and when they are reconnected, the
discovery module will load duplicate device module instances.
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=57239
This is a minor optimization too, but the main benefit is that it's
makes the code easier to understand (I hope), since run_callback()
won't be called at times when it's not needed.
The new helper function makes it easier to check whether any audio
profiles are connected. That information is needed by the discovery
module for deciding whether a new device module should be loaded. The
device module should use this information too to unload itself at the
right time, but that's currently not implemented.
Use a more accurate name for the function since it doesn't just check
if it is an audio device (which can be detected quite early), but it
also checks if the most relevant properties (device info, etc.) have
been received.
Besides, add the const qualifier to the pointer since it's not going to
be modified.
The Device.Connected was only used for tracking whether a device module
should be loaded, but that information is already included in the
individual profile state properties. The property can therefore be
completely ignored without any loss in functionality.
Since some devices can be chatty with regards to how often they return
from poll(), this adds a PA_UNLIKELY() to all the the rewind_requested
checks in our sink modules to make the general case (no rewind was
requested) the fast path.
UUIDs might be announced at any time, so a hook is needed to notify any
interested module. In practice, the UUIDs are quite stable with the
exception of the pairing procedure, where the UUIDs are reported by
BlueZ as soon as they are discovered.
Instead of repeatedly asking the discovery API to find a device given
our device path, let's hold a pointer to the device and make sure we
remove the reference when the hook is fired reporting that the device
has been removed. This makes the code easier to follow and slightly
more efficient.
The internal API in bluetooth-util should not use the const qualifier
for operations involving a device object. After all, the structure
contains many pointers and thus the const qualifier provides no real
protection.
Instead of repeatedly asking the discovery API to find a transport given
our transport path, let's hold a pointer to the transport and make sure
we remove the reference when the hook is fired reporting that the
transport has been removed. This makes the code easier to follow and
slightly more efficient.