A bluetooth connection has significant latency compared to simple wired headphones or speakers. What's more, the connection latency can vary, depending on the properties of the bluetooth receiver and maybe even radio signal strength as the user moves around.
The interface between an application and PulseAudio can be as simple as "here's some PCM audio data; play this." But it can also be more complicated; something like "Here's some PCM audio data; play this and tell me every 50 ms how far you've got, so that I can tell you to skip ahead if it looks like you're falling out of lip-synch with the video stream I'm playing. Oh, and you'll need to resample it too, since the data has a sample rate your hardware won't directly support." In the latter case, PulseAudio needs to be able to give the application some feedback from the audio device to correctly determine how far the audio data is actually been played at any given time.
As a result, it makes sense for PulseAudio to be fairly deeply involved in Bluetooth audio processing: the more intervening layers there are, the more possibilities for data to be buffered without maintaining accurate feedback, causing lip-synch to be lost.
In fact, before PulseAudio existed, there used to be an ALSA backend for Bluetooth audio, but it was deprecated. I think the problem was that ALSA's interfaces at that time were designed mainly for traditional sound cards, and dealing with a potentially variable audio latency of Bluetooth was difficult.
PulseAudio's interfaces were designed from the ground up to handle various sound devices and even switching audio streams between them while the stream is playing, so it seems to me it has a pretty advanced concept of audio latency built-in too.
Yes, it could have been implemented in BlueZ rather than as a PulseAudio module; but then, BlueZ would have had to present an audio interface for the applications. And since PulseAudio wants to handle "all" the audio on a system (in order to be able to transfer the audio you've currently playing from speakers to Bluetooth or vice versa on-the-fly), it would have to interface with PulseAudio somehow anyway.
You are right about HSP/HFP being required for audio input. Bluetooth can be quite finicky, make sure to try forgetting the headset and repairing it.
For helping with troubleshooting, here is the output of /usr/bin/pacmd list-sources
for my blueheadset in HSP/HSF mode.
* index: 23
name: <bluez_source.00_16_94_1E_CC_05.headset_head_unit>
driver: <module-bluez5-device.c>
flags: HARDWARE HW_VOLUME_CTRL LATENCY
state: RUNNING
suspend cause: (none)
priority: 9050
volume: mono: 61166 / 93%
balance 0.00
base volume: 65536 / 100%
volume steps: 16
muted: no
current latency: 34.37 ms
max rewind: 0 KiB
sample spec: s16le 1ch 8000Hz
channel map: mono
Mono
used by: 1
linked by: 1
fixed latency: 28.00 ms
card: 9 <bluez_card.00_16_94_1E_CC_05>
module: 34
properties:
bluetooth.protocol = "headset_head_unit"
device.intended_roles = "phone"
device.description = "HD 4.40BT"
device.string = "00:16:94:1E:CC:05"
device.api = "bluez"
device.class = "sound"
device.bus = "bluetooth"
device.form_factor = "headset"
bluez.path = "/org/bluez/hci0/dev_00_16_94_1E_CC_05"
bluez.class = "0x240404"
bluez.alias = "HD 4.40BT"
device.icon_name = "audio-headset-bluetooth"
ports:
headset-input: Headset (priority 0, latency offset 0 usec, available: yes)
properties:
active port: <headset-input>
I do see that I have suspend cause: (none)
and you have suspend cause:
but that is the only difference I can notice.
FYI, when working with bluetooth sometime restarting the bluetooth service alone isn't enough. I found this works better:
sudo rfkill block bluetooth && sleep 0.1 && sudo rfkill unblock bluetooth;
Best Answer
The first problem occurs because Pulse Audio unloads the bluetooth module after startup, so even if you put it in your startup script, it still gets unloaded a few seconds later.
Solution A
Just add a startup delay in your script, something like:
Solution B (recommended)
Sorry, but I don't have a solution for your remaining two issues.