From f2a7f6ab455106ed5614b39dc678c71f8cc99879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rebelo?= Date: Fri, 24 Mar 2023 00:03:54 +0000 Subject: [PATCH] Sony WH-1000XM4: Add speak-to-chat settings --- .../SonyHeadphonesCapabilities.java | 3 +- .../headphones/SonyHeadphonesCoordinator.java | 4 +- .../SonyWH1000XM4Coordinator.java | 4 +- .../headphones/prefs/SpeakToChatConfig.java | 124 ++++++++++++++++++ ...eakToChat.java => SpeakToChatEnabled.java} | 10 +- .../headphones/SonyHeadphonesProtocol.java | 7 +- .../impl/AbstractSonyProtocolImpl.java | 11 +- .../protocol/impl/v1/PayloadTypeV1.java | 5 + .../protocol/impl/v1/SonyProtocolImplV1.java | 84 +++++++++++- .../protocol/impl/v2/SonyProtocolImplV2.java | 22 +++- 10 files changed, 247 insertions(+), 27 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChatConfig.java rename app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/{SpeakToChat.java => SpeakToChatEnabled.java} (82%) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCapabilities.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCapabilities.java index abd6a50e3..a44e4dfc7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCapabilities.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCapabilities.java @@ -23,7 +23,8 @@ public enum SonyHeadphonesCapabilities { PowerOffFromPhone, AmbientSoundControl, WindNoiseReduction, - SpeakToChat, + SpeakToChatEnabled, + SpeakToChatConfig, AncOptimizer, AudioSettingsOnlyOnSbcCodec, AudioUpsampling, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCoordinator.java index 3746fe2ee..964b2b426 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCoordinator.java @@ -178,7 +178,9 @@ public abstract class SonyHeadphonesCoordinator extends AbstractBLClassicDeviceC settings.add(R.xml.devicesettings_sony_headphones_ambient_sound_control); } - if (supports(SonyHeadphonesCapabilities.SpeakToChat)) { + if (supports(SonyHeadphonesCapabilities.SpeakToChatConfig)) { + settings.add(R.xml.devicesettings_sony_headphones_speak_to_chat_with_settings); + } else if (supports(SonyHeadphonesCapabilities.SpeakToChatEnabled)) { settings.add(R.xml.devicesettings_sony_headphones_speak_to_chat_simple); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/coordinators/SonyWH1000XM4Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/coordinators/SonyWH1000XM4Coordinator.java index 86afc0d1b..ff1f59470 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/coordinators/SonyWH1000XM4Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/coordinators/SonyWH1000XM4Coordinator.java @@ -47,11 +47,11 @@ public class SonyWH1000XM4Coordinator extends SonyHeadphonesCoordinator { return Arrays.asList( // TODO: Function of [CUSTOM] button // TODO R.xml.devicesettings_connect_two_devices, - // TODO R.xml.devicesettings_sony_headphones_speak_to_chat_with_settings, SonyHeadphonesCapabilities.BatterySingle, SonyHeadphonesCapabilities.AmbientSoundControl, SonyHeadphonesCapabilities.WindNoiseReduction, - SonyHeadphonesCapabilities.SpeakToChat, + SonyHeadphonesCapabilities.SpeakToChatEnabled, + SonyHeadphonesCapabilities.SpeakToChatConfig, SonyHeadphonesCapabilities.AncOptimizer, SonyHeadphonesCapabilities.EqualizerWithCustomBands, SonyHeadphonesCapabilities.AudioUpsampling, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChatConfig.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChatConfig.java new file mode 100644 index 000000000..0ec9f7259 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChatConfig.java @@ -0,0 +1,124 @@ +/* Copyright (C) 2023 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 . */ +package nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs; + +import android.content.SharedPreferences; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; + +public class SpeakToChatConfig { + public enum Sensitivity { + AUTO(0x00), + HIGH(0x01), + LOW(0x02), + ; + + private final byte code; + + Sensitivity(final int code) { + this.code = (byte) code; + } + + public byte getCode() { + return this.code; + } + + public static Sensitivity fromCode(final byte b) { + for (Sensitivity value : Sensitivity.values()) { + if (value.getCode() == b) { + return value; + } + } + + return null; + } + } + + public enum Timeout { + SHORT(0x00), + STANDARD(0x01), + LONG(0x02), + OFF(0x03), + ; + + private final byte code; + + Timeout(final int code) { + this.code = (byte) code; + } + + public byte getCode() { + return this.code; + } + + public static Timeout fromCode(final byte b) { + for (Timeout value : Timeout.values()) { + if (value.getCode() == b) { + return value; + } + } + + return null; + } + } + + private final boolean focusOnVoice; + private final Sensitivity sensitivity; + private final Timeout timeout; + + public SpeakToChatConfig(final boolean focusOnVoice, final Sensitivity sensitivity, final Timeout timeout) { + this.focusOnVoice = focusOnVoice; + this.sensitivity = sensitivity; + this.timeout = timeout; + } + + public boolean isFocusOnVoice() { + return focusOnVoice; + } + + public Sensitivity getSensitivity() { + return sensitivity; + } + + public Timeout getTimeout() { + return timeout; + } + + public String toString() { + return String.format(Locale.getDefault(), "SpeakToChatConfig{focusOnVoice=%s, sensitivity=%s, timeout=%s}", focusOnVoice, sensitivity, timeout); + } + + public Map toPreferences() { + return new HashMap() {{ + put(DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE, focusOnVoice); + put(DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_SENSITIVITY, sensitivity.name().toLowerCase(Locale.getDefault())); + put(DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_TIMEOUT, timeout.name().toLowerCase(Locale.getDefault())); + }}; + } + + public static SpeakToChatConfig fromPreferences(final SharedPreferences prefs) { + final boolean focusOnVoice = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE, false); + final Sensitivity sensitivity = Sensitivity.valueOf(prefs.getString(DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_SENSITIVITY, "auto").toUpperCase()); + final Timeout timeout = Timeout.valueOf(prefs.getString(DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_TIMEOUT, "standard").toUpperCase()); + + return new SpeakToChatConfig(focusOnVoice, sensitivity, timeout); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChat.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChatEnabled.java similarity index 82% rename from app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChat.java rename to app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChatEnabled.java index 5b5e5f648..9e2352189 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChat.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/prefs/SpeakToChatEnabled.java @@ -24,15 +24,15 @@ import java.util.Map; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; -public class SpeakToChat { +public class SpeakToChatEnabled { private final boolean enabled; - public SpeakToChat(final boolean enabled) { + public SpeakToChatEnabled(final boolean enabled) { this.enabled = enabled; } public String toString() { - return String.format(Locale.getDefault(), "SpeakToChat{enabled=%s}", enabled); + return String.format(Locale.getDefault(), "SpeakToChatEnabled{enabled=%s}", enabled); } public boolean isEnabled() { @@ -45,9 +45,9 @@ public class SpeakToChat { }}; } - public static SpeakToChat fromPreferences(final SharedPreferences prefs) { + public static SpeakToChatEnabled fromPreferences(final SharedPreferences prefs) { final boolean enabled = prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT, false); - return new SpeakToChat(enabled); + return new SpeakToChatEnabled(enabled); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/SonyHeadphonesProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/SonyHeadphonesProtocol.java index def7bdf58..56be60083 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/SonyHeadphonesProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/SonyHeadphonesProtocol.java @@ -40,7 +40,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.Equali import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.EqualizerPreset; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.PauseWhenTakenOff; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.QuickAccess; -import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChat; +import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChatConfig; +import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChatEnabled; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SoundPosition; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SurroundMode; @@ -221,10 +222,12 @@ public class SonyHeadphonesProtocol extends GBDeviceProtocol { LOG.warn("Connection to two devices not implemented ('{}')", config); return super.encodeSendConfiguration(config); case DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT: + configRequest = protocolImpl.setSpeakToChatEnabled(SpeakToChatEnabled.fromPreferences(prefs)); + break; case DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_SENSITIVITY: case DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE: case DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_TIMEOUT: - configRequest = protocolImpl.setSpeakToChat(SpeakToChat.fromPreferences(prefs)); + configRequest = protocolImpl.setSpeakToChatConfig(SpeakToChatConfig.fromPreferences(prefs)); break; default: LOG.warn("Unknown config '{}'", config); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/AbstractSonyProtocolImpl.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/AbstractSonyProtocolImpl.java index 83a20769e..7d67819a6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/AbstractSonyProtocolImpl.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/AbstractSonyProtocolImpl.java @@ -30,7 +30,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.Equali import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.PauseWhenTakenOff; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.QuickAccess; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SoundPosition; -import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChat; +import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChatConfig; +import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChatEnabled; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SurroundMode; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.TouchSensor; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications; @@ -59,9 +60,13 @@ public abstract class AbstractSonyProtocolImpl { public abstract Request setAmbientSoundControl(final AmbientSoundControl config); - public abstract Request setSpeakToChat(final SpeakToChat config); + public abstract Request setSpeakToChatEnabled(final SpeakToChatEnabled config); - public abstract Request getSpeakToChat(); + public abstract Request getSpeakToChatEnabled(); + + public abstract Request setSpeakToChatConfig(final SpeakToChatConfig config); + + public abstract Request getSpeakToChatConfig(); public abstract Request getNoiseCancellingOptimizerState(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v1/PayloadTypeV1.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v1/PayloadTypeV1.java index 17a706e12..11c5f92f4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v1/PayloadTypeV1.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v1/PayloadTypeV1.java @@ -75,6 +75,11 @@ public enum PayloadTypeV1 { AUTOMATIC_POWER_OFF_BUTTON_MODE_SET(MessageType.COMMAND_1, 0xf8), AUTOMATIC_POWER_OFF_BUTTON_MODE_NOTIFY(MessageType.COMMAND_1, 0xf9), + SPEAK_TO_CHAT_CONFIG_GET(MessageType.COMMAND_1, 0xfa), + SPEAK_TO_CHAT_CONFIG_RET(MessageType.COMMAND_1, 0xfb), + SPEAK_TO_CHAT_CONFIG_SET(MessageType.COMMAND_1, 0xfc), + SPEAK_TO_CHAT_CONFIG_NOTIFY(MessageType.COMMAND_1, 0xfd), + // TODO: The headphones spit out a lot of json, analyze it JSON_GET(MessageType.COMMAND_1, 0xc4), JSON_RET(MessageType.COMMAND_1, 0xc9), diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v1/SonyProtocolImplV1.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v1/SonyProtocolImplV1.java index 2cad4083e..9bba6cc57 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v1/SonyProtocolImplV1.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v1/SonyProtocolImplV1.java @@ -50,7 +50,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.Equali import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.PauseWhenTakenOff; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.QuickAccess; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SoundPosition; -import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChat; +import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChatConfig; +import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChatEnabled; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SurroundMode; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.TouchSensor; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications; @@ -141,7 +142,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { } @Override - public Request setSpeakToChat(final SpeakToChat config) { + public Request setSpeakToChatEnabled(final SpeakToChatEnabled config) { return new Request( PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getMessageType(), new byte[]{ @@ -154,7 +155,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { } @Override - public Request getSpeakToChat() { + public Request getSpeakToChatEnabled() { return new Request( PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(), new byte[]{ @@ -164,6 +165,32 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { ); } + @Override + public Request setSpeakToChatConfig(final SpeakToChatConfig config) { + return new Request( + PayloadTypeV1.SPEAK_TO_CHAT_CONFIG_SET.getMessageType(), + new byte[]{ + PayloadTypeV1.SPEAK_TO_CHAT_CONFIG_SET.getCode(), + (byte) 0x05, + (byte) 0x00, + config.getSensitivity().getCode(), + (byte) (config.isFocusOnVoice() ? 0x01 : 0x00), + config.getTimeout().getCode() + } + ); + } + + @Override + public Request getSpeakToChatConfig() { + return new Request( + PayloadTypeV1.SPEAK_TO_CHAT_CONFIG_GET.getMessageType(), + new byte[]{ + PayloadTypeV1.SPEAK_TO_CHAT_CONFIG_GET.getCode(), + (byte) 0x05 + } + ); + } + @Override public Request getNoiseCancellingOptimizerState() { return new Request( @@ -530,6 +557,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { case AUTOMATIC_POWER_OFF_BUTTON_MODE_RET: case AUTOMATIC_POWER_OFF_BUTTON_MODE_NOTIFY: return handleAutomaticPowerOffButtonMode(payload); + case SPEAK_TO_CHAT_CONFIG_RET: + case SPEAK_TO_CHAT_CONFIG_NOTIFY: + return handleSpeakToChatConfig(payload); case VOICE_NOTIFICATIONS_RET: case VOICE_NOTIFICATIONS_NOTIFY: return handleVoiceNotifications(payload); @@ -567,7 +597,8 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { put(SonyHeadphonesCapabilities.EqualizerWithCustomBands, getEqualizer()); put(SonyHeadphonesCapabilities.SoundPosition, getSoundPosition()); put(SonyHeadphonesCapabilities.SurroundMode, getSurroundMode()); - put(SonyHeadphonesCapabilities.SpeakToChat, getSpeakToChat()); + put(SonyHeadphonesCapabilities.SpeakToChatEnabled, getSpeakToChatEnabled()); + put(SonyHeadphonesCapabilities.SpeakToChatConfig, getSpeakToChatConfig()); put(SonyHeadphonesCapabilities.PauseWhenTakenOff, getPauseWhenTakenOff()); put(SonyHeadphonesCapabilities.AmbientSoundControlButtonMode, getAmbientSoundControlButtonMode()); put(SonyHeadphonesCapabilities.QuickAccess, getQuickAccess()); @@ -733,7 +764,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { return Collections.singletonList(event); } - public List handleSpeakToChat(final byte[] payload) { + public List handleSpeakToChatEnabled(final byte[] payload) { if (payload.length != 4) { LOG.warn("Unexpected payload length {}", payload.length); return Collections.emptyList(); @@ -748,7 +779,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { LOG.debug("Speak to chat: {}", enabled); final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences() - .withPreferences(new SpeakToChat(enabled).toPreferences()); + .withPreferences(new SpeakToChatEnabled(enabled).toPreferences()); return Collections.singletonList(event); } @@ -954,7 +985,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { case 0x03: return handlePauseWhenTakenOff(payload); case 0x05: - return handleSpeakToChat(payload); + return handleSpeakToChatEnabled(payload); case 0x06: return handleButtonModes(payload); } @@ -1068,6 +1099,45 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl { return Collections.singletonList(event); } + public List handleSpeakToChatConfig(final byte[] payload) { + if (payload.length != 6) { + LOG.warn("Unexpected payload length {}", payload.length); + return Collections.emptyList(); + } + + if (payload[1] != 0x05) { + LOG.warn("Not speak to chat config, ignoring"); + return Collections.emptyList(); + } + + final SpeakToChatConfig.Sensitivity sensitivity = SpeakToChatConfig.Sensitivity.fromCode(payload[3]); + if (sensitivity == null) { + LOG.warn("Unknown sensitivity code {}", String.format("%02x", payload[3])); + return Collections.emptyList(); + } + + final Boolean focusOnVoice = booleanFromByte(payload[4]); + if (focusOnVoice == null) { + LOG.warn("Unknown focus on voice code {}", String.format("%02x", payload[3])); + return Collections.emptyList(); + } + + final SpeakToChatConfig.Timeout timeout = SpeakToChatConfig.Timeout.fromCode(payload[5]); + if (timeout == null) { + LOG.warn("Unknown timeout code {}", String.format("%02x", payload[3])); + return Collections.emptyList(); + } + + final SpeakToChatConfig speakToChatConfig = new SpeakToChatConfig(focusOnVoice, sensitivity, timeout); + + LOG.debug("Speak to chat config: {}", speakToChatConfig); + + final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences() + .withPreferences(speakToChatConfig.toPreferences()); + + return Collections.singletonList(event); + } + public List handleVoiceNotifications(final byte[] payload) { if (payload.length != 4) { LOG.warn("Unexpected payload length {}", payload.length); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v2/SonyProtocolImplV2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v2/SonyProtocolImplV2.java index f0790cdf8..52d71ea1c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v2/SonyProtocolImplV2.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/sony/headphones/protocol/impl/v2/SonyProtocolImplV2.java @@ -20,7 +20,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -28,7 +27,6 @@ import java.util.Locale; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; -import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceInfo; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl; @@ -41,12 +39,12 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.Equali import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.PauseWhenTakenOff; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.QuickAccess; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SoundPosition; -import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChat; +import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChatConfig; +import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakToChatEnabled; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SurroundMode; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.TouchSensor; import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; -import nodomain.freeyourgadget.gadgetbridge.model.BatteryState; import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.MessageType; import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.Request; import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.impl.v1.PayloadTypeV1; @@ -106,13 +104,25 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 { } @Override - public Request setSpeakToChat(SpeakToChat config) { + public Request setSpeakToChatEnabled(SpeakToChatEnabled config) { LOG.warn("Speak-to-chat not implemented for V2"); return null; } @Override - public Request getSpeakToChat() { + public Request getSpeakToChatEnabled() { + LOG.warn("Speak-to-chat not implemented for V2"); + return null; + } + + @Override + public Request setSpeakToChatConfig(SpeakToChatConfig config) { + LOG.warn("Speak-to-chat not implemented for V2"); + return null; + } + + @Override + public Request getSpeakToChatConfig() { LOG.warn("Speak-to-chat not implemented for V2"); return null; }