From f042221c916574c5ac4e15c2a87b35520b67390a Mon Sep 17 00:00:00 2001 From: gordas-debug Date: Wed, 15 Jul 2026 15:16:03 +0300 Subject: [PATCH 1/2] Add configurable music auto-ducking --- .../java/com/cooper/wheellog/AppConfig.kt | 16 +++ .../java/com/cooper/wheellog/WheelData.java | 110 +++++++++++++++++- .../wheellog/settings/ApplicationScreen.kt | 63 +++++++++- app/src/main/res/values-ru/strings.xml | 14 ++- app/src/main/res/values/strings.xml | 14 ++- 5 files changed, 205 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/cooper/wheellog/AppConfig.kt b/app/src/main/java/com/cooper/wheellog/AppConfig.kt index 15d5d892e..3f18d02e5 100644 --- a/app/src/main/java/com/cooper/wheellog/AppConfig.kt +++ b/app/src/main/java/com/cooper/wheellog/AppConfig.kt @@ -152,6 +152,22 @@ class AppConfig(var context: Context): KoinComponent { get() = getValue(R.string.use_stop_music, false) set(value) = setValue(R.string.use_stop_music, value) + var stopMusicSpeed: Int + get() = getValue("stop_music_speed", 10) + set(value) = setValue("stop_music_speed", value) + + var stopMusicLowVolume: Int + get() = getValue("stop_music_low_volume", 5) + set(value) = setValue("stop_music_low_volume", value) + + var stopMusicRestoreDelay: Int + get() = getValue("stop_music_restore_delay", 3) + set(value) = setValue("stop_music_restore_delay", value) + + var stopMusicHighSpeed: Int + get() = getValue("stop_music_high_speed", 50) + set(value) = setValue("stop_music_high_speed", value) + var showUnknownDevices: Boolean get() = getValue(R.string.show_unknown_devices, false) set(value) = setValue(R.string.show_unknown_devices, value) diff --git a/app/src/main/java/com/cooper/wheellog/WheelData.java b/app/src/main/java/com/cooper/wheellog/WheelData.java index a204fb555..6d092450c 100644 --- a/app/src/main/java/com/cooper/wheellog/WheelData.java +++ b/app/src/main/java/com/cooper/wheellog/WheelData.java @@ -102,6 +102,9 @@ public class WheelData { private double mCalculatedPwm = 0.0; private double mMaxPwm = 0.0; private long mLowSpeedMusicTime = 0; + private int mMusicVolumeBeforeQuiet = -1; + private boolean mMusicVolumeChangedByWheelLog = false; + private boolean mMusicMutedByWheelLog = false; private boolean mBmsView = false; private String protoVer = ""; @@ -1143,21 +1146,113 @@ public long getLastLifeData() { } private void CheckMuteMusic() { - if (!appConfig.getUseStopMusic()) + if (!appConfig.getUseStopMusic()) { + releaseMusicControl(); return; + } + + final double lowMuteSpeedThreshold = appConfig.getStopMusicSpeed(); + final double highMuteSpeedThreshold = appConfig.getStopMusicHighSpeed(); - final double muteSpeedThreshold = 3.5; double speed = getSpeedDouble(); - if (speed <= muteSpeedThreshold) { + + if (speed <= lowMuteSpeedThreshold) { mLowSpeedMusicTime = 0; - MainActivity.audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true); + setQuietMusicVolume(); + } else if (speed >= highMuteSpeedThreshold) { + mLowSpeedMusicTime = 0; + muteMusic(); } else { if (mLowSpeedMusicTime == 0) mLowSpeedMusicTime = System.currentTimeMillis(); - if ((System.currentTimeMillis() - mLowSpeedMusicTime) >= 1500) - MainActivity.audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false); + long restoreDelayMs = appConfig.getStopMusicRestoreDelay() * 1000L; + + // Задержка возврата обычной громкости. + // Нужна, чтобы звук не возвращался от краткого скачка скорости на ямке, + // переходе, трамвайных путях и т.п. + if ((System.currentTimeMillis() - mLowSpeedMusicTime) >= restoreDelayMs) + restoreMusicVolume(); + } + } + + private void setQuietMusicVolume() { + if (MainActivity.audioManager == null) + return; + + // Если до этого WheelLog полностью заглушил звук на высокой скорости, + // сначала отпускаем mute. + if (mMusicMutedByWheelLog) { + MainActivity.audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false); + mMusicMutedByWheelLog = false; } + + int currentVolume = MainActivity.audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + + // Запоминаем громкость пользователя только один раз, + // перед первым переходом в тихий режим. + if (!mMusicVolumeChangedByWheelLog) { + mMusicVolumeBeforeQuiet = currentVolume; + mMusicVolumeChangedByWheelLog = true; + } + + int quietVolume = getMusicVolumeByPercent(appConfig.getStopMusicLowVolume()); + + if (currentVolume != quietVolume) { + MainActivity.audioManager.setStreamVolume( + AudioManager.STREAM_MUSIC, + quietVolume, + 0 + ); + } + } + + private void muteMusic() { + if (MainActivity.audioManager == null) + return; + + MainActivity.audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true); + mMusicMutedByWheelLog = true; + } + + private void restoreMusicVolume() { + if (MainActivity.audioManager == null) + return; + + if (mMusicMutedByWheelLog) { + MainActivity.audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false); + mMusicMutedByWheelLog = false; + } + + if (mMusicVolumeChangedByWheelLog && mMusicVolumeBeforeQuiet >= 0) { + MainActivity.audioManager.setStreamVolume( + AudioManager.STREAM_MUSIC, + mMusicVolumeBeforeQuiet, + 0 + ); + } + + mMusicVolumeBeforeQuiet = -1; + mMusicVolumeChangedByWheelLog = false; + } + + private void releaseMusicControl() { + restoreMusicVolume(); + mLowSpeedMusicTime = 0; + } + + private int getMusicVolumeByPercent(int percent) { + if (MainActivity.audioManager == null) + return 0; + + int maxVolume = MainActivity.audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + + percent = Math.max(0, Math.min(percent, 100)); + + if (percent == 0) + return 0; + + return Math.max(1, (int) Math.round(maxVolume * percent / 100.0)); } public void resetRideTime() { @@ -1202,6 +1297,9 @@ void full_reset() { void reset() { mLowSpeedMusicTime = 0; + mMusicVolumeBeforeQuiet = -1; + mMusicVolumeChangedByWheelLog = false; + mMusicMutedByWheelLog = false; mSpeed = 0; mTorque = 0; mMotorPower = 0; diff --git a/app/src/main/java/com/cooper/wheellog/settings/ApplicationScreen.kt b/app/src/main/java/com/cooper/wheellog/settings/ApplicationScreen.kt index 5b5389858..2ba38fb1c 100644 --- a/app/src/main/java/com/cooper/wheellog/settings/ApplicationScreen.kt +++ b/app/src/main/java/com/cooper/wheellog/settings/ApplicationScreen.kt @@ -395,15 +395,74 @@ fun applicationScreen( appConfig.noConnectionSound = it.toInt() } + var useStopMusic by remember { mutableStateOf(appConfig.useStopMusic) } + switchPref( name = stringResource(R.string.use_stop_music_title), desc = stringResource(R.string.use_stop_music_description), themeIcon = ThemeIconEnum.SettingsAutoMute, - default = appConfig.useStopMusic, - showDiv = false, + default = useStopMusic, + showDiv = !useStopMusic, ) { appConfig.useStopMusic = it + useStopMusic = it + } + AnimatedVisibility(visible = useStopMusic) { + Column { + sliderPref( + name = stringResource(R.string.stop_music_speed_title), + desc = stringResource(R.string.stop_music_speed_description), + min = 3f, + max = 20f, + position = appConfig.stopMusicSpeed.toFloat(), + unit = R.string.speed_unit_kmh, + format = "%.0f", + showDiv = true, + ) { + appConfig.stopMusicSpeed = it.toInt() + } + + sliderPref( + name = stringResource(R.string.stop_music_low_volume_title), + desc = stringResource(R.string.stop_music_low_volume_description), + min = 0f, + max = 100f, + position = appConfig.stopMusicLowVolume.toFloat(), + unit = R.string.volume_unit_percent, + format = "%.0f", + showDiv = true, + ) { + appConfig.stopMusicLowVolume = it.toInt() + } + + sliderPref( + name = stringResource(R.string.stop_music_restore_delay_title), + desc = stringResource(R.string.stop_music_restore_delay_description), + min = 1f, + max = 10f, + position = appConfig.stopMusicRestoreDelay.toFloat(), + unit = R.string.sec, + format = "%.0f", + showDiv = true, + ) { + appConfig.stopMusicRestoreDelay = it.toInt() + } + + sliderPref( + name = stringResource(R.string.stop_music_high_speed_title), + desc = stringResource(R.string.stop_music_high_speed_description), + min = 20f, + max = 120f, + position = appConfig.stopMusicHighSpeed.toFloat(), + unit = R.string.speed_unit_kmh, + format = "%.0f", + showDiv = false, + ) { + appConfig.stopMusicHighSpeed = it.toInt() + } + } } + } group(name = stringResource(R.string.connection_category_title)) { diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 3071788b9..8c0932079 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -294,8 +294,18 @@ Измеренная на весу максимальная скорость вращения колеса Напряжение раскрутки Напряжение при котором измерялась скорость раскрутки - Выключение звука - Автовыключение звука при скорости ниже 3.5 км/ч + Автоприглушение музыки + Музыка становится тише на малой скорости и выключается на высокой + Минимальная скорость для обычной громкости + Ниже этой скорости музыка будет тише + Тихая громкость + Громкость музыки на скорости ниже минимальной + Задержка возврата звука + Через сколько секунд вернуть обычную громкость + Максимальная скорость для музыки + Выше этой скорости музыка выключается + км/ч + % Н*м Ограничение тока Ограничение скорости diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 442e68df7..58718cb94 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -221,8 +221,18 @@ Play sound when Wheel connects or disconnects Connection lost beeps period Period of beeps when connection lost, 0sec - no beeps - Auto mute - Auto mute at speeds below 3.5 km/h + Music auto-ducking + Music gets quieter at low speed and is muted at high speed + Minimum speed for normal volume + Below this speed, music gets quieter + Quiet volume + Music volume below the minimum speed + Sound restore delay + How many seconds to wait before restoring normal volume + Maximum speed for music + Above this speed, music is muted + km/h + % Battery capacity Battery Capacity in Wh Charging power From 5172f5efd927d875dc57147985781f2ee1a2a9c7 Mon Sep 17 00:00:00 2001 From: gordas-debug Date: Wed, 15 Jul 2026 17:00:32 +0300 Subject: [PATCH 2/2] Add configurable music auto-ducking --- app/src/main/java/com/cooper/wheellog/WheelData.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/cooper/wheellog/WheelData.java b/app/src/main/java/com/cooper/wheellog/WheelData.java index 6d092450c..8217bda0f 100644 --- a/app/src/main/java/com/cooper/wheellog/WheelData.java +++ b/app/src/main/java/com/cooper/wheellog/WheelData.java @@ -1169,7 +1169,7 @@ private void CheckMuteMusic() { long restoreDelayMs = appConfig.getStopMusicRestoreDelay() * 1000L; // Задержка возврата обычной громкости. - // Нужна, чтобы звук не возвращался от краткого скачка скорости на ямке, + // Нужна, чтобы звук не возвращался от скачка скорости на ямке, // переходе, трамвайных путях и т.п. if ((System.currentTimeMillis() - mLowSpeedMusicTime) >= restoreDelayMs) restoreMusicVolume(); @@ -1180,7 +1180,7 @@ private void setQuietMusicVolume() { if (MainActivity.audioManager == null) return; - // Если до этого WheelLog полностью заглушил звук на высокой скорости, + // Если до этого звук был полностью заглушен на высокой скорости, // сначала отпускаем mute. if (mMusicMutedByWheelLog) { MainActivity.audioManager.setStreamMute(AudioManager.STREAM_MUSIC, false); @@ -1189,7 +1189,7 @@ private void setQuietMusicVolume() { int currentVolume = MainActivity.audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); - // Запоминаем громкость пользователя только один раз, + // Запоминаем уровень громкости только один раз, // перед первым переходом в тихий режим. if (!mMusicVolumeChangedByWheelLog) { mMusicVolumeBeforeQuiet = currentVolume;