Moondrop: Restrict ANC controls to Space Travel 2 only

This commit is contained in:
Jan64X
2026-05-02 20:12:56 +02:00
parent f616c3159c
commit 7e3fdc8806
9 changed files with 129 additions and 71 deletions
@@ -21,6 +21,9 @@ import androidx.annotation.NonNull;
import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.moondrop.MoondropSpaceTravel2DeviceSupport;
@@ -36,6 +39,28 @@ public class MoondropSpaceTravel2Coordinator extends MoondropSpaceTravelCoordina
return R.string.devicetype_moondrop_space_travel_2;
}
@Override
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
final DeviceSpecificSettings settings = new DeviceSpecificSettings();
settings.addRootScreen(R.xml.devicesettings_moondrop_space_travel_2_audio);
settings.addRootScreen(DeviceSpecificSettingsScreen.TOUCH_OPTIONS);
settings.addSubScreen(
DeviceSpecificSettingsScreen.TOUCH_OPTIONS,
R.xml.devicesettings_moondrop_space_travel_touch);
settings.addRootScreen(DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS);
settings.addSubScreen(
DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS,
R.xml.devicesettings_headphones);
return settings;
}
@Override
public DeviceSpecificSettingsCustomizer getDeviceSpecificSettingsCustomizer(final GBDevice device) {
return new MoondropSpaceTravel2SettingsCustomizer(device);
}
@NonNull
@Override
public Class<? extends DeviceSupport> getDeviceSupportClass(final GBDevice device) {
@@ -31,10 +31,10 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_MOONDROP_ANC_MODE;
public class MoondropSpaceTravelSettingsCustomizer implements DeviceSpecificSettingsCustomizer {
public class MoondropSpaceTravel2SettingsCustomizer implements DeviceSpecificSettingsCustomizer {
private final GBDevice device;
public MoondropSpaceTravelSettingsCustomizer(final GBDevice device) {
public MoondropSpaceTravel2SettingsCustomizer(final GBDevice device) {
this.device = device;
}
@@ -58,16 +58,16 @@ public class MoondropSpaceTravelSettingsCustomizer implements DeviceSpecificSett
return Collections.emptySet();
}
public static final Creator<MoondropSpaceTravelSettingsCustomizer> CREATOR = new Creator<MoondropSpaceTravelSettingsCustomizer>() {
public static final Creator<MoondropSpaceTravel2SettingsCustomizer> CREATOR = new Creator<MoondropSpaceTravel2SettingsCustomizer>() {
@Override
public MoondropSpaceTravelSettingsCustomizer createFromParcel(final Parcel in) {
final GBDevice device = in.readParcelable(MoondropSpaceTravelSettingsCustomizer.class.getClassLoader());
return new MoondropSpaceTravelSettingsCustomizer(device);
public MoondropSpaceTravel2SettingsCustomizer createFromParcel(final Parcel in) {
final GBDevice device = in.readParcelable(MoondropSpaceTravel2SettingsCustomizer.class.getClassLoader());
return new MoondropSpaceTravel2SettingsCustomizer(device);
}
@Override
public MoondropSpaceTravelSettingsCustomizer[] newArray(final int size) {
return new MoondropSpaceTravelSettingsCustomizer[size];
public MoondropSpaceTravel2SettingsCustomizer[] newArray(final int size) {
return new MoondropSpaceTravel2SettingsCustomizer[size];
}
};
@@ -22,7 +22,6 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLClassicDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
@@ -79,11 +78,6 @@ public class MoondropSpaceTravelCoordinator extends AbstractBLClassicDeviceCoord
return MoondropSpaceTravelDeviceSupport.class;
}
@Override
public DeviceSpecificSettingsCustomizer getDeviceSpecificSettingsCustomizer(final GBDevice device) {
return new MoondropSpaceTravelSettingsCustomizer(device);
}
@Override
public DeviceCoordinator.DeviceKind getDeviceKind(@NonNull GBDevice device) {
return DeviceKind.EARBUDS;
@@ -16,9 +16,34 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.moondrop;
public class MoondropSpaceTravel2DeviceSupport extends MoondropSpaceTravelDeviceSupport {
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_MOONDROP_ANC_MODE;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractHeadphoneSerialDeviceSupportV2;
public class MoondropSpaceTravel2DeviceSupport extends AbstractHeadphoneSerialDeviceSupportV2<MoondropSpaceTravel2Protocol> {
@Override
protected MoondropSpaceTravelProtocol createDeviceProtocol() {
protected MoondropSpaceTravel2Protocol createDeviceProtocol() {
return new MoondropSpaceTravel2Protocol(getDevice());
}
@Override
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
builder.write(mDeviceProtocol.encodeGetEqualizerPreset());
builder.write(mDeviceProtocol.encodeGetTouchActions());
builder.write(mDeviceProtocol.encodeGetAudioCurationMode());
builder.setDeviceState(GBDevice.State.INITIALIZED);
return builder;
}
@Override
public void onReadConfiguration(final String config) {
if (PREF_MOONDROP_ANC_MODE.equals(config)) {
final TransactionBuilder builder = createTransactionBuilder("read anc mode");
builder.write(mDeviceProtocol.encodeGetAudioCurationMode());
builder.queue();
}
}
}
@@ -16,10 +16,61 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.moondrop;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_MOONDROP_ANC_MODE;
public class MoondropSpaceTravel2Protocol extends MoondropSpaceTravelProtocol {
private static final byte AUDIO_CURATION_FEATURE = (byte)0x08;
private static final byte AUDIO_CURATION_PDU_GET_MODE = (byte)0x03;
private static final byte AUDIO_CURATION_PDU_SET_MODE = (byte)0x04;
protected MoondropSpaceTravel2Protocol(GBDevice device) {
super(device);
}
@Override
protected GBDeviceEvent decodePacket(short featureId, short pduId, byte[] payload) {
if (featureId == AUDIO_CURATION_FEATURE && pduId == AUDIO_CURATION_PDU_GET_MODE)
return handlePacketAudioCurationMode(payload);
return super.decodePacket(featureId, pduId, payload);
}
@Override
public byte[] encodeSendConfiguration(String config) {
if (PREF_MOONDROP_ANC_MODE.equals(config))
return encodeSetAudioCurationMode();
return super.encodeSendConfiguration(config);
}
public byte[] encodeGetAudioCurationMode() {
return new GaiaPacket(AUDIO_CURATION_FEATURE, AUDIO_CURATION_PDU_GET_MODE).encode();
}
private byte[] encodeSetAudioCurationMode() {
Prefs prefs = getDevicePrefs();
byte mode = Byte.parseByte(prefs.getString(PREF_MOONDROP_ANC_MODE, "1"));
byte[] payload = new byte[] { mode };
return new GaiaPacket(AUDIO_CURATION_FEATURE, AUDIO_CURATION_PDU_SET_MODE, payload).encode();
}
private GBDeviceEvent handlePacketAudioCurationMode(byte[] payload) {
if (payload.length < 1)
return null;
// GET_MODE returns a 0-based slot index, SET_MODE and the UI dropdown use a
// bitmask (Normal=1, ANC=2, Transparency=4). Convert before storing the
// preference.
int slot = payload[0] & 0xff;
if (slot > 2)
return null;
int mode = 1 << slot;
return new GBDeviceEventUpdatePreferences(PREF_MOONDROP_ANC_MODE, String.valueOf(mode));
}
}
@@ -16,8 +16,6 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.moondrop;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_MOONDROP_ANC_MODE;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractHeadphoneSerialDeviceSupportV2;
@@ -32,18 +30,8 @@ public class MoondropSpaceTravelDeviceSupport extends AbstractHeadphoneSerialDev
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
builder.write(mDeviceProtocol.encodeGetEqualizerPreset());
builder.write(mDeviceProtocol.encodeGetTouchActions());
builder.write(mDeviceProtocol.encodeGetAudioCurationMode());
builder.setDeviceState(GBDevice.State.INITIALIZED);
return builder;
}
@Override
public void onReadConfiguration(final String config) {
if (PREF_MOONDROP_ANC_MODE.equals(config)) {
final TransactionBuilder builder = createTransactionBuilder("read anc mode");
builder.write(mDeviceProtocol.encodeGetAudioCurationMode());
builder.queue();
}
}
}
@@ -41,10 +41,6 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
private static final byte TOUCH_ACTIONS_PDU_GET = (byte)0x02;
private static final byte TOUCH_ACTIONS_PDU_SET = (byte)0x03;
private static final byte AUDIO_CURATION_FEATURE = (byte)0x08;
private static final byte AUDIO_CURATION_PDU_GET_MODE = (byte)0x03;
private static final byte AUDIO_CURATION_PDU_SET_MODE = (byte)0x04;
protected MoondropSpaceTravelProtocol(GBDevice device) {
super(device);
}
@@ -76,8 +72,6 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
return handlePacketEqualizerPreset(payload);
else if (featureId == TOUCH_ACTIONS_FEATURE && pduId == TOUCH_ACTIONS_PDU_GET)
return handlePacketTouchActions(payload);
else if (featureId == AUDIO_CURATION_FEATURE && pduId == AUDIO_CURATION_PDU_GET_MODE)
return handlePacketAudioCurationMode(payload);
return null;
}
@@ -107,28 +101,11 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
return new GBDeviceEventUpdatePreferences(prefs);
}
private GBDeviceEvent handlePacketAudioCurationMode(byte[] payload) {
if (payload.length < 1)
return null;
// GET_MODE returns a 0-based slot index, SET_MODE and the UI dropdown use a
// bitmask (Normal=1, ANC=2, Transparency=4). Convert before storing the
// preference.
int slot = payload[0] & 0xff;
if (slot > 2)
return null;
int mode = 1 << slot;
return new GBDeviceEventUpdatePreferences(PREF_MOONDROP_ANC_MODE, String.valueOf(mode));
}
@Override
public byte[] encodeSendConfiguration(String config) {
switch (config) {
case PREF_MOONDROP_EQUALIZER_PRESET:
return encodeSetEqualizerPreset();
case PREF_MOONDROP_ANC_MODE:
return encodeSetAudioCurationMode();
case PREF_MOONDROP_TOUCH_PLAY_PAUSE_EARBUD:
case PREF_MOONDROP_TOUCH_PLAY_PAUSE_TRIGGER:
case PREF_MOONDROP_TOUCH_MEDIA_PREV_EARBUD:
@@ -157,10 +134,6 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
return new GaiaPacket(TOUCH_ACTIONS_FEATURE, TOUCH_ACTIONS_PDU_GET).encode();
}
public byte[] encodeGetAudioCurationMode() {
return new GaiaPacket(AUDIO_CURATION_FEATURE, AUDIO_CURATION_PDU_GET_MODE).encode();
}
private byte[] encodeSetEqualizerPreset() {
Prefs prefs = getDevicePrefs();
byte preset = Byte.parseByte(prefs.getString(PREF_MOONDROP_EQUALIZER_PRESET, "0"));
@@ -170,15 +143,6 @@ public class MoondropSpaceTravelProtocol extends GBDeviceProtocol {
return new GaiaPacket(EQUALIZER_PRESET_FEATURE, EQUALIZER_PRESET_PDU_SET, payload).encode();
}
private byte[] encodeSetAudioCurationMode() {
Prefs prefs = getDevicePrefs();
byte mode = Byte.parseByte(prefs.getString(PREF_MOONDROP_ANC_MODE, "1"));
byte[] payload = new byte[] { mode };
return new GaiaPacket(AUDIO_CURATION_FEATURE, AUDIO_CURATION_PDU_SET_MODE, payload).encode();
}
private byte[] encodeSetTouchActions() {
Prefs prefs = getDevicePrefs();
byte actionPlayPause = encodeTouchAction(prefs, PREF_MOONDROP_TOUCH_PLAY_PAUSE_EARBUD, PREF_MOONDROP_TOUCH_PLAY_PAUSE_TRIGGER);
@@ -0,0 +1,18 @@
<?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">
<ListPreference
android:entries="@array/moondrop_equalizer_preset_names"
android:entryValues="@array/moondrop_equalizer_preset_values"
android:icon="@drawable/ic_graphic_eq"
android:key="pref_moondrop_equalizer_preset"
app:useSimpleSummaryProvider="true"
android:title="@string/prefs_equalizer_preset" />
<ListPreference
android:entries="@array/moondrop_anc_mode_names"
android:entryValues="@array/moondrop_anc_mode_values"
android:icon="@drawable/ic_voice"
android:key="pref_moondrop_anc_mode"
app:useSimpleSummaryProvider="true"
android:title="@string/prefs_active_noise_cancelling_level" />
</androidx.preference.PreferenceScreen>
@@ -8,11 +8,4 @@
android:key="pref_moondrop_equalizer_preset"
app:useSimpleSummaryProvider="true"
android:title="@string/prefs_equalizer_preset" />
<ListPreference
android:entries="@array/moondrop_anc_mode_names"
android:entryValues="@array/moondrop_anc_mode_values"
android:icon="@drawable/ic_voice"
android:key="pref_moondrop_anc_mode"
app:useSimpleSummaryProvider="true"
android:title="@string/prefs_active_noise_cancelling_level" />
</androidx.preference.PreferenceScreen>