mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
oppo: add AncConfigType.TOUCH_CYCLE_MODES
This commit is contained in:
+1
@@ -83,6 +83,7 @@ public abstract class OppoHeadphonesCoordinator extends AbstractBLClassicDeviceC
|
||||
}
|
||||
if (this.supportsAnc(device)) {
|
||||
settings.addSubScreen(DeviceSpecificSettingsScreen.AUDIO, R.xml.devicesettings_onemore_noise_control_selector);
|
||||
settings.addSubScreen(DeviceSpecificSettingsScreen.TOUCH_OPTIONS, R.xml.devicesettings_oppo_headphones_touch_options_anc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -22,12 +22,13 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.TouchC
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.TouchConfigType;
|
||||
|
||||
public class OppoHeadphonesPreferences {
|
||||
public static final String TOUCH_PREFIX= "oppo_touch__";
|
||||
public static final String TOUCH_PREFIX = "oppo_touch__";
|
||||
|
||||
public static final String LDAC = "pref_soundcore_ldac_mode";
|
||||
public static final String MULTIPOINT = "oppo_multipoint";
|
||||
public static final String GAME_MODE = "oppo_game_mode";
|
||||
public static final String ANC_SELECTOR = "noise_control_selector";
|
||||
public static final String ANC_TOUCH_CYCLE_MODES = "oppo_touch_anc_cycle_modes";
|
||||
|
||||
public static String getTouchKey(final TouchConfigSide side, final TouchConfigType type) {
|
||||
return String.format(
|
||||
|
||||
+1
@@ -93,6 +93,7 @@ public class OppoHeadphonesSettingsCustomizer implements DeviceSpecificSettingsC
|
||||
this.addPreferenceHandler(handler, OppoHeadphonesPreferences.MULTIPOINT, supportsMultipoint);
|
||||
this.addPreferenceHandler(handler, OppoHeadphonesPreferences.GAME_MODE, supportsGameMode);
|
||||
this.addPreferenceHandler(handler, OppoHeadphonesPreferences.ANC_SELECTOR, supportsAnc);
|
||||
this.addPreferenceHandler(handler, OppoHeadphonesPreferences.ANC_TOUCH_CYCLE_MODES, supportsAnc);
|
||||
|
||||
for (final Map.Entry<Pair<TouchConfigSide, TouchConfigType>, List<TouchConfigValue>> e : touchOptions.entrySet()) {
|
||||
final TouchConfigSide side = e.getKey().first;
|
||||
|
||||
+71
-25
@@ -26,6 +26,9 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
@@ -42,6 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.TouchC
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.TouchConfigType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.TouchConfigValue;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.MiscConfigType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.AncConfigType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.AncConfigValue;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.preferences.DevicePrefs;
|
||||
@@ -344,16 +348,16 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
||||
private static GBDeviceEvent parseMiscConfig(final byte[] payload) {
|
||||
final GBDeviceEventUpdatePreferences eventUpdatePreferences = new GBDeviceEventUpdatePreferences();
|
||||
for (int i = 2; i + 1 < payload.length; i += 2) {
|
||||
final int code = payload[i] & 0xff;
|
||||
final int value = payload[i + 1] & 0xff;
|
||||
final int typeCode = payload[i] & 0xff;
|
||||
final int valueCode = payload[i + 1] & 0xff;
|
||||
|
||||
final MiscConfigType type = MiscConfigType.fromCode(code);
|
||||
final MiscConfigType type = MiscConfigType.fromCode(typeCode);
|
||||
if (type == null) {
|
||||
LOG.warn("Unknown misc config code {}", code);
|
||||
LOG.warn("Unknown misc config type code {}", typeCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
final boolean isEnabled = (value == 1);
|
||||
final boolean isEnabled = (valueCode == 1);
|
||||
switch (type) {
|
||||
case LDAC:
|
||||
LOG.debug("Got misc config for LDAC = {}", isEnabled);
|
||||
@@ -377,7 +381,7 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
||||
);
|
||||
break;
|
||||
default:
|
||||
LOG.warn("Unknown misc config code {}", code);
|
||||
LOG.warn("Unknown misc config type code {}", typeCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -421,22 +425,39 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
||||
private static GBDeviceEvent parseAncConfig(final byte[] payload) {
|
||||
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences();
|
||||
|
||||
for (int i = 2; i + 1 < payload.length; i += 2) {
|
||||
final int code = payload[i] & 0xff;
|
||||
final int value = payload[i + 1] & 0xff;
|
||||
final int typeCode = payload[1] & 0xff;
|
||||
final int valueCode = payload[3] & 0xff;
|
||||
|
||||
switch (code) {
|
||||
case 0x01:
|
||||
final AncConfigValue mode = AncConfigValue.fromCode(value);
|
||||
if (mode != null) {
|
||||
event.withPreference(OppoHeadphonesPreferences.ANC_SELECTOR, mode.getPrefId());
|
||||
} else {
|
||||
LOG.warn("Unknown ANC mode {}", value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG.debug("Unknown code {}", code);
|
||||
break;
|
||||
final AncConfigType type = AncConfigType.fromCode(typeCode);
|
||||
if (type == null) {
|
||||
LOG.warn("Unknown anc type code {}", typeCode);
|
||||
return event;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case MODE: {
|
||||
final AncConfigValue mode = AncConfigValue.fromCode(valueCode);
|
||||
if (mode != null) {
|
||||
LOG.debug("Got anc config for {} = {}", type, mode);
|
||||
event.withPreference(OppoHeadphonesPreferences.ANC_SELECTOR, mode.getPrefId());
|
||||
} else {
|
||||
LOG.warn("Unknown anc mode code {}", valueCode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TOUCH_CYCLE_MODES: {
|
||||
final EnumSet<AncConfigValue> modes = AncConfigValue.fromMask(valueCode);
|
||||
if (!modes.isEmpty()) {
|
||||
final Set<String> prefIds = AncConfigValue.toPrefIds(modes);
|
||||
|
||||
LOG.debug("Got anc config for {} = {}", type, prefIds);
|
||||
event.withPreference(OppoHeadphonesPreferences.ANC_TOUCH_CYCLE_MODES, prefIds);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG.debug("Unknown anc type code {}", typeCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return event;
|
||||
@@ -498,7 +519,19 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
||||
mode = AncConfigValue.OFF;
|
||||
}
|
||||
LOG.debug("Sending ANC mode = {}", mode);
|
||||
return encodeAncConfigSet(mode);
|
||||
return encodeAncModeSet(mode);
|
||||
}
|
||||
|
||||
if (config.equals(OppoHeadphonesPreferences.ANC_TOUCH_CYCLE_MODES)) {
|
||||
final Set<String> prefIds = prefs.getStringSet(OppoHeadphonesPreferences.ANC_TOUCH_CYCLE_MODES, Collections.emptySet());
|
||||
final EnumSet<AncConfigValue> modes = AncConfigValue.fromPrefIds(prefIds);
|
||||
if (modes.size() < 2) {
|
||||
LOG.warn("ANC cycle must contain at least 2 modes. Current selection: {}", modes);
|
||||
return super.encodeSendConfiguration(config);
|
||||
}
|
||||
|
||||
LOG.debug("Sending ANC touch cycle modes = {}", modes);
|
||||
return encodeAncTouchCycleModesSet(modes);
|
||||
}
|
||||
|
||||
return super.encodeSendConfiguration(config);
|
||||
@@ -563,18 +596,31 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
||||
return encodeMessage(OppoCommand.MISC_CONFIG_REQ, payload);
|
||||
}
|
||||
|
||||
public byte[] encodeAncConfigSet(final AncConfigValue mode) {
|
||||
public byte[] encodeAncModeSet(final AncConfigValue mode) {
|
||||
final byte[] payload = new byte[] {
|
||||
(byte) 0x01,
|
||||
(byte) AncConfigType.MODE.getCode(),
|
||||
(byte) 0x01,
|
||||
(byte) mode.getCode()
|
||||
};
|
||||
return encodeMessage(OppoCommand.ANC_CONFIG_SET, payload);
|
||||
}
|
||||
|
||||
public byte[] encodeAncConfigReq() {
|
||||
public byte[] encodeAncTouchCycleModesSet(final EnumSet<AncConfigValue> modes) {
|
||||
int mask = 0;
|
||||
for (AncConfigValue mode : modes) {
|
||||
mask |= mode.getCode();
|
||||
}
|
||||
final byte[] payload = new byte[] {
|
||||
(byte) AncConfigType.TOUCH_CYCLE_MODES.getCode(),
|
||||
(byte) 0x01,
|
||||
(byte) mask
|
||||
};
|
||||
return encodeMessage(OppoCommand.ANC_CONFIG_SET, payload);
|
||||
}
|
||||
|
||||
public byte[] encodeAncConfigReq(final AncConfigType type) {
|
||||
final byte[] payload = new byte[] {
|
||||
(byte) type.getCode(),
|
||||
(byte) 0x01,
|
||||
};
|
||||
return encodeMessage(OppoCommand.ANC_CONFIG_REQ, payload);
|
||||
|
||||
+3
-1
@@ -30,6 +30,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractHeadphoneSerialDeviceSupportV2;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.MiscConfigType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands.AncConfigType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.oppo.OppoHeadphonesCoordinator;
|
||||
|
||||
public class OppoHeadphonesSupport extends AbstractHeadphoneSerialDeviceSupportV2<OppoHeadphonesProtocol> {
|
||||
@@ -91,7 +92,8 @@ public class OppoHeadphonesSupport extends AbstractHeadphoneSerialDeviceSupportV
|
||||
}
|
||||
builder.write(mDeviceProtocol.encodeTouchConfigReq());
|
||||
if (coordinator.supportsAnc(getDevice())) {
|
||||
builder.write(mDeviceProtocol.encodeAncConfigReq());
|
||||
builder.write(mDeviceProtocol.encodeAncConfigReq(AncConfigType.MODE));
|
||||
builder.write(mDeviceProtocol.encodeAncConfigReq(AncConfigType.TOUCH_CYCLE_MODES));
|
||||
}
|
||||
|
||||
builder.write(mDeviceProtocol.encodeBatteryReq());
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/* Copyright (C) 2024 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
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/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public enum AncConfigType {
|
||||
MODE(0x01),
|
||||
TOUCH_CYCLE_MODES(0x02),
|
||||
;
|
||||
|
||||
private final int code;
|
||||
|
||||
AncConfigType(final int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AncConfigType fromCode(final int code) {
|
||||
for (final AncConfigType param : AncConfigType.values()) {
|
||||
if (param.code == code) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+35
@@ -16,6 +16,11 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.oppo.commands;
|
||||
|
||||
import java.lang.Iterable;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public enum AncConfigValue {
|
||||
@@ -51,6 +56,17 @@ public enum AncConfigValue {
|
||||
return prefId;
|
||||
}
|
||||
|
||||
public static EnumSet<AncConfigValue> fromMask(int mask) {
|
||||
EnumSet<AncConfigValue> modes = EnumSet.noneOf(AncConfigValue.class);
|
||||
for (AncConfigValue mode : AncConfigValue.values()) {
|
||||
if ((mask & mode.getCode()) == mode.getCode()) {
|
||||
modes.add(mode);
|
||||
}
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AncConfigValue fromPrefId(final String prefId) {
|
||||
for (final AncConfigValue param : AncConfigValue.values()) {
|
||||
@@ -61,4 +77,23 @@ public enum AncConfigValue {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Set<String> toPrefIds(Iterable<AncConfigValue> modes) {
|
||||
Set<String> prefIds = new HashSet<>();
|
||||
for (AncConfigValue mode : modes) {
|
||||
prefIds.add(mode.getPrefId());
|
||||
}
|
||||
return prefIds;
|
||||
}
|
||||
|
||||
public static EnumSet<AncConfigValue> fromPrefIds(Iterable<String> prefIds) {
|
||||
EnumSet<AncConfigValue> modes = EnumSet.noneOf(AncConfigValue.class);
|
||||
for (String prefId : prefIds) {
|
||||
AncConfigValue mode = fromPrefId(prefId);
|
||||
if (mode != null) {
|
||||
modes.add(mode);
|
||||
}
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4520,7 +4520,7 @@
|
||||
<item>@string/pref_title_touch_voice_assistant</item>
|
||||
<item>@string/pref_title_touch_voice_assistant</item>
|
||||
<item>@string/prefs_game_mode</item>
|
||||
<item>@string/prefs_noise_control</item>
|
||||
<item>@string/moondrop_touch_action_anc_mode</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="oppo_touch_tap_values">
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="oppo_touch_header_anc"
|
||||
android:title="@string/prefs_active_noise_cancelling"
|
||||
app:iconSpaceReserved="false">
|
||||
<MultiSelectListPreference
|
||||
android:key="oppo_touch_anc_cycle_modes"
|
||||
android:title="@string/prefs_noise_modes_to_cycle"
|
||||
android:icon="@drawable/ic_sync"
|
||||
android:entries="@array/onemore_noise_control_modes"
|
||||
android:entryValues="@array/onemore_noise_control_values"
|
||||
android:defaultValue="@array/onemore_noise_control_values" />
|
||||
</PreferenceCategory>
|
||||
</androidx.preference.PreferenceScreen>
|
||||
Reference in New Issue
Block a user