Add one-pod mode for reactions

This commit is contained in:
darken
2022-01-24 15:29:05 +01:00
parent 38bc3be5b7
commit c5b1c417a4
8 changed files with 77 additions and 11 deletions
@@ -0,0 +1,15 @@
package eu.darken.capod.pods.core
interface HasDualEarDetection : HasEarDetection {
val isLeftPodInEar: Boolean
val isRightPodInEar: Boolean
val isEitherPodInEar: Boolean
get() = isLeftPodInEar || isRightPodInEar
override val isBeingWorn: Boolean
get() = isLeftPodInEar && isRightPodInEar
}
@@ -8,11 +8,11 @@ import eu.darken.capod.common.isBitSet
import eu.darken.capod.common.lowerNibble
import eu.darken.capod.common.upperNibble
import eu.darken.capod.pods.core.HasCase
import eu.darken.capod.pods.core.HasDualEarDetection
import eu.darken.capod.pods.core.HasDualPods
import eu.darken.capod.pods.core.HasDualPods.Pod
import eu.darken.capod.pods.core.HasEarDetection
interface DualApplePods : ApplePods, HasDualPods, HasEarDetection, HasCase {
interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
val microPhonePod: Pod
get() = when (rawStatus.isBitSet(5)) {
@@ -53,22 +53,18 @@ interface DualApplePods : ApplePods, HasDualPods, HasEarDetection, HasCase {
}
}
}
val isLeftPodInEar: Boolean
override val isLeftPodInEar: Boolean
get() = when (microPhonePod) {
Pod.LEFT -> rawStatus.isBitSet(1)
Pod.RIGHT -> rawStatus.isBitSet(3)
}
val isRightPodInEar: Boolean
override val isRightPodInEar: Boolean
get() = when (microPhonePod) {
Pod.LEFT -> rawStatus.isBitSet(3)
Pod.RIGHT -> rawStatus.isBitSet(1)
}
override val isBeingWorn: Boolean
get() = isLeftPodInEar && isRightPodInEar
val isLeftPodCharging: Boolean
get() = when (microPhonePod) {
Pod.LEFT -> rawCaseBattery.upperNibble.isBitSet(0)
@@ -8,6 +8,7 @@ import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.flow.setupCommonEventHandlers
import eu.darken.capod.main.core.GeneralSettings
import eu.darken.capod.monitor.core.PodMonitor
import eu.darken.capod.pods.core.HasDualEarDetection
import eu.darken.capod.pods.core.HasEarDetection
import eu.darken.capod.pods.core.apple.DualApplePods
import eu.darken.capod.reaction.settings.ReactionSettings
@@ -71,7 +72,13 @@ class AutoConnect @Inject constructor(
else -> true
}
AutoConnectCondition.IN_EAR -> when (mainDevice) {
is HasEarDetection -> mainDevice.isBeingWorn
is HasEarDetection -> {
if (mainDevice is HasDualEarDetection && reactionSettings.onePodMode.value) {
mainDevice.isEitherPodInEar
} else {
mainDevice.isBeingWorn
}
}
else -> true
}
}
@@ -9,6 +9,7 @@ import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.flow.setupCommonEventHandlers
import eu.darken.capod.common.flow.withPrevious
import eu.darken.capod.monitor.core.PodMonitor
import eu.darken.capod.pods.core.HasDualEarDetection
import eu.darken.capod.pods.core.HasEarDetection
import eu.darken.capod.reaction.settings.ReactionSettings
import kotlinx.coroutines.flow.*
@@ -25,7 +26,8 @@ class PlayPause @Inject constructor(
fun monitor() = combine(
reactionSettings.autoPlay.flow,
reactionSettings.autoPause.flow,
) { play, pause -> play || pause }
reactionSettings.onePodMode.flow,
) { play, pause, _ -> play || pause }
.flatMapLatest { if (it) bluetoothManager.connectedDevices() else emptyFlow() }
.flatMapLatest {
if (it.isEmpty()) {
@@ -42,7 +44,28 @@ class PlayPause @Inject constructor(
if (previous is HasEarDetection && current is HasEarDetection) {
log(TAG, VERBOSE) { "previous=${previous.isBeingWorn}, current=${current.isBeingWorn}" }
log(TAG, VERBOSE) { "previous-id=${previous.identifier}, current-id=${current.identifier}" }
if (previous.identifier == current.identifier && previous.isBeingWorn != current.isBeingWorn) {
if (previous.identifier != current.identifier) {
return@onEach
}
if (previous is HasDualEarDetection && current is HasDualEarDetection && reactionSettings.onePodMode.value) {
log(TAG) { "Ear status changed for dual pod device in single pod mode." }
val previousWorn = previous.isEitherPodInEar
val currentWorn = current.isEitherPodInEar
if (!previousWorn && currentWorn && !mediaControl.isPlaying) {
if (reactionSettings.autoPlay.value) {
mediaControl.sendPlay()
} else {
log(TAG) { "autoPlay is disabled" }
}
} else if (!currentWorn && previousWorn && mediaControl.isPlaying) {
if (reactionSettings.autoPause.value) {
mediaControl.sendPause()
} else {
log(TAG) { "autoPause is disabled" }
}
}
} else if (previous.isBeingWorn != current.isBeingWorn) {
log(TAG) { "Ear status changed for monitored device." }
if (current.isBeingWorn && !mediaControl.isPlaying) {
if (reactionSettings.autoPlay.value) {
@@ -47,11 +47,17 @@ class ReactionSettings @Inject constructor(
false
)
val onePodMode = preferences.createFlowPreference(
"reaction.onepod.enabled",
false
)
override val preferenceDataStore: PreferenceDataStore = PreferenceStoreMapper(
autoPause,
autoPlay,
autoConnect,
autoConnectCondition,
showPopUpOnCaseOpen,
onePodMode,
)
}
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM14,17h-2L12,9h-2L10,7h4v10z" />
</vector>
+2
View File
@@ -132,4 +132,6 @@
<string name="overview_bluetooth_disabled_description">Bluetooth is disabled, enable it ;).</string>
<string name="help_translate_label">Translation</string>
<string name="help_translate_description">Help translate this into your favorite language.</string>
<string name="settings_onepod_mode_label">One pod mode</string>
<string name="settings_onepod_mode_description">Wearing both pods is not required, wearing a single pod is sufficient to trigger reactions.</string>
</resources>
@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:icon="@drawable/ic_baseline_looks_one_24"
android:key="reaction.onepod.enabled"
android:summary="@string/settings_onepod_mode_description"
android:title="@string/settings_onepod_mode_label" />
<CheckBoxPreference
android:icon="@drawable/ic_baseline_play_circle_24"
android:key="reaction.autoplay.enabled"