mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-03-18 12:11:29 +00:00
implement #57
This commit is contained in:
@@ -1462,131 +1462,23 @@ class AirPodsService : Service() {
|
|||||||
if (oldLongPressArray.contentEquals(newLongPressArray)) {
|
if (oldLongPressArray.contentEquals(newLongPressArray)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val oldOffEnabled = oldLongPressArray[0]
|
val oldModes = mutableSetOf<LongPressMode>()
|
||||||
val oldAncEnabled = oldLongPressArray[1]
|
val newModes = mutableSetOf<LongPressMode>()
|
||||||
val oldTransparencyEnabled = oldLongPressArray[2]
|
|
||||||
val oldAdaptiveEnabled = oldLongPressArray[3]
|
|
||||||
|
|
||||||
val newOffEnabled = newLongPressArray[0]
|
if (oldLongPressArray[0]) oldModes.add(LongPressMode.OFF)
|
||||||
val newAncEnabled = newLongPressArray[1]
|
if (oldLongPressArray[1]) oldModes.add(LongPressMode.ANC)
|
||||||
val newTransparencyEnabled = newLongPressArray[2]
|
if (oldLongPressArray[2]) oldModes.add(LongPressMode.TRANSPARENCY)
|
||||||
val newAdaptiveEnabled = newLongPressArray[3]
|
if (oldLongPressArray[3]) oldModes.add(LongPressMode.ADAPTIVE)
|
||||||
|
|
||||||
|
if (newLongPressArray[0]) newModes.add(LongPressMode.OFF)
|
||||||
|
if (newLongPressArray[1]) newModes.add(LongPressMode.ANC)
|
||||||
|
if (newLongPressArray[2]) newModes.add(LongPressMode.TRANSPARENCY)
|
||||||
|
if (newLongPressArray[3]) newModes.add(LongPressMode.ADAPTIVE)
|
||||||
|
|
||||||
val changedIndex = findChangedIndex(oldLongPressArray, newLongPressArray)
|
val changedIndex = findChangedIndex(oldLongPressArray, newLongPressArray)
|
||||||
Log.d("AirPodsService", "changedIndex: $changedIndex")
|
val newEnabled = newLongPressArray[changedIndex]
|
||||||
var packet: ByteArray? = null
|
|
||||||
if (offListeningMode) {
|
|
||||||
packet = when (changedIndex) {
|
|
||||||
0 -> {
|
|
||||||
if (newOffEnabled) {
|
|
||||||
when {
|
|
||||||
oldAncEnabled && oldTransparencyEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_EVERYTHING.value
|
|
||||||
oldAncEnabled && oldTransparencyEnabled -> LongPressPackets.ENABLE_OFF_FROM_TRANSPARENCY_AND_ANC.value
|
|
||||||
oldAncEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_OFF_FROM_ADAPTIVE_AND_ANC.value
|
|
||||||
oldTransparencyEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_OFF_FROM_TRANSPARENCY_AND_ADAPTIVE.value
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when {
|
|
||||||
oldAncEnabled && oldTransparencyEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_OFF_FROM_EVERYTHING.value
|
|
||||||
oldAncEnabled && oldTransparencyEnabled -> LongPressPackets.DISABLE_OFF_FROM_TRANSPARENCY_AND_ANC.value
|
|
||||||
oldAncEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_OFF_FROM_ADAPTIVE_AND_ANC.value
|
|
||||||
oldTransparencyEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_OFF_FROM_TRANSPARENCY_AND_ADAPTIVE.value
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
1 -> {
|
val packet = determinePacket(changedIndex, newEnabled, oldModes, newModes)
|
||||||
if (newAncEnabled) {
|
|
||||||
when {
|
|
||||||
oldOffEnabled && oldTransparencyEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_EVERYTHING.value
|
|
||||||
oldOffEnabled && oldTransparencyEnabled -> LongPressPackets.ENABLE_ANC_FROM_OFF_AND_TRANSPARENCY.value
|
|
||||||
oldOffEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_ANC_FROM_OFF_AND_ADAPTIVE.value
|
|
||||||
oldTransparencyEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_OFF_FROM_TRANSPARENCY_AND_ADAPTIVE.value
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when {
|
|
||||||
oldOffEnabled && oldTransparencyEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_ANC_FROM_EVERYTHING.value
|
|
||||||
oldOffEnabled && oldTransparencyEnabled -> LongPressPackets.DISABLE_ANC_FROM_OFF_AND_TRANSPARENCY.value
|
|
||||||
oldOffEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_ANC_FROM_OFF_AND_ADAPTIVE.value
|
|
||||||
oldTransparencyEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_OFF_FROM_TRANSPARENCY_AND_ADAPTIVE.value
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
2 -> {
|
|
||||||
if (newTransparencyEnabled) {
|
|
||||||
when {
|
|
||||||
oldOffEnabled && oldAncEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_EVERYTHING.value
|
|
||||||
oldOffEnabled && oldAncEnabled -> LongPressPackets.ENABLE_TRANSPARENCY_FROM_OFF_AND_ANC.value
|
|
||||||
oldOffEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_TRANSPARENCY_FROM_OFF_AND_ADAPTIVE.value
|
|
||||||
oldAncEnabled && oldAdaptiveEnabled -> LongPressPackets.ENABLE_TRANSPARENCY_FROM_ADAPTIVE_AND_ANC.value
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when {
|
|
||||||
oldOffEnabled && oldAncEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_TRANSPARENCY_FROM_EVERYTHING.value
|
|
||||||
oldOffEnabled && oldAncEnabled -> LongPressPackets.DISABLE_TRANSPARENCY_FROM_OFF_AND_ANC.value
|
|
||||||
oldOffEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_TRANSPARENCY_FROM_OFF_AND_ADAPTIVE.value
|
|
||||||
oldAncEnabled && oldAdaptiveEnabled -> LongPressPackets.DISABLE_TRANSPARENCY_FROM_ADAPTIVE_AND_ANC.value
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
3 -> {
|
|
||||||
if (newAdaptiveEnabled) {
|
|
||||||
when {
|
|
||||||
oldOffEnabled && oldAncEnabled && oldTransparencyEnabled -> LongPressPackets.ENABLE_EVERYTHING.value
|
|
||||||
oldOffEnabled && oldAncEnabled -> LongPressPackets.ENABLE_ADAPTIVE_FROM_OFF_AND_ANC.value
|
|
||||||
oldOffEnabled && oldTransparencyEnabled -> LongPressPackets.ENABLE_ADAPTIVE_FROM_OFF_AND_TRANSPARENCY.value
|
|
||||||
oldAncEnabled && oldTransparencyEnabled -> LongPressPackets.ENABLE_ADAPTIVE_FROM_TRANSPARENCY_AND_ANC.value
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when {
|
|
||||||
oldOffEnabled && oldAncEnabled && oldTransparencyEnabled -> LongPressPackets.DISABLE_ADAPTIVE_FROM_EVERYTHING.value
|
|
||||||
oldOffEnabled && oldAncEnabled -> LongPressPackets.DISABLE_ADAPTIVE_FROM_OFF_AND_ANC.value
|
|
||||||
oldOffEnabled && oldTransparencyEnabled -> LongPressPackets.DISABLE_ADAPTIVE_FROM_OFF_AND_TRANSPARENCY.value
|
|
||||||
oldAncEnabled && oldTransparencyEnabled -> LongPressPackets.DISABLE_ADAPTIVE_FROM_TRANSPARENCY_AND_ANC.value
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when (changedIndex) {
|
|
||||||
1 -> {
|
|
||||||
packet = if (newLongPressArray[1]) {
|
|
||||||
LongPressPackets.ENABLE_EVERYTHING_OFF_DISABLED.value
|
|
||||||
} else {
|
|
||||||
LongPressPackets.DISABLE_ANC_OFF_DISABLED.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
2 -> {
|
|
||||||
packet = if (newLongPressArray[2]) {
|
|
||||||
LongPressPackets.ENABLE_EVERYTHING_OFF_DISABLED.value
|
|
||||||
} else {
|
|
||||||
LongPressPackets.DISABLE_TRANSPARENCY_OFF_DISABLED.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
3 -> {
|
|
||||||
packet = if (newLongPressArray[3]) {
|
|
||||||
LongPressPackets.ENABLE_EVERYTHING_OFF_DISABLED.value
|
|
||||||
} else {
|
|
||||||
LongPressPackets.DISABLE_ADAPTIVE_OFF_DISABLED.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
packet?.let {
|
packet?.let {
|
||||||
Log.d("AirPodsService", "Sending packet: ${it.joinToString(" ") { "%02X".format(it) }}")
|
Log.d("AirPodsService", "Sending packet: ${it.joinToString(" ") { "%02X".format(it) }}")
|
||||||
sendPacket(it)
|
sendPacket(it)
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* AirPods like Normal (ALN) - Bringing Apple-only features to Linux and Android for seamless AirPods functionality!
|
* AirPods like Normal (ALN) - Bringing Apple-only features to Linux and Android for seamless AirPods functionality!
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 Kavish Devar
|
* Copyright (C) 2024 Kavish Devar
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as published
|
* it under the terms of the GNU Affero General Public License as published
|
||||||
* by the Free Software Foundation, either version 3 of the License.
|
* by the Free Software Foundation, either version 3 of the License.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Affero General Public License for more details.
|
* GNU Affero General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@@ -241,47 +241,36 @@ class Capabilities {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class LongPressPackets(val value: ByteArray) {
|
enum class LongPressMode {
|
||||||
ENABLE_EVERYTHING(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0F, 0x00, 0x00, 0x00)),
|
OFF, TRANSPARENCY, ADAPTIVE, ANC
|
||||||
|
}
|
||||||
|
|
||||||
DISABLE_OFF_FROM_EVERYTHING(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0e, 0x00, 0x00, 0x00)),
|
data class LongPressPacket(val modes: Set<LongPressMode>) {
|
||||||
DISABLE_OFF_FROM_TRANSPARENCY_AND_ADAPTIVE(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0c, 0x00, 0x00, 0x00)),
|
val value: ByteArray
|
||||||
DISABLE_OFF_FROM_TRANSPARENCY_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x06, 0x00, 0x00, 0x00)),
|
get() {
|
||||||
DISABLE_OFF_FROM_ADAPTIVE_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0a, 0x00, 0x00, 0x00)),
|
val baseArray = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A)
|
||||||
|
val modeByte = calculateModeByte()
|
||||||
|
return baseArray + byteArrayOf(modeByte, 0x00, 0x00, 0x00)
|
||||||
|
}
|
||||||
|
|
||||||
ENABLE_OFF_FROM_TRANSPARENCY_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x07, 0x00, 0x00, 0x00)),
|
private fun calculateModeByte(): Byte {
|
||||||
ENABLE_OFF_FROM_ADAPTIVE_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0b, 0x00, 0x00, 0x00)),
|
var modeByte: Byte = 0x00
|
||||||
ENABLE_OFF_FROM_TRANSPARENCY_AND_ADAPTIVE(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0d, 0x00, 0x00, 0x00)),
|
modes.forEach { mode ->
|
||||||
|
modeByte = when (mode) {
|
||||||
|
LongPressMode.OFF -> (modeByte + 0x01).toByte()
|
||||||
|
LongPressMode.TRANSPARENCY -> (modeByte + 0x02).toByte()
|
||||||
|
LongPressMode.ADAPTIVE -> (modeByte + 0x04).toByte()
|
||||||
|
LongPressMode.ANC -> (modeByte + 0x08).toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modeByte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DISABLE_TRANSPARENCY_FROM_EVERYTHING(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0b, 0x00, 0x00, 0x00)),
|
fun determinePacket(changedIndex: Int, newEnabled: Boolean, oldModes: Set<LongPressMode>, newModes: Set<LongPressMode>): ByteArray? {
|
||||||
DISABLE_TRANSPARENCY_FROM_OFF_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x03, 0x00, 0x00, 0x00)),
|
return if (newEnabled) {
|
||||||
DISABLE_TRANSPARENCY_FROM_ADAPTIVE_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0a, 0x00, 0x00, 0x00)),
|
LongPressPacket(oldModes + newModes.elementAt(changedIndex)).value
|
||||||
DISABLE_TRANSPARENCY_FROM_OFF_AND_ADAPTIVE(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x09, 0x00, 0x00, 0x00)),
|
} else {
|
||||||
|
LongPressPacket(oldModes - newModes.elementAt(changedIndex)).value
|
||||||
ENABLE_TRANSPARENCY_FROM_OFF_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x07, 0x00, 0x00, 0x00)),
|
}
|
||||||
ENABLE_TRANSPARENCY_FROM_ADAPTIVE_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0e, 0x00, 0x00, 0x00)),
|
}
|
||||||
ENABLE_TRANSPARENCY_FROM_OFF_AND_ADAPTIVE(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0d, 0x00, 0x00, 0x00)),
|
|
||||||
|
|
||||||
DISABLE_ANC_FROM_EVERYTHING(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0D, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_ANC_FROM_OFF_AND_TRANSPARENCY(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x05, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_ANC_FROM_ADAPTIVE_AND_TRANSPARENCY(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0c, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_ANC_FROM_OFF_AND_ADAPTIVE(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x09, 0x00, 0x00, 0x00)),
|
|
||||||
|
|
||||||
ENABLE_ANC_FROM_OFF_AND_TRANSPARENCY(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x07, 0x00, 0x00, 0x00)),
|
|
||||||
ENABLE_ANC_FROM_ADAPTIVE_AND_TRANSPARENCY(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0e, 0x00, 0x00, 0x00)),
|
|
||||||
ENABLE_ANC_FROM_OFF_AND_ADAPTIVE(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0b, 0x00, 0x00, 0x00)),
|
|
||||||
|
|
||||||
DISABLE_ADAPTIVE_FROM_EVERYTHING(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x07, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_ADAPTIVE_FROM_OFF_AND_TRANSPARENCY(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x05, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_ADAPTIVE_FROM_TRANSPARENCY_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x06, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_ADAPTIVE_FROM_OFF_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x03, 0x00, 0x00, 0x00)),
|
|
||||||
|
|
||||||
ENABLE_ADAPTIVE_FROM_OFF_AND_TRANSPARENCY(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0d, 0x00, 0x00, 0x00)),
|
|
||||||
ENABLE_ADAPTIVE_FROM_TRANSPARENCY_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0e, 0x00, 0x00, 0x00)),
|
|
||||||
ENABLE_ADAPTIVE_FROM_OFF_AND_ANC(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0b, 0x00, 0x00, 0x00)),
|
|
||||||
|
|
||||||
ENABLE_EVERYTHING_OFF_DISABLED(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0E, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_TRANSPARENCY_OFF_DISABLED(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0A, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_ADAPTIVE_OFF_DISABLED(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x06, 0x00, 0x00, 0x00)),
|
|
||||||
DISABLE_ANC_OFF_DISABLED(byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x09, 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x00)),
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user