Created
June 8, 2020 21:42
-
-
Save ConfusedVorlon/8cefb0c623142837206f7f6507e7c3f4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AudioDeviceNotifier.swift | |
// | |
// Created by Rob Jonson on 20/01/2017. | |
// Copyright © 2017 HobbyistSoftware. All rights reserved. | |
// | |
import Foundation | |
import CoreAudio | |
/// Provides notification when the default audio device changes, or when the stream settings of the default audio device change | |
class AudioDeviceNotifier { | |
var active = true | |
var handler:(()->(Void))? | |
private var listenerBlock:AudioObjectPropertyListenerBlock? | |
private var streamBlock:AudioObjectPropertyListenerBlock? | |
private var audioDevicesAddress = AudioObjectPropertyAddress.init(mSelector: kAudioHardwarePropertyDefaultOutputDevice, | |
mScope: kAudioObjectPropertyScopeGlobal, | |
mElement: kAudioObjectPropertyElementMaster) | |
private var currentAudioDevice:AudioDevice? { | |
didSet { | |
if oldValue != currentAudioDevice { | |
moveStreamNotifier(from: oldValue, to:currentAudioDevice ) | |
} | |
} | |
} | |
init() { | |
listenerBlock = { | |
[weak self] (numberOfElements, pointerToArrayOfAddresses) in | |
print("Default device changed") | |
self?.deviceChanged() | |
} | |
streamBlock = { | |
[weak self] (numberOfElements, pointerToArrayOfAddresses) in | |
print("Stream details changed") | |
self?.deviceChanged() | |
} | |
let err = AudioObjectAddPropertyListenerBlock(AudioObjectID(kAudioObjectSystemObject), &audioDevicesAddress, DispatchQueue.main,listenerBlock!) | |
currentAudioDevice = AudioDevice.defaultOutputDevice() | |
moveStreamNotifier(from: nil, to: currentAudioDevice) | |
if err != noErr { | |
print("Failed to register audio block") | |
} | |
} | |
deinit { | |
AudioObjectRemovePropertyListenerBlock(AudioObjectID(kAudioObjectSystemObject), | |
&audioDevicesAddress, | |
DispatchQueue.main,listenerBlock!) | |
moveStreamNotifier(from: currentAudioDevice, to: nil) | |
} | |
func deviceChanged() { | |
currentAudioDevice = AudioDevice.defaultOutputDevice() | |
if active { | |
handler?() | |
} | |
} | |
func moveStreamNotifier(from:AudioDevice?, to:AudioDevice?) { | |
var audioDeviceStreamsAddress = AudioObjectPropertyAddress.init(mSelector: kAudioDevicePropertyStreamFormat, | |
mScope: kAudioObjectPropertyScopeOutput, | |
mElement: kAudioObjectPropertyElementMaster) | |
if let streamBlock = streamBlock { | |
if let from = from { | |
let err = AudioObjectRemovePropertyListenerBlock(from.id, | |
&audioDeviceStreamsAddress, | |
DispatchQueue.main,streamBlock) | |
if err != noErr { | |
print("Error removing listening block") | |
} | |
} | |
if let to = to { | |
print("moving notifier to \(String(describing: to.name())))") | |
let err = AudioObjectAddPropertyListenerBlock(to.id, | |
&audioDeviceStreamsAddress, | |
DispatchQueue.main,streamBlock) | |
if err != noErr { | |
print("Error adding listening block") | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment