linux: improve conversation detect logging (#302)

media: correct AirPods conversational awareness state handling

Fix incorrect detection of conversational awareness events. The previous
implementation treated all non-0x01 packets as "disabled", which caused
wrong behavior when the user manually enabled/disabled the feature or when
voice-end events were received.

Adds full decoding for packet types:
 - 0x01 → voice detected
 - 0x06/others → voice ended
 - 0x08 → feature disabled
 - 0x09 → feature enabled

Signed-off-by: ozan956 <ozandurgut.2001@hotmail.com>
This commit is contained in:
Ozan Durgut
2025-11-22 20:12:00 +01:00
committed by GitHub
parent 10bf2fe68c
commit 574c193a6d

View File

@@ -101,40 +101,54 @@ bool MediaController::isActiveOutputDeviceAirPods() {
} }
void MediaController::handleConversationalAwareness(const QByteArray &data) { void MediaController::handleConversationalAwareness(const QByteArray &data) {
LOG_DEBUG("Handling conversational awareness data: " << data.toHex()); if (data.size() < 10) {
bool lowered = data[9] == 0x01; LOG_ERROR("Invalid conversational awareness packet");
LOG_INFO("Conversational awareness: " << (lowered ? "enabled" : "disabled"));
if (lowered) {
if (initialVolume == -1 && isActiveOutputDeviceAirPods()) {
QString defaultSink = m_pulseAudio->getDefaultSink();
initialVolume = m_pulseAudio->getSinkVolume(defaultSink);
if (initialVolume == -1) {
LOG_ERROR("Failed to get initial volume");
return; return;
}
LOG_DEBUG("Initial volume: " << initialVolume << "%");
} }
QString defaultSink = m_pulseAudio->getDefaultSink();
int targetVolume = initialVolume * 0.20; uint8_t flag = (uint8_t)data[9];
if (m_pulseAudio->setSinkVolume(defaultSink, targetVolume)) {
LOG_INFO("Volume lowered to 0.20 of initial which is " << targetVolume << "%"); switch (flag) {
} else { case 0x01:
LOG_ERROR("Failed to lower volume"); LOG_INFO("Conversational awareness event: voice detected");
if (initialVolume == -1 && isActiveOutputDeviceAirPods()) {
QString sink = m_pulseAudio->getDefaultSink();
initialVolume = m_pulseAudio->getSinkVolume(sink);
LOG_DEBUG("Initial volume saved: " << initialVolume << "%");
}
if (initialVolume != -1) {
QString sink = m_pulseAudio->getDefaultSink();
int target = initialVolume * 0.20;
m_pulseAudio->setSinkVolume(sink, target);
LOG_INFO("Volume lowered to " << target << "%");
}
break;
case 0x08:
LOG_INFO("Conversational awareness disabled");
initialVolume = -1;
break;
case 0x09:
LOG_INFO("Conversational awareness enabled");
break;
default:
LOG_INFO("Conversational awareness event: voice ended");
if (initialVolume != -1 && isActiveOutputDeviceAirPods()) {
QString sink = m_pulseAudio->getDefaultSink();
m_pulseAudio->setSinkVolume(sink, initialVolume);
LOG_INFO("Volume restored to " << initialVolume << "%");
initialVolume = -1;
}
break;
} }
} else {
if (initialVolume != -1 && isActiveOutputDeviceAirPods()) {
QString defaultSink = m_pulseAudio->getDefaultSink();
if (m_pulseAudio->setSinkVolume(defaultSink, initialVolume)) {
LOG_INFO("Volume restored to " << initialVolume << "%");
} else {
LOG_ERROR("Failed to restore volume");
}
initialVolume = -1;
}
}
} }
bool MediaController::isA2dpProfileAvailable() { bool MediaController::isA2dpProfileAvailable() {
if (m_deviceOutputName.isEmpty()) { if (m_deviceOutputName.isEmpty()) {
return false; return false;