From 5e609c24467649460a035601c49d769354852d1c Mon Sep 17 00:00:00 2001 From: ckfear Date: Tue, 16 Aug 2022 05:47:24 +0800 Subject: [PATCH] fix incorrect value of audio slider when audio output is switched (#444) --- MTMR/Widgets/VolumeViewController.swift | 52 +++++++++++++++++++++---- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/MTMR/Widgets/VolumeViewController.swift b/MTMR/Widgets/VolumeViewController.swift index 6ac5945..f30a708 100644 --- a/MTMR/Widgets/VolumeViewController.swift +++ b/MTMR/Widgets/VolumeViewController.swift @@ -5,18 +5,11 @@ import CoreAudio class VolumeViewController: NSCustomTouchBarItem { private(set) var sliderItem: CustomSlider! + private var currentDeviceId: AudioObjectID = AudioObjectID(0) init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) { super.init(identifier: identifier) - var forPropertyAddress = AudioObjectPropertyAddress( - mSelector: kAudioHardwareServiceDeviceProperty_VirtualMainVolume, - mScope: kAudioDevicePropertyScopeOutput, - mElement: kAudioObjectPropertyElementMaster - ) - - AudioObjectAddPropertyListenerBlock(defaultDeviceID, &forPropertyAddress, nil, audioObjectPropertyListenerBlock) - if image == nil { sliderItem = CustomSlider() } else { @@ -29,6 +22,49 @@ class VolumeViewController: NSCustomTouchBarItem { sliderItem.floatValue = getInputGain() * 100 view = sliderItem + + currentDeviceId = defaultDeviceID + self.addAudioRouteChangedListener() + self.addCurrentAudioVolumeChangedListener() + } + + private func addAudioRouteChangedListener() { + let audioId = AudioObjectID(bitPattern: kAudioObjectSystemObject) + var forPropertyAddress = AudioObjectPropertyAddress( + mSelector: kAudioHardwarePropertyDefaultOutputDevice, + mScope: kAudioObjectPropertyScopeGlobal, + mElement: kAudioObjectPropertyElementMaster) + AudioObjectAddPropertyListenerBlock(audioId, &forPropertyAddress, nil, audioRouteChanged) + } + + + func audioRouteChanged(numberAddresses _: UInt32, addresses _: UnsafePointer) { + self.removeLastAudioVolumeChangeListener() + currentDeviceId = defaultDeviceID + self.addCurrentAudioVolumeChangedListener() + DispatchQueue.main.async { + self.sliderItem.floatValue = self.getInputGain() * 100 + } + } + + private func addCurrentAudioVolumeChangedListener() { + var forPropertyAddress = AudioObjectPropertyAddress( + mSelector: kAudioHardwareServiceDeviceProperty_VirtualMainVolume, + mScope: kAudioDevicePropertyScopeOutput, + mElement: kAudioObjectPropertyElementMaster + ) + + AudioObjectAddPropertyListenerBlock(defaultDeviceID, &forPropertyAddress, nil, audioObjectPropertyListenerBlock) + } + + private func removeLastAudioVolumeChangeListener() { + var forPropertyAddress = AudioObjectPropertyAddress( + mSelector: kAudioHardwareServiceDeviceProperty_VirtualMainVolume, + mScope: kAudioDevicePropertyScopeOutput, + mElement: kAudioObjectPropertyElementMaster + ) + + AudioObjectRemovePropertyListenerBlock(currentDeviceId, &forPropertyAddress, nil, audioObjectPropertyListenerBlock) } func audioObjectPropertyListenerBlock(numberAddresses _: UInt32, addresses _: UnsafePointer) {