diff --git a/android/app/src/main/java/me/kavishdevar/librepods/screens/AppSettingsScreen.kt b/android/app/src/main/java/me/kavishdevar/librepods/screens/AppSettingsScreen.kt index 06949ad..6f2ce0d 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/screens/AppSettingsScreen.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/screens/AppSettingsScreen.kt @@ -179,6 +179,10 @@ fun AppSettingsScreen(navController: NavController) { mutableStateOf(sharedPreferences.getBoolean("takeover_when_media_start", true)) } + var useAlternateHeadTrackingPackets by remember { + mutableStateOf(sharedPreferences.getBoolean("use_alternate_head_tracking_packets", false)) + } + var mDensity by remember { mutableFloatStateOf(0f) } fun validateHexInput(input: String): Boolean { @@ -1040,6 +1044,47 @@ fun AppSettingsScreen(navController: NavController) { } } + Row( + modifier = Modifier + .fillMaxWidth() + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() } + ) { + useAlternateHeadTrackingPackets = !useAlternateHeadTrackingPackets + sharedPreferences.edit().putBoolean("use_alternate_head_tracking_packets", useAlternateHeadTrackingPackets).apply() + }, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + .padding(vertical = 8.dp) + .padding(end = 4.dp) + ) { + Text( + text = "Use alternate head tracking packets", + fontSize = 16.sp, + color = textColor + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = "Enable this if head tracking doesn't work for you. This sends different data to AirPods for requesting/stopping head tracking data.", + fontSize = 14.sp, + color = textColor.copy(0.6f), + lineHeight = 16.sp, + ) + } + + StyledSwitch( + checked = useAlternateHeadTrackingPackets, + onCheckedChange = { + useAlternateHeadTrackingPackets = it + sharedPreferences.edit().putBoolean("use_alternate_head_tracking_packets", it).apply() + } + ) + } + Row( modifier = Modifier .fillMaxWidth() diff --git a/android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt b/android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt index d20e924..1cb5960 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt @@ -1068,7 +1068,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList if (isInCall) return if (config.headGestures) { initGestureDetector() - aacpManager.sendStartHeadTracking() + startHeadTracking() gestureDetector?.startDetection { accepted -> if (accepted) { answerCall() @@ -2131,12 +2131,22 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList fun startHeadTracking() { isHeadTrackingActive = true - aacpManager.sendStartHeadTracking() + val useAlternatePackets = sharedPreferences.getBoolean("use_alternate_head_tracking_packets", false) + if (useAlternatePackets) { + aacpManager.sendDataPacket(aacpManager.createAlternateStartHeadTrackingPacket()) + } else { + aacpManager.sendStartHeadTracking() + } HeadTracking.reset() } fun stopHeadTracking() { - aacpManager.sendStopHeadTracking() + val useAlternatePackets = sharedPreferences.getBoolean("use_alternate_head_tracking_packets", false) + if (useAlternatePackets) { + aacpManager.sendDataPacket(aacpManager.createAlternateStopHeadTrackingPacket()) + } else { + aacpManager.sendStopHeadTracking() + } isHeadTrackingActive = false } diff --git a/android/app/src/main/java/me/kavishdevar/librepods/utils/AACPManager.kt b/android/app/src/main/java/me/kavishdevar/librepods/utils/AACPManager.kt index 4ec3baf..82f7395 100644 --- a/android/app/src/main/java/me/kavishdevar/librepods/utils/AACPManager.kt +++ b/android/app/src/main/java/me/kavishdevar/librepods/utils/AACPManager.kt @@ -370,6 +370,14 @@ class AACPManager { return opcode + data } + fun createAlternateStartHeadTrackingPacket(): ByteArray { + val opcode = byteArrayOf(Opcodes.HEADTRACKING, 0x00) + val data = byteArrayOf( + 0x00, 0x00, 0x10, 0x00, 0x0F, 0x00, 0x08, 0x73, 0x42, 0x0B, 0x08, 0x10, 0x10, 0x02, 0x1A, 0x05, 0x01, 0x40, 0x9C.toByte(), 0x00, 0x00 + ) + return opcode + data + } + fun sendStopHeadTracking(): Boolean { return sendDataPacket(createStopHeadTrackingPacket()) } @@ -382,6 +390,14 @@ class AACPManager { return opcode + data } + fun createAlternateStopHeadTrackingPacket(): ByteArray { + val opcode = byteArrayOf(Opcodes.HEADTRACKING, 0x00) + val data = byteArrayOf( + 0x00, 0x00, 0x10, 0x00, 0x0F, 0x00, 0x08, 0x75, 0x42, 0x0B, 0x08, 0x10, 0x10, 0x02, 0x1A, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00 + ) + return opcode + data + } + fun sendRename(name: String): Boolean { return sendDataPacket(createRenamePacket(name)) }