Skip to content

Commit 0d3bf2d

Browse files
committed
fix play/previous/next
1 parent 6d1104e commit 0d3bf2d

1 file changed

Lines changed: 39 additions & 2 deletions

File tree

‎app/src/main/java/com/mg4/control/hardware/MG4Hardware.kt‎

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3907,6 +3907,43 @@ object MG4Hardware {
39073907
}
39083908
}
39093909

3910+
/**
3911+
* CarPlay / Android Auto joue-t-il ? `null` si on ne peut pas conclure.
3912+
*
3913+
* `getLastCpAaAudioInfoBean` (tx 0x7) rend un `AudioInfoBean` dont le champ `mPlayState`
3914+
* vaut 3 en lecture — la carte média du launcher le compare à cette valeur exacte. Il faut
3915+
* dérouler le bean dans l'ordre de son `writeToParcel` : id(long), durée(long), puis sept
3916+
* chaînes, deux longs, une chaîne, et enfin **l'état(int)**.
3917+
*
3918+
* Sans cette lecture, la projection retombait sur `isMusicActive`, qui reste vrai deux à
3919+
* trois secondes après une pause : le raccourci renvoyait une pause au lieu d'une reprise,
3920+
* et il fallait patienter avant que la bascule redevienne possible.
3921+
*/
3922+
private fun cpAaEnLecture(): Boolean? {
3923+
val binder = serviceBinder(ACT_CPAA, MEDIA_PKG, MEDIA_CLS) ?: return null
3924+
val data = Parcel.obtain()
3925+
val reply = Parcel.obtain()
3926+
return try {
3927+
data.writeInterfaceToken(DESC_CPAA)
3928+
binder.transact(0x7, data, reply, 0)
3929+
reply.readException()
3930+
if (reply.readInt() == 0) return null // bean nul : rien à conclure
3931+
reply.readLong(); reply.readLong() // id, durée
3932+
repeat(7) { reply.readString() } // nom, pochette, chemin, artiste, utilisateur, avatar, album
3933+
reply.readLong(); reply.readLong() // ajout, dernière lecture
3934+
reply.readString() // position lisible
3935+
val etat = reply.readInt()
3936+
AppLogger.i(MEDIA_TAG, "état projection = $etat ($PLAYER_STATUS_START = en lecture)")
3937+
etat == PLAYER_STATUS_START
3938+
} catch (e: Exception) {
3939+
AppLogger.w(MEDIA_TAG, "état projection illisible : ${(e.cause ?: e).message}")
3940+
null
3941+
} finally {
3942+
data.recycle()
3943+
reply.recycle()
3944+
}
3945+
}
3946+
39103947
/** Source audio réellement active, ou -1 si le service SAIC ne répond pas. */
39113948
private fun mediaSourceCourante(): Int {
39123949
val v = mediaLireInt(ACT_STATUS, DESC_STATUS, 0x9) ?: return -1 // getCurrentMediaSource
@@ -3928,6 +3965,8 @@ object MG4Hardware {
39283965
SRC_BT -> mediaLireInt(ACT_BT, DESC_BT, 0x9)?.let { it != 0 }
39293966
// getPlayerStatus : un état parmi PLAYER_STATUS_*.
39303967
SRC_ONLINE -> mediaLireInt(ACT_ONLINE, DESC_ONLINE, 0x6)?.let { it == PLAYER_STATUS_START }
3968+
// La projection expose son état dans son bean, pas par un getter direct.
3969+
SRC_CARPLAY, SRC_AA -> cpAaEnLecture()
39313970
else -> null
39323971
}
39333972
if (reel != null) {
@@ -4036,8 +4075,6 @@ object MG4Hardware {
40364075
cible == SRC_CARPLAY || cible == SRC_AA -> mediaTransact(ACT_CPAA, DESC_CPAA, when (cmd) {
40374076
CmdMedia.SUIVANT -> 4
40384077
CmdMedia.PRECEDENT -> 3
4039-
// La projection n'expose pas son état : isMusicActive est le seul indice, et il
4040-
// suffit ici — il retombe à faux quand la lecture s'arrête vraiment.
40414078
CmdMedia.LECTURE_PAUSE -> if (enLecture(cible)) 2 else 1
40424079
})
40434080

0 commit comments

Comments
 (0)