1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-09 22:57:54 +02:00

Sony WH-1000XM3/WF-SP800N: Add volume setting

This commit is contained in:
José Rebelo 2023-07-23 19:40:11 +01:00
parent 059b857e45
commit 702651c119
12 changed files with 103 additions and 11 deletions

View File

@ -12,6 +12,7 @@
* Huami: Persist workout raw details even if gpx has no points
* Mi Band 5: Fix activity fetch error toast when stress monitoring is enabled
* LeFun: Fix heart rate popup when measurement is triggered from phone
* Sony WH-1000XM3/WF-SP800N: Add volume setting
* Sony WH-1000XM5: Fix speak-to-chat enable/disable
* Zepp OS: Add loyalty cards integration with Catima
* Zepp OS: Fix reminder creation

View File

@ -39,5 +39,6 @@ public enum SonyHeadphonesCapabilities {
SoundPosition,
SurroundMode,
QuickAccess,
PauseWhenTakenOff
PauseWhenTakenOff,
Volume,
}

View File

@ -196,6 +196,7 @@ public abstract class SonyHeadphonesCoordinator extends AbstractBLClassicDeviceC
put(SonyHeadphonesCapabilities.SoundPosition, R.xml.devicesettings_sony_headphones_sound_position);
put(SonyHeadphonesCapabilities.SurroundMode, R.xml.devicesettings_sony_headphones_surround_mode);
put(SonyHeadphonesCapabilities.AudioUpsampling, R.xml.devicesettings_sony_headphones_audio_upsampling);
put(SonyHeadphonesCapabilities.Volume, R.xml.devicesettings_volume);
}});
addSettingsUnderHeader(settings, R.xml.devicesettings_header_system, new LinkedHashMap<SonyHeadphonesCapabilities, Integer>() {{

View File

@ -64,7 +64,8 @@ public class SonyWFSP800NCoordinator extends SonyHeadphonesCoordinator {
SonyHeadphonesCapabilities.ButtonModesLeftRight,
SonyHeadphonesCapabilities.PauseWhenTakenOff,
SonyHeadphonesCapabilities.AutomaticPowerOffWhenTakenOff,
SonyHeadphonesCapabilities.VoiceNotifications
SonyHeadphonesCapabilities.VoiceNotifications,
SonyHeadphonesCapabilities.Volume
);
}
}

View File

@ -56,7 +56,8 @@ public class SonyWH1000XM3Coordinator extends SonyHeadphonesCoordinator {
SonyHeadphonesCapabilities.AudioUpsampling,
SonyHeadphonesCapabilities.TouchSensorSingle,
SonyHeadphonesCapabilities.AutomaticPowerOffByTime,
SonyHeadphonesCapabilities.VoiceNotifications
SonyHeadphonesCapabilities.VoiceNotifications,
SonyHeadphonesCapabilities.Volume
);
}
}

View File

@ -201,6 +201,9 @@ public class SonyHeadphonesProtocol extends GBDeviceProtocol {
case DeviceSettingsPreferenceConst.PREF_SONY_AUDIO_UPSAMPLING:
configRequest = protocolImpl.setAudioUpsampling(AudioUpsampling.fromPreferences(prefs));
break;
case DeviceSettingsPreferenceConst.PREF_VOLUME:
configRequest = protocolImpl.setVolume(prefs.getInt(config, 15));
break;
case DeviceSettingsPreferenceConst.PREF_SONY_TOUCH_SENSOR:
configRequest = protocolImpl.setTouchSensor(TouchSensor.fromPreferences(prefs));
break;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 José Rebelo
/* Copyright (C) 2023 José Rebelo
This file is part of Gadgetbridge.
@ -16,16 +16,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones;
import android.net.Uri;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.deviceevents.SonyHeadphonesEnqueueRequestEvent;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;

View File

@ -126,5 +126,9 @@ public abstract class AbstractSonyProtocolImpl {
public abstract Request powerOff();
public abstract Request getVolume();
public abstract Request setVolume(final int volume);
public abstract List<? extends GBDeviceEvent> handlePayload(final MessageType messageType, final byte[] payload);
}

View File

@ -53,6 +53,11 @@ public enum PayloadTypeV1 {
AMBIENT_SOUND_CONTROL_SET(MessageType.COMMAND_1, 0x68),
AMBIENT_SOUND_CONTROL_NOTIFY(MessageType.COMMAND_1, 0x69),
VOLUME_GET(MessageType.COMMAND_1, 0xa6),
VOLUME_RET(MessageType.COMMAND_1, 0xa7),
VOLUME_SET(MessageType.COMMAND_1, 0xa8),
VOLUME_NOTIFY(MessageType.COMMAND_1, 0xa9),
NOISE_CANCELLING_OPTIMIZER_START(MessageType.COMMAND_1, 0x84),
NOISE_CANCELLING_OPTIMIZER_STATUS(MessageType.COMMAND_1, 0x85),

View File

@ -519,6 +519,31 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
);
}
@Override
public Request getVolume() {
return new Request(
PayloadTypeV1.VOLUME_GET.getMessageType(),
new byte[]{
PayloadTypeV1.VOLUME_GET.getCode(),
(byte) 0x01,
(byte) 0x20
}
);
}
@Override
public Request setVolume(final int volume) {
return new Request(
PayloadTypeV1.VOLUME_SET.getMessageType(),
new byte[]{
PayloadTypeV1.VOLUME_SET.getCode(),
(byte) 0x01,
(byte) 0x20,
(byte) volume
}
);
}
@Override
public List<? extends GBDeviceEvent> handlePayload(final MessageType messageType, final byte[] payload) {
final PayloadTypeV1 payloadType = PayloadTypeV1.fromCode(messageType, payload[0]);
@ -543,6 +568,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
case AMBIENT_SOUND_CONTROL_RET:
case AMBIENT_SOUND_CONTROL_NOTIFY:
return handleAmbientSoundControl(payload);
case VOLUME_RET:
case VOLUME_NOTIFY:
return handleVolume(payload);
case NOISE_CANCELLING_OPTIMIZER_STATUS:
return handleNoiseCancellingOptimizerStatus(payload);
case NOISE_CANCELLING_OPTIMIZER_STATE_RET:
@ -602,6 +630,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
put(SonyHeadphonesCapabilities.PauseWhenTakenOff, getPauseWhenTakenOff());
put(SonyHeadphonesCapabilities.AmbientSoundControlButtonMode, getAmbientSoundControlButtonMode());
put(SonyHeadphonesCapabilities.QuickAccess, getQuickAccess());
put(SonyHeadphonesCapabilities.Volume, getVolume());
}};
for (Map.Entry<SonyHeadphonesCapabilities, Request> capabilityEntry : capabilityRequestMap.entrySet()) {
@ -667,7 +696,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
final AmbientSoundControl ambientSoundControl = new AmbientSoundControl(mode, focusOnVoice, ambientSound);
LOG.warn("Ambient sound control: {}", ambientSoundControl);
LOG.debug("Ambient sound control: {}", ambientSoundControl);
final GBDeviceEventUpdatePreferences eventUpdatePreferences = new GBDeviceEventUpdatePreferences()
.withPreferences(ambientSoundControl.toPreferences());
@ -675,6 +704,37 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.singletonList(eventUpdatePreferences);
}
public List<? extends GBDeviceEvent> handleVolume(final byte[] payload) {
if (payload.length != 4) {
LOG.warn("Unexpected payload length {}", payload.length);
return Collections.emptyList();
}
AmbientSoundControl.Mode mode = null;
if (payload[1] != (byte) 0x01) {
LOG.warn("Unexpected byte at position 1 for volume: {}", payload[1]);
return Collections.emptyList();
}
if (payload[2] != (byte) 0x20) {
LOG.warn("Unexpected byte at position 2 for volume: {}", payload[1]);
return Collections.emptyList();
}
final int volume = payload[3];
if (volume < 0 || volume > 30) {
LOG.warn("Volume {} is out of range", String.format("%02x", payload[3]));
return Collections.emptyList();
}
LOG.debug("Volume: {}", volume);
final GBDeviceEventUpdatePreferences eventUpdatePreferences = new GBDeviceEventUpdatePreferences()
.withPreference(DeviceSettingsPreferenceConst.PREF_VOLUME, volume);
return Collections.singletonList(eventUpdatePreferences);
}
public List<? extends GBDeviceEvent> handleNoiseCancellingOptimizerStatus(final byte[] payload) {
if (payload.length != 4) {
LOG.warn("Unexpected payload length {}", payload.length);

View File

@ -375,6 +375,18 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
);
}
@Override
public Request getVolume() {
LOG.warn("Volume not implemented for V2");
return null;
}
@Override
public Request setVolume(final int volume) {
LOG.warn("Volume not implemented for V2");
return null;
}
@Override
public List<? extends GBDeviceEvent> handlePayload(final MessageType messageType, final byte[] payload) {
final PayloadTypeV2 payloadType = PayloadTypeV2.fromCode(messageType, payload[0]);

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SeekBarPreference
android:defaultValue="15"
android:icon="@drawable/ic_volume_up"
android:key="volume"
android:max="30"
android:title="@string/menuitem_volume" />
</androidx.preference.PreferenceScreen>