mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-01-12 18:57:36 +01:00
Sony LinkBuds: Initial support
This commit is contained in:
parent
5798466e55
commit
fcc930749e
@ -373,6 +373,8 @@ public class DeviceSettingsPreferenceConst {
|
|||||||
public static final String PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE = "pref_sony_speak_to_chat_focus_on_voice";
|
public static final String PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE = "pref_sony_speak_to_chat_focus_on_voice";
|
||||||
public static final String PREF_SONY_SPEAK_TO_CHAT_TIMEOUT = "pref_sony_speak_to_chat_timeout";
|
public static final String PREF_SONY_SPEAK_TO_CHAT_TIMEOUT = "pref_sony_speak_to_chat_timeout";
|
||||||
public static final String PREF_SONY_CONNECT_TWO_DEVICES = "pref_sony_connect_two_devices";
|
public static final String PREF_SONY_CONNECT_TWO_DEVICES = "pref_sony_connect_two_devices";
|
||||||
|
public static final String PREF_SONY_ADAPTIVE_VOLUME_CONTROL = "pref_adaptive_volume_control";
|
||||||
|
public static final String PREF_SONY_WIDE_AREA_TAP = "pref_wide_area_tap";
|
||||||
|
|
||||||
public static final String PREF_QC35_NOISE_CANCELLING_LEVEL = "qc35_noise_cancelling_level";
|
public static final String PREF_QC35_NOISE_CANCELLING_LEVEL = "qc35_noise_cancelling_level";
|
||||||
|
|
||||||
|
@ -533,6 +533,8 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
|
|||||||
addPreferenceHandlerFor(PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE);
|
addPreferenceHandlerFor(PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE);
|
||||||
addPreferenceHandlerFor(PREF_SONY_SPEAK_TO_CHAT_TIMEOUT);
|
addPreferenceHandlerFor(PREF_SONY_SPEAK_TO_CHAT_TIMEOUT);
|
||||||
addPreferenceHandlerFor(PREF_SONY_CONNECT_TWO_DEVICES);
|
addPreferenceHandlerFor(PREF_SONY_CONNECT_TWO_DEVICES);
|
||||||
|
addPreferenceHandlerFor(PREF_SONY_ADAPTIVE_VOLUME_CONTROL);
|
||||||
|
addPreferenceHandlerFor(PREF_SONY_WIDE_AREA_TAP);
|
||||||
addPreferenceHandlerFor(PREF_FEMOMETER_MEASUREMENT_MODE);
|
addPreferenceHandlerFor(PREF_FEMOMETER_MEASUREMENT_MODE);
|
||||||
|
|
||||||
addPreferenceHandlerFor(PREF_QC35_NOISE_CANCELLING_LEVEL);
|
addPreferenceHandlerFor(PREF_QC35_NOISE_CANCELLING_LEVEL);
|
||||||
|
@ -25,6 +25,7 @@ public enum SonyHeadphonesCapabilities {
|
|||||||
WindNoiseReduction,
|
WindNoiseReduction,
|
||||||
SpeakToChatEnabled,
|
SpeakToChatEnabled,
|
||||||
SpeakToChatConfig,
|
SpeakToChatConfig,
|
||||||
|
SpeakToChatFocusOnVoice,
|
||||||
AncOptimizer,
|
AncOptimizer,
|
||||||
AudioSettingsOnlyOnSbcCodec,
|
AudioSettingsOnlyOnSbcCodec,
|
||||||
AudioUpsampling,
|
AudioUpsampling,
|
||||||
@ -41,4 +42,6 @@ public enum SonyHeadphonesCapabilities {
|
|||||||
QuickAccess,
|
QuickAccess,
|
||||||
PauseWhenTakenOff,
|
PauseWhenTakenOff,
|
||||||
Volume,
|
Volume,
|
||||||
|
WideAreaTap,
|
||||||
|
AdaptiveVolumeControl,
|
||||||
}
|
}
|
||||||
|
@ -176,17 +176,21 @@ public abstract class SonyHeadphonesCoordinator extends AbstractBLClassicDeviceC
|
|||||||
settings.add(R.xml.devicesettings_sony_headphones_ambient_sound_control);
|
settings.add(R.xml.devicesettings_sony_headphones_ambient_sound_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supports(SonyHeadphonesCapabilities.AncOptimizer)) {
|
if (supports(SonyHeadphonesCapabilities.AncOptimizer)) {
|
||||||
settings.add(R.xml.devicesettings_sony_headphones_anc_optimizer);
|
settings.add(R.xml.devicesettings_sony_headphones_anc_optimizer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (supports(SonyHeadphonesCapabilities.AdaptiveVolumeControl)) {
|
||||||
|
settings.add(R.xml.devicesettings_sony_headphones_adaptive_volume_control);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
addSettingsUnderHeader(settings, R.xml.devicesettings_header_other, new LinkedHashMap<SonyHeadphonesCapabilities, Integer>() {{
|
addSettingsUnderHeader(settings, R.xml.devicesettings_header_other, new LinkedHashMap<SonyHeadphonesCapabilities, Integer>() {{
|
||||||
put(SonyHeadphonesCapabilities.AudioSettingsOnlyOnSbcCodec, R.xml.devicesettings_sony_warning_wh1000xm3);
|
put(SonyHeadphonesCapabilities.AudioSettingsOnlyOnSbcCodec, R.xml.devicesettings_sony_warning_wh1000xm3);
|
||||||
put(SonyHeadphonesCapabilities.EqualizerSimple, R.xml.devicesettings_sony_headphones_equalizer);
|
put(SonyHeadphonesCapabilities.EqualizerSimple, R.xml.devicesettings_sony_headphones_equalizer);
|
||||||
@ -198,6 +202,7 @@ public abstract class SonyHeadphonesCoordinator extends AbstractBLClassicDeviceC
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
addSettingsUnderHeader(settings, R.xml.devicesettings_header_system, new LinkedHashMap<SonyHeadphonesCapabilities, Integer>() {{
|
addSettingsUnderHeader(settings, R.xml.devicesettings_header_system, new LinkedHashMap<SonyHeadphonesCapabilities, Integer>() {{
|
||||||
|
put(SonyHeadphonesCapabilities.WideAreaTap, R.xml.devicesettings_sony_headphones_wide_area_tap);
|
||||||
put(SonyHeadphonesCapabilities.ButtonModesLeftRight, R.xml.devicesettings_sony_headphones_button_modes_left_right);
|
put(SonyHeadphonesCapabilities.ButtonModesLeftRight, R.xml.devicesettings_sony_headphones_button_modes_left_right);
|
||||||
put(SonyHeadphonesCapabilities.AmbientSoundControlButtonMode, R.xml.devicesettings_sony_headphones_ambient_sound_control_button_modes);
|
put(SonyHeadphonesCapabilities.AmbientSoundControlButtonMode, R.xml.devicesettings_sony_headphones_ambient_sound_control_button_modes);
|
||||||
put(SonyHeadphonesCapabilities.QuickAccess, R.xml.devicesettings_sony_headphones_quick_access);
|
put(SonyHeadphonesCapabilities.QuickAccess, R.xml.devicesettings_sony_headphones_quick_access);
|
||||||
|
@ -32,6 +32,7 @@ import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.Dev
|
|||||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_NOISE_OPTIMIZER_START;
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_NOISE_OPTIMIZER_START;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_NOISE_OPTIMIZER_STATUS;
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_NOISE_OPTIMIZER_STATUS;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_SOUND_POSITION;
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_SOUND_POSITION;
|
||||||
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_SURROUND_MODE;
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SONY_SURROUND_MODE;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
@ -54,6 +55,7 @@ import java.util.Set;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsHandler;
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||||
@ -117,6 +119,8 @@ public class SonyHeadphonesSettingsCustomizer implements DeviceSpecificSettingsC
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void customizeSettings(final DeviceSpecificSettingsHandler handler, Prefs prefs) {
|
public void customizeSettings(final DeviceSpecificSettingsHandler handler, Prefs prefs) {
|
||||||
|
final SonyHeadphonesCoordinator coordinator = (SonyHeadphonesCoordinator) device.getDeviceCoordinator();
|
||||||
|
|
||||||
// Only enable the focus on voice check and voice level slider if the ambient sound control mode is ambient sound
|
// Only enable the focus on voice check and voice level slider if the ambient sound control mode is ambient sound
|
||||||
|
|
||||||
final ListPreference ambientSoundControl = handler.findPreference(PREF_SONY_AMBIENT_SOUND_CONTROL);
|
final ListPreference ambientSoundControl = handler.findPreference(PREF_SONY_AMBIENT_SOUND_CONTROL);
|
||||||
@ -185,6 +189,12 @@ public class SonyHeadphonesSettingsCustomizer implements DeviceSpecificSettingsC
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hide unsupported preferences
|
||||||
|
final Preference speakToChatFocusVoice = handler.findPreference(PREF_SONY_SPEAK_TO_CHAT_FOCUS_ON_VOICE);
|
||||||
|
if (speakToChatFocusVoice != null && !coordinator.supports(SonyHeadphonesCapabilities.SpeakToChatFocusOnVoice)) {
|
||||||
|
speakToChatFocusVoice.setVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
/* 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.devices.sony.headphones.coordinators;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
||||||
|
|
||||||
|
public class SonyLinkBudsCoordinator extends SonyHeadphonesCoordinator {
|
||||||
|
@Override
|
||||||
|
protected Pattern getSupportedDeviceName() {
|
||||||
|
// TODO fully exclude LE_LinkBuds?
|
||||||
|
return Pattern.compile("^LinkBuds$");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SonyHeadphonesCapabilities> getCapabilities() {
|
||||||
|
return Arrays.asList(
|
||||||
|
SonyHeadphonesCapabilities.BatteryDual,
|
||||||
|
SonyHeadphonesCapabilities.BatteryCase,
|
||||||
|
SonyHeadphonesCapabilities.SpeakToChatEnabled,
|
||||||
|
SonyHeadphonesCapabilities.SpeakToChatConfig,
|
||||||
|
SonyHeadphonesCapabilities.AdaptiveVolumeControl,
|
||||||
|
SonyHeadphonesCapabilities.EqualizerWithCustomBands,
|
||||||
|
SonyHeadphonesCapabilities.AudioUpsampling,
|
||||||
|
SonyHeadphonesCapabilities.ButtonModesLeftRight,
|
||||||
|
SonyHeadphonesCapabilities.PauseWhenTakenOff,
|
||||||
|
SonyHeadphonesCapabilities.AutomaticPowerOffWhenTakenOff,
|
||||||
|
SonyHeadphonesCapabilities.WideAreaTap,
|
||||||
|
SonyHeadphonesCapabilities.VoiceNotifications
|
||||||
|
// TODO spacial sound optimization
|
||||||
|
// TODO factory reset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preferServiceV2() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDeviceNameResource() {
|
||||||
|
return R.string.devicetype_sony_linkbuds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDefaultIconResource() {
|
||||||
|
return R.drawable.ic_device_galaxy_buds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDisabledIconResource() {
|
||||||
|
return R.drawable.ic_device_galaxy_buds_disabled;
|
||||||
|
}
|
||||||
|
}
|
@ -16,8 +16,6 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators;
|
package nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -25,8 +23,6 @@ import java.util.regex.Pattern;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
|
||||||
|
|
||||||
public class SonyLinkBudsSCoordinator extends SonyHeadphonesCoordinator {
|
public class SonyLinkBudsSCoordinator extends SonyHeadphonesCoordinator {
|
||||||
@Override
|
@Override
|
||||||
@ -55,13 +51,11 @@ public class SonyLinkBudsSCoordinator extends SonyHeadphonesCoordinator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDeviceNameResource() {
|
public int getDeviceNameResource() {
|
||||||
return R.string.devicetype_sony_linkbuds_s;
|
return R.string.devicetype_sony_linkbuds_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDefaultIconResource() {
|
public int getDefaultIconResource() {
|
||||||
return R.drawable.ic_device_galaxy_buds;
|
return R.drawable.ic_device_galaxy_buds;
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators;
|
package nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -25,8 +23,6 @@ import java.util.regex.Pattern;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
|
||||||
|
|
||||||
public class SonyWH1000XM4Coordinator extends SonyHeadphonesCoordinator {
|
public class SonyWH1000XM4Coordinator extends SonyHeadphonesCoordinator {
|
||||||
@Override
|
@Override
|
||||||
@ -49,6 +45,7 @@ public class SonyWH1000XM4Coordinator extends SonyHeadphonesCoordinator {
|
|||||||
SonyHeadphonesCapabilities.WindNoiseReduction,
|
SonyHeadphonesCapabilities.WindNoiseReduction,
|
||||||
SonyHeadphonesCapabilities.SpeakToChatEnabled,
|
SonyHeadphonesCapabilities.SpeakToChatEnabled,
|
||||||
SonyHeadphonesCapabilities.SpeakToChatConfig,
|
SonyHeadphonesCapabilities.SpeakToChatConfig,
|
||||||
|
SonyHeadphonesCapabilities.SpeakToChatFocusOnVoice,
|
||||||
SonyHeadphonesCapabilities.AncOptimizer,
|
SonyHeadphonesCapabilities.AncOptimizer,
|
||||||
SonyHeadphonesCapabilities.EqualizerWithCustomBands,
|
SonyHeadphonesCapabilities.EqualizerWithCustomBands,
|
||||||
SonyHeadphonesCapabilities.AudioUpsampling,
|
SonyHeadphonesCapabilities.AudioUpsampling,
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators;
|
package nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -25,8 +23,6 @@ import java.util.regex.Pattern;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
|
||||||
|
|
||||||
public class SonyWH1000XM5Coordinator extends SonyHeadphonesCoordinator {
|
public class SonyWH1000XM5Coordinator extends SonyHeadphonesCoordinator {
|
||||||
@Override
|
@Override
|
||||||
@ -49,6 +45,7 @@ public class SonyWH1000XM5Coordinator extends SonyHeadphonesCoordinator {
|
|||||||
SonyHeadphonesCapabilities.AmbientSoundControl,
|
SonyHeadphonesCapabilities.AmbientSoundControl,
|
||||||
SonyHeadphonesCapabilities.SpeakToChatEnabled,
|
SonyHeadphonesCapabilities.SpeakToChatEnabled,
|
||||||
SonyHeadphonesCapabilities.SpeakToChatConfig,
|
SonyHeadphonesCapabilities.SpeakToChatConfig,
|
||||||
|
SonyHeadphonesCapabilities.SpeakToChatFocusOnVoice,
|
||||||
// TODO SonyHeadphonesCapabilities.AudioUpsampling,
|
// TODO SonyHeadphonesCapabilities.AudioUpsampling,
|
||||||
// TODO SonyHeadphonesCapabilities.AmbientSoundControlButtonMode,
|
// TODO SonyHeadphonesCapabilities.AmbientSoundControlButtonMode,
|
||||||
SonyHeadphonesCapabilities.VoiceNotifications,
|
SonyHeadphonesCapabilities.VoiceNotifications,
|
||||||
|
@ -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.devices.sony.headphones.prefs;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||||
|
|
||||||
|
public class AdaptiveVolumeControl {
|
||||||
|
private final boolean enabled;
|
||||||
|
|
||||||
|
public AdaptiveVolumeControl(final boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> toPreferences() {
|
||||||
|
return new HashMap<String, Object>() {{
|
||||||
|
put(DeviceSettingsPreferenceConst.PREF_SONY_ADAPTIVE_VOLUME_CONTROL, enabled);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AdaptiveVolumeControl fromPreferences(final SharedPreferences prefs) {
|
||||||
|
return new AdaptiveVolumeControl(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SONY_ADAPTIVE_VOLUME_CONTROL, true));
|
||||||
|
}
|
||||||
|
}
|
@ -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.devices.sony.headphones.prefs;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||||
|
|
||||||
|
public class WideAreaTap {
|
||||||
|
private final boolean enabled;
|
||||||
|
|
||||||
|
public WideAreaTap(final boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> toPreferences() {
|
||||||
|
return new HashMap<String, Object>() {{
|
||||||
|
put(DeviceSettingsPreferenceConst.PREF_SONY_WIDE_AREA_TAP, enabled);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WideAreaTap fromPreferences(final SharedPreferences prefs) {
|
||||||
|
return new WideAreaTap(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SONY_WIDE_AREA_TAP, true));
|
||||||
|
}
|
||||||
|
}
|
@ -150,6 +150,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.roidmi.Roidmi1Coordinator;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.roidmi.Roidmi3Coordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.roidmi.Roidmi3Coordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.smaq2oss.SMAQ2OSSCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.smaq2oss.SMAQ2OSSCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.soflow.SoFlowCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.soflow.SoFlowCoordinator;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyLinkBudsCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyLinkBudsSCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyLinkBudsSCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM3Coordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM3Coordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM4Coordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.coordinators.SonyWF1000XM4Coordinator;
|
||||||
@ -335,6 +336,7 @@ public enum DeviceType {
|
|||||||
SONY_WF_1000XM3(SonyWF1000XM3Coordinator.class),
|
SONY_WF_1000XM3(SonyWF1000XM3Coordinator.class),
|
||||||
SONY_WH_1000XM2(SonyWH1000XM2Coordinator.class),
|
SONY_WH_1000XM2(SonyWH1000XM2Coordinator.class),
|
||||||
SONY_WF_1000XM4(SonyWF1000XM4Coordinator.class),
|
SONY_WF_1000XM4(SonyWF1000XM4Coordinator.class),
|
||||||
|
SONY_LINKBUDS(SonyLinkBudsCoordinator.class),
|
||||||
SONY_LINKBUDS_S(SonyLinkBudsSCoordinator.class),
|
SONY_LINKBUDS_S(SonyLinkBudsSCoordinator.class),
|
||||||
SONY_WH_1000XM5(SonyWH1000XM5Coordinator.class),
|
SONY_WH_1000XM5(SonyWH1000XM5Coordinator.class),
|
||||||
SONY_WF_1000XM5(SonyWF1000XM5Coordinator.class),
|
SONY_WF_1000XM5(SonyWF1000XM5Coordinator.class),
|
||||||
|
@ -32,6 +32,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceState;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceState;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AdaptiveVolumeControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AudioUpsampling;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AudioUpsampling;
|
||||||
@ -47,6 +48,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceN
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SoundPosition;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SoundPosition;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SurroundMode;
|
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.TouchSensor;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.WideAreaTap;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.Request;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.Request;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.Message;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.Message;
|
||||||
@ -126,6 +128,7 @@ public class SonyHeadphonesProtocol extends GBDeviceProtocol {
|
|||||||
// LinkBuds S 2.0.2: 01:00:03:00:00:07:00:00
|
// LinkBuds S 2.0.2: 01:00:03:00:00:07:00:00
|
||||||
// WH-1000XM5 1.1.3: 01:00:03:00:00:00:00:00
|
// WH-1000XM5 1.1.3: 01:00:03:00:00:00:00:00
|
||||||
// WF-1000XM5 2.0.1: 01:00:03:00:10:04:00:00
|
// WF-1000XM5 2.0.1: 01:00:03:00:10:04:00:00
|
||||||
|
// LinkBuds 1.0.3: 01:00:02:00:10:00:00:00
|
||||||
protocolVersion = "v2";
|
protocolVersion = "v2";
|
||||||
} else {
|
} else {
|
||||||
LOG.error("Unexpected init response payload length: {}", message.getPayload().length);
|
LOG.error("Unexpected init response payload length: {}", message.getPayload().length);
|
||||||
@ -260,6 +263,12 @@ public class SonyHeadphonesProtocol extends GBDeviceProtocol {
|
|||||||
case DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_TIMEOUT:
|
case DeviceSettingsPreferenceConst.PREF_SONY_SPEAK_TO_CHAT_TIMEOUT:
|
||||||
configRequest = protocolImpl.setSpeakToChatConfig(SpeakToChatConfig.fromPreferences(prefs));
|
configRequest = protocolImpl.setSpeakToChatConfig(SpeakToChatConfig.fromPreferences(prefs));
|
||||||
break;
|
break;
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SONY_ADAPTIVE_VOLUME_CONTROL:
|
||||||
|
configRequest = protocolImpl.setAdaptiveVolumeControl(AdaptiveVolumeControl.fromPreferences(prefs));
|
||||||
|
break;
|
||||||
|
case DeviceSettingsPreferenceConst.PREF_SONY_WIDE_AREA_TAP:
|
||||||
|
configRequest = protocolImpl.setWideAreaTap(WideAreaTap.fromPreferences(prefs));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG.warn("Unknown config '{}'", config);
|
LOG.warn("Unknown config '{}'", config);
|
||||||
return super.encodeSendConfiguration(config);
|
return super.encodeSendConfiguration(config);
|
||||||
|
@ -20,6 +20,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AdaptiveVolumeControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AudioUpsampling;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AudioUpsampling;
|
||||||
@ -35,6 +36,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakT
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SurroundMode;
|
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.TouchSensor;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.WideAreaTap;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.Request;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.Request;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.MessageType;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.MessageType;
|
||||||
@ -60,6 +62,11 @@ public abstract class AbstractSonyProtocolImpl {
|
|||||||
|
|
||||||
public abstract Request setAmbientSoundControl(final AmbientSoundControl config);
|
public abstract Request setAmbientSoundControl(final AmbientSoundControl config);
|
||||||
|
|
||||||
|
|
||||||
|
public abstract Request setAdaptiveVolumeControl(final AdaptiveVolumeControl config);
|
||||||
|
|
||||||
|
public abstract Request getAdaptiveVolumeControl();
|
||||||
|
|
||||||
public abstract Request setSpeakToChatEnabled(final SpeakToChatEnabled config);
|
public abstract Request setSpeakToChatEnabled(final SpeakToChatEnabled config);
|
||||||
|
|
||||||
public abstract Request getSpeakToChatEnabled();
|
public abstract Request getSpeakToChatEnabled();
|
||||||
@ -84,6 +91,10 @@ public abstract class AbstractSonyProtocolImpl {
|
|||||||
|
|
||||||
public abstract Request setAutomaticPowerOff(final AutomaticPowerOff config);
|
public abstract Request setAutomaticPowerOff(final AutomaticPowerOff config);
|
||||||
|
|
||||||
|
public abstract Request setWideAreaTap(final WideAreaTap config);
|
||||||
|
|
||||||
|
public abstract Request getWideAreaTap();
|
||||||
|
|
||||||
public abstract Request getButtonModes();
|
public abstract Request getButtonModes();
|
||||||
|
|
||||||
public abstract Request setButtonModes(final ButtonModes config);
|
public abstract Request setButtonModes(final ButtonModes config);
|
||||||
|
@ -40,6 +40,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePref
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AdaptiveVolumeControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AudioUpsampling;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AudioUpsampling;
|
||||||
@ -55,6 +56,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakT
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SurroundMode;
|
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.TouchSensor;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.WideAreaTap;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.deviceevents.SonyHeadphonesEnqueueRequestEvent;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.deviceevents.SonyHeadphonesEnqueueRequestEvent;
|
||||||
@ -141,6 +143,18 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
|
|||||||
return new Request(PayloadTypeV1.AMBIENT_SOUND_CONTROL_SET.getMessageType(), buf.array());
|
return new Request(PayloadTypeV1.AMBIENT_SOUND_CONTROL_SET.getMessageType(), buf.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request setAdaptiveVolumeControl(final AdaptiveVolumeControl config) {
|
||||||
|
LOG.warn("Adaptive volume control not implemented for V1");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request getAdaptiveVolumeControl() {
|
||||||
|
LOG.warn("Adaptive volume control not implemented for V1");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Request setSpeakToChatEnabled(final SpeakToChatEnabled config) {
|
public Request setSpeakToChatEnabled(final SpeakToChatEnabled config) {
|
||||||
return new Request(
|
return new Request(
|
||||||
@ -284,6 +298,18 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request setWideAreaTap(final WideAreaTap config) {
|
||||||
|
LOG.warn("Adaptive volume control not implemented for V1");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request getWideAreaTap() {
|
||||||
|
LOG.warn("Adaptive volume control not implemented for V1");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Request getButtonModes() {
|
public Request getButtonModes() {
|
||||||
return new Request(
|
return new Request(
|
||||||
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
|
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
|
||||||
@ -631,6 +657,8 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
|
|||||||
put(SonyHeadphonesCapabilities.AmbientSoundControlButtonMode, getAmbientSoundControlButtonMode());
|
put(SonyHeadphonesCapabilities.AmbientSoundControlButtonMode, getAmbientSoundControlButtonMode());
|
||||||
put(SonyHeadphonesCapabilities.QuickAccess, getQuickAccess());
|
put(SonyHeadphonesCapabilities.QuickAccess, getQuickAccess());
|
||||||
put(SonyHeadphonesCapabilities.Volume, getVolume());
|
put(SonyHeadphonesCapabilities.Volume, getVolume());
|
||||||
|
put(SonyHeadphonesCapabilities.AdaptiveVolumeControl, getAdaptiveVolumeControl());
|
||||||
|
put(SonyHeadphonesCapabilities.WideAreaTap, getWideAreaTap());
|
||||||
}};
|
}};
|
||||||
|
|
||||||
for (Map.Entry<SonyHeadphonesCapabilities, Request> capabilityEntry : capabilityRequestMap.entrySet()) {
|
for (Map.Entry<SonyHeadphonesCapabilities, Request> capabilityEntry : capabilityRequestMap.entrySet()) {
|
||||||
|
@ -29,6 +29,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSett
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdateDeviceInfo;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AdaptiveVolumeControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AmbientSoundControlButtonMode;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AudioUpsampling;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.AudioUpsampling;
|
||||||
@ -44,6 +45,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SpeakT
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.SurroundMode;
|
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.TouchSensor;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications;
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.VoiceNotifications;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.prefs.WideAreaTap;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.MessageType;
|
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.Request;
|
||||||
@ -105,6 +107,29 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
|
|||||||
return new Request(PayloadTypeV1.AMBIENT_SOUND_CONTROL_SET.getMessageType(), buf.array());
|
return new Request(PayloadTypeV1.AMBIENT_SOUND_CONTROL_SET.getMessageType(), buf.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request setAdaptiveVolumeControl(final AdaptiveVolumeControl config) {
|
||||||
|
return new Request(
|
||||||
|
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getMessageType(),
|
||||||
|
new byte[]{
|
||||||
|
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getCode(),
|
||||||
|
(byte) 0x0a,
|
||||||
|
(byte) (config.isEnabled() ? 0x00 : 0x01) // this is reversed on V2...?
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request getAdaptiveVolumeControl() {
|
||||||
|
return new Request(
|
||||||
|
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
|
||||||
|
new byte[]{
|
||||||
|
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getCode(),
|
||||||
|
(byte) 0x0a
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Request setSpeakToChatEnabled(SpeakToChatEnabled config) {
|
public Request setSpeakToChatEnabled(SpeakToChatEnabled config) {
|
||||||
return new Request(
|
return new Request(
|
||||||
@ -233,6 +258,30 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request setWideAreaTap(final WideAreaTap config) {
|
||||||
|
return new Request(
|
||||||
|
PayloadTypeV1.TOUCH_SENSOR_SET.getMessageType(),
|
||||||
|
new byte[]{
|
||||||
|
PayloadTypeV1.TOUCH_SENSOR_SET.getCode(),
|
||||||
|
(byte) 0xd1,
|
||||||
|
(byte) 0x00,
|
||||||
|
(byte) (config.isEnabled() ? 0x00 : 0x01) // this is reversed on V2...?
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request getWideAreaTap() {
|
||||||
|
return new Request(
|
||||||
|
PayloadTypeV1.TOUCH_SENSOR_GET.getMessageType(),
|
||||||
|
new byte[]{
|
||||||
|
PayloadTypeV1.TOUCH_SENSOR_GET.getCode(),
|
||||||
|
(byte) 0xd1
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Request getButtonModes() {
|
public Request getButtonModes() {
|
||||||
return new Request(
|
return new Request(
|
||||||
@ -627,6 +676,31 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
|
|||||||
return Collections.singletonList(event);
|
return Collections.singletonList(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<? extends GBDeviceEvent> handleAdaptiveVolumeControl(final byte[] payload) {
|
||||||
|
if (payload.length != 3) {
|
||||||
|
LOG.warn("Unexpected payload length {}", payload.length);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload[1] != 0x0a) {
|
||||||
|
LOG.warn("Not adaptive volume control, ignoring");
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Boolean disabled = booleanFromByte(payload[2]);
|
||||||
|
if (disabled == null) {
|
||||||
|
LOG.warn("Unknown adaptive volume control code {}", String.format("%02x", payload[2]));
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("Adaptive volume control: {}", !disabled);
|
||||||
|
|
||||||
|
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences()
|
||||||
|
.withPreferences(new AdaptiveVolumeControl(!disabled).toPreferences());
|
||||||
|
|
||||||
|
return Collections.singletonList(event);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends GBDeviceEvent> handleSpeakToChatEnabled(final byte[] payload) {
|
public List<? extends GBDeviceEvent> handleSpeakToChatEnabled(final byte[] payload) {
|
||||||
if (payload.length != 4) {
|
if (payload.length != 4) {
|
||||||
@ -653,6 +727,40 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
|
|||||||
return Collections.singletonList(event);
|
return Collections.singletonList(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends GBDeviceEvent> handleSpeakToChatConfig(final byte[] payload) {
|
||||||
|
if (payload.length != 4) {
|
||||||
|
LOG.warn("Unexpected payload length {}", payload.length);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload[1] != 0x0c) {
|
||||||
|
LOG.warn("Not speak to chat config, ignoring");
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final SpeakToChatConfig.Sensitivity sensitivity = SpeakToChatConfig.Sensitivity.fromCode(payload[2]);
|
||||||
|
if (sensitivity == null) {
|
||||||
|
LOG.warn("Unknown sensitivity code {}", String.format("%02x", payload[2]));
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final SpeakToChatConfig.Timeout timeout = SpeakToChatConfig.Timeout.fromCode(payload[3]);
|
||||||
|
if (timeout == null) {
|
||||||
|
LOG.warn("Unknown timeout code {}", String.format("%02x", payload[3]));
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final SpeakToChatConfig speakToChatConfig = new SpeakToChatConfig(false, sensitivity, timeout);
|
||||||
|
|
||||||
|
LOG.debug("Speak to chat config: {}", speakToChatConfig);
|
||||||
|
|
||||||
|
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences()
|
||||||
|
.withPreferences(speakToChatConfig.toPreferences());
|
||||||
|
|
||||||
|
return Collections.singletonList(event);
|
||||||
|
}
|
||||||
|
|
||||||
public List<? extends GBDeviceEvent> handleQuickAccess(final byte[] payload) {
|
public List<? extends GBDeviceEvent> handleQuickAccess(final byte[] payload) {
|
||||||
if (payload.length != 5) {
|
if (payload.length != 5) {
|
||||||
LOG.warn("Unexpected payload length {}", payload.length);
|
LOG.warn("Unexpected payload length {}", payload.length);
|
||||||
@ -680,6 +788,11 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<? extends GBDeviceEvent> handleAmbientSoundControlButtonMode(final byte[] payload) {
|
public List<? extends GBDeviceEvent> handleAmbientSoundControlButtonMode(final byte[] payload) {
|
||||||
|
if (payload.length == 4 && payload[1] == 0x0c) {
|
||||||
|
// FIXME split this
|
||||||
|
return handleSpeakToChatConfig(payload);
|
||||||
|
}
|
||||||
|
|
||||||
if (payload.length != 7) {
|
if (payload.length != 7) {
|
||||||
LOG.warn("Unexpected payload length {}", payload.length);
|
LOG.warn("Unexpected payload length {}", payload.length);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@ -815,6 +928,8 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
|
|||||||
return handlePauseWhenTakenOff(payload);
|
return handlePauseWhenTakenOff(payload);
|
||||||
case 0x03:
|
case 0x03:
|
||||||
return handleButtonModes(payload);
|
return handleButtonModes(payload);
|
||||||
|
case 0x0a:
|
||||||
|
return handleAdaptiveVolumeControl(payload);
|
||||||
case 0x0c:
|
case 0x0c:
|
||||||
return handleSpeakToChatEnabled(payload);
|
return handleSpeakToChatEnabled(payload);
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
@ -844,8 +959,37 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<? extends GBDeviceEvent> handleTouchSensor(final byte[] payload) {
|
public List<? extends GBDeviceEvent> handleTouchSensor(final byte[] payload) {
|
||||||
LOG.warn("Touch sensor not implemented for V2");
|
if (payload.length != 4) {
|
||||||
return Collections.emptyList();
|
LOG.warn("Unexpected payload length {}", payload.length);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload[1] != (byte) 0xd1) {
|
||||||
|
LOG.warn("Not wide area tap");
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean enabled;
|
||||||
|
|
||||||
|
// reversed?
|
||||||
|
switch (payload[3]) {
|
||||||
|
case 0x00:
|
||||||
|
enabled = true;
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
enabled = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG.warn("Unknown wide area tap code {}", String.format("%02x", payload[3]));
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("Wide Area Tap: {}", enabled);
|
||||||
|
|
||||||
|
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences()
|
||||||
|
.withPreferences(new WideAreaTap(enabled).toPreferences());
|
||||||
|
|
||||||
|
return Collections.singletonList(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1521,6 +1521,7 @@
|
|||||||
<string name="devicetype_sony_wf_1000xm4">Sony WF-1000XM4</string>
|
<string name="devicetype_sony_wf_1000xm4">Sony WF-1000XM4</string>
|
||||||
<string name="devicetype_sony_wf_1000xm5">Sony WF-1000XM5</string>
|
<string name="devicetype_sony_wf_1000xm5">Sony WF-1000XM5</string>
|
||||||
<string name="devicetype_sony_wi_sp600n">Sony WI-SP600N</string>
|
<string name="devicetype_sony_wi_sp600n">Sony WI-SP600N</string>
|
||||||
|
<string name="devicetype_sony_linkbuds">Sony LinkBuds</string>
|
||||||
<string name="devicetype_sony_linkbuds_s">Sony LinkBuds S</string>
|
<string name="devicetype_sony_linkbuds_s">Sony LinkBuds S</string>
|
||||||
<string name="devicetype_binary_sensor">Binary sensor</string>
|
<string name="devicetype_binary_sensor">Binary sensor</string>
|
||||||
<string name="devicetype_honor_band3">Honor Band 3</string>
|
<string name="devicetype_honor_band3">Honor Band 3</string>
|
||||||
@ -2174,6 +2175,7 @@
|
|||||||
<string name="pref_header_stress">Stress</string>
|
<string name="pref_header_stress">Stress</string>
|
||||||
<string name="pref_header_spo2">Blood Oxygen</string>
|
<string name="pref_header_spo2">Blood Oxygen</string>
|
||||||
<string name="pref_header_sony_ambient_sound_control">Ambient Sound Control</string>
|
<string name="pref_header_sony_ambient_sound_control">Ambient Sound Control</string>
|
||||||
|
<string name="pref_header_sony_sound_control">Sound Control</string>
|
||||||
<string name="pref_header_sony_device_info">Device Information</string>
|
<string name="pref_header_sony_device_info">Device Information</string>
|
||||||
<string name="stress_relaxed">Relaxed</string>
|
<string name="stress_relaxed">Relaxed</string>
|
||||||
<string name="stress_mild">Mild</string>
|
<string name="stress_mild">Mild</string>
|
||||||
@ -2238,6 +2240,10 @@
|
|||||||
<string name="sony_equalizer_clear_bass">Clear Bass</string>
|
<string name="sony_equalizer_clear_bass">Clear Bass</string>
|
||||||
<string name="sony_audio_upsampling">Audio Upsampling</string>
|
<string name="sony_audio_upsampling">Audio Upsampling</string>
|
||||||
<string name="sony_touch_sensor">Touch sensor control</string>
|
<string name="sony_touch_sensor">Touch sensor control</string>
|
||||||
|
<string name="pref_wide_area_tap_summary">Recognize taps between cheeks and ears</string>
|
||||||
|
<string name="pref_wide_area_tap_title">Wide area tap</string>
|
||||||
|
<string name="pref_adaptive_volume_control_summary">Increase volume automatically when ambient sound is loud</string>
|
||||||
|
<string name="pref_adaptive_volume_control_title">Adaptive volume control</string>
|
||||||
<string name="sony_speak_to_chat">Speak-to-chat</string>
|
<string name="sony_speak_to_chat">Speak-to-chat</string>
|
||||||
<string name="sony_speak_to_chat_summary">Turn off noise cancelling automatically when you start talking.</string>
|
<string name="sony_speak_to_chat_summary">Turn off noise cancelling automatically when you start talking.</string>
|
||||||
<string name="sony_speak_to_chat_sensitivity">Voice Detection Sensitivity</string>
|
<string name="sony_speak_to_chat_sensitivity">Voice Detection Sensitivity</string>
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="pref_key_header_sony_ambient_sound_control"
|
||||||
|
android:title="@string/pref_header_sony_sound_control">
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:icon="@drawable/ic_hearing"
|
||||||
|
android:key="pref_adaptive_volume_control"
|
||||||
|
android:summary="@string/pref_adaptive_volume_control_summary"
|
||||||
|
android:title="@string/pref_adaptive_volume_control_title" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
</androidx.preference.PreferenceScreen>
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:icon="@drawable/ic_touch"
|
||||||
|
android:key="pref_wide_area_tap"
|
||||||
|
android:summary="@string/pref_wide_area_tap_summary"
|
||||||
|
android:title="@string/pref_wide_area_tap_title" />
|
||||||
|
</androidx.preference.PreferenceScreen>
|
Loading…
x
Reference in New Issue
Block a user