mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-28 23:54:32 +00:00
BugFix: Headphone polling - Dynamic Polling
This commit is contained in:
parent
494f2d57cc
commit
dc774a073b
1 changed files with 38 additions and 24 deletions
|
|
@ -23,16 +23,16 @@ class SystemChangesObserver {
|
||||||
private var currentPollingInterval: TimeInterval = 2.0
|
private var currentPollingInterval: TimeInterval = 2.0
|
||||||
|
|
||||||
// Polling intervals
|
// Polling intervals
|
||||||
private let rapidPollingInterval: TimeInterval = 0.05 // Burst mode for 5 seconds after key press
|
private let rapidPollingInterval: TimeInterval = 0.05 // Burst mode for active changes
|
||||||
private let fastPollingInterval: TimeInterval = 0.3 // Fast mode when headphones connected
|
|
||||||
private let normalPollingInterval: TimeInterval = 2.0 // Normal mode when idle
|
private let normalPollingInterval: TimeInterval = 2.0 // Normal mode when idle
|
||||||
|
|
||||||
// Activity tracking
|
// Activity tracking
|
||||||
private var lastBrightnessChangeTime: Date = Date.distantPast
|
private var lastBrightnessChangeTime: Date = Date.distantPast
|
||||||
private var lastVolumeChangeTime: Date = Date.distantPast
|
private var lastVolumeChangeTime: Date = Date.distantPast
|
||||||
private var lastVolumeCheckTime: Date = Date.distantPast
|
private var lastVolumeCheckTime: Date = Date.distantPast
|
||||||
|
private var lastExternalChangeTime: Date = Date.distantPast // Track external volume changes
|
||||||
|
|
||||||
// Headphone detection
|
// Headphone detection (for info only, doesn't affect polling)
|
||||||
private var hasHeadphonesConnected: Bool = false
|
private var hasHeadphonesConnected: Bool = false
|
||||||
|
|
||||||
init(coordinator: DynamicIslandViewCoordinator) {
|
init(coordinator: DynamicIslandViewCoordinator) {
|
||||||
|
|
@ -63,18 +63,20 @@ class SystemChangesObserver {
|
||||||
private func determinePollingInterval() -> TimeInterval {
|
private func determinePollingInterval() -> TimeInterval {
|
||||||
let now = Date()
|
let now = Date()
|
||||||
|
|
||||||
// Burst mode: Rapid polling within 5 seconds of any key press
|
// Burst mode: Rapid polling within 5 seconds of any activity
|
||||||
if now.timeIntervalSince(lastVolumeChangeTime) < 5.0 ||
|
// Activity = key press OR external change detected
|
||||||
now.timeIntervalSince(lastBrightnessChangeTime) < 5.0 {
|
let timeSinceKeyPress = min(
|
||||||
|
now.timeIntervalSince(lastVolumeChangeTime),
|
||||||
|
now.timeIntervalSince(lastBrightnessChangeTime)
|
||||||
|
)
|
||||||
|
let timeSinceExternalChange = now.timeIntervalSince(lastExternalChangeTime)
|
||||||
|
|
||||||
|
// Use burst mode if there's been recent activity (within 5 seconds)
|
||||||
|
if timeSinceKeyPress < 5.0 || timeSinceExternalChange < 5.0 {
|
||||||
return rapidPollingInterval
|
return rapidPollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast mode: When headphones are connected
|
// Normal mode: Idle state (regardless of headphones)
|
||||||
if hasHeadphonesConnected {
|
|
||||||
return fastPollingInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal mode: Idle state
|
|
||||||
return normalPollingInterval
|
return normalPollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,9 +108,8 @@ class SystemChangesObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mode = interval == rapidPollingInterval ? "BURST (50ms)" :
|
let mode = interval == rapidPollingInterval ? "BURST (50ms)" : "NORMAL (2s)"
|
||||||
interval == fastPollingInterval ? "FAST (300ms)" : "NORMAL (2s)"
|
print("✅ Polling started: \(mode) mode\(hasHeadphonesConnected ? " [🎧 Headphones connected]" : "")")
|
||||||
print("✅ Polling started: \(mode) mode")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Headphone Detection
|
// MARK: - Headphone Detection
|
||||||
|
|
@ -185,8 +186,8 @@ class SystemChangesObserver {
|
||||||
transportType != kAudioDeviceTransportTypeBuiltIn
|
transportType != kAudioDeviceTransportTypeBuiltIn
|
||||||
|
|
||||||
if wasConnected != hasHeadphonesConnected {
|
if wasConnected != hasHeadphonesConnected {
|
||||||
print(hasHeadphonesConnected ? "🎧 Headphones connected - switching to FAST polling" :
|
print(hasHeadphonesConnected ? "🎧 Headphones connected (will use burst mode on change detection)" :
|
||||||
"🔊 Headphones disconnected - switching to NORMAL polling")
|
"🔊 Headphones disconnected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,19 +281,33 @@ class SystemChangesObserver {
|
||||||
let muteChanged = newMuted != oldMuted
|
let muteChanged = newMuted != oldMuted
|
||||||
|
|
||||||
if volumeChanged || muteChanged {
|
if volumeChanged || muteChanged {
|
||||||
// Don't show HUD if change was just triggered by key press (within 0.1s in burst mode, 0.3s otherwise)
|
// Check if this is an external change (not from key press)
|
||||||
let debounceWindow = currentPollingInterval == rapidPollingInterval ? 0.1 : 0.3
|
let debounceWindow = currentPollingInterval == rapidPollingInterval ? 0.1 : 0.5
|
||||||
let timeSinceKeyPress = now.timeIntervalSince(lastVolumeChangeTime)
|
let timeSinceKeyPress = now.timeIntervalSince(lastVolumeChangeTime)
|
||||||
|
|
||||||
|
// External change detected!
|
||||||
if timeSinceKeyPress > debounceWindow {
|
if timeSinceKeyPress > debounceWindow {
|
||||||
let mode = currentPollingInterval == rapidPollingInterval ? "[BURST]" : "[EXTERNAL]"
|
// Mark it and trigger burst mode
|
||||||
|
lastExternalChangeTime = now
|
||||||
|
|
||||||
|
let mode = currentPollingInterval == rapidPollingInterval ? "[BURST]" : "[EXTERNAL→BURST]"
|
||||||
print("🔊 Volume change detected \(mode): \(oldVolume) → \(newVolume), muted: \(oldMuted) → \(newMuted)")
|
print("🔊 Volume change detected \(mode): \(oldVolume) → \(newVolume), muted: \(oldMuted) → \(newMuted)")
|
||||||
|
|
||||||
|
// Show HUD immediately
|
||||||
if newMuted {
|
if newMuted {
|
||||||
sendVolumeNotification(value: 0.0)
|
sendVolumeNotification(value: 0.0)
|
||||||
} else {
|
} else {
|
||||||
sendVolumeNotification(value: newVolume)
|
sendVolumeNotification(value: newVolume)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Switch to burst mode immediately if we're in normal mode
|
||||||
|
if currentPollingInterval == normalPollingInterval {
|
||||||
|
print("⚡ Switching from NORMAL to BURST mode due to external change")
|
||||||
|
startPollingTimer(interval: rapidPollingInterval)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Within debounce window of key press - still update values but don't show HUD
|
||||||
|
print("🔇 Volume change within debounce window (\(timeSinceKeyPress)s) - skipping HUD")
|
||||||
}
|
}
|
||||||
|
|
||||||
oldVolume = newVolume
|
oldVolume = newVolume
|
||||||
|
|
@ -319,10 +334,9 @@ class SystemChangesObserver {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func isAlmost(firstNumber: Float, secondNumber: Float) -> Bool {
|
private func isAlmost(firstNumber: Float, secondNumber: Float) -> Bool {
|
||||||
// Convert sensitivity setting to a more responsive threshold
|
// Use a fixed sensitive threshold for volume changes
|
||||||
// Sensitivity 1-10 scale maps to 0.01-0.10 threshold range
|
// 0.015 = 1.5% change required (sensitive enough for headphone increments)
|
||||||
let marginValue = Float(Defaults[.systemHUDSensitivity]) / 100.0
|
let threshold: Float = 0.015
|
||||||
let threshold = max(0.01, marginValue) // Minimum threshold for responsiveness
|
|
||||||
return abs(firstNumber - secondNumber) <= threshold
|
return abs(firstNumber - secondNumber) <= threshold
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue