macos - tener - cómo cambiar el sonido de las notificaciones
Cómo recibir una notificación si el sonido predeterminado de las preferencias del sistema cambió (2)
Esto es bastante simple (creo). Simplemente quiero recibir una notificación en mi aplicación cada vez que un usuario cambia la entrada de sonido predeterminada o el dispositivo de salida de sonido en Preferencias del Sistema - Sonido. Sin embargo, me zurrarán si puedo sacarlo de los documentos de Apple.
Como nota al margen, esto es para OSX, no para iOS.
¡Gracias chicos!
Configure AudioObjectPropertyAddress
para el dispositivo de salida predeterminado:
AudioObjectPropertyAddress outputDeviceAddress = {
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
Luego, use AudioObjectSetPropertyData
para registrar un detector de cambios en el dispositivo predeterminado:
AudioObjectAddPropertyListener(kAudioObjectSystemObject,
&outputDeviceAddress,
&callbackFunction, nil);
La función de devolución de llamada se ve así:
OSStatus callbackFunction(AudioObjectID inObjectID,
UInt32 inNumberAddresses,
const AudioObjectPropertyAddress inAddresses[],
void *inClientData)
Como nota al margen, también debe usar AudioObjectPropertyAddress
para decirle al HAL que administre su propio hilo para las notificaciones. Para ello, establezca el selector de ciclo de ejecución en NULL. De hecho, realizo este paso antes de configurar el oyente del dispositivo de salida.
AudioObjectPropertyAddress runLoopAddress = {
kAudioHardwarePropertyRunLoop,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
CFRunLoopRef runLoop = NULL;
UInt32 size = sizeof(CFRunLoopRef);
AudioObjectSetPropertyData(kAudioObjectSystemObject,
&runLoopAddress, 0, NULL, size, &runLoop);
He aquí cómo hacerlo en Swift:
Regístrese para recibir notificaciones agregando un bloque de escucha, por ejemplo, cuando un Controlador de Vista carga su vista. La función
addListenerBlock
simplifica la adición de bloques de escucha de propiedad. Swift permite que los parámetros sean variables, lo cual es muy conveniente para el parámetroforPropertyAddress
. Al llamar aaddListenerBlock
, los parámetros de la dirección de propiedad simplemente están enchufados.import Cocoa import CoreAudio class ViewController: NSViewController { // Utility function to simplify adding listener blocks: func addListenerBlock( listenerBlock: AudioObjectPropertyListenerBlock, onAudioObjectID: AudioObjectID, var forPropertyAddress: AudioObjectPropertyAddress) { if (kAudioHardwareNoError != AudioObjectAddPropertyListenerBlock(onAudioObjectID, &forPropertyAddress, nil, listenerBlock)) { print("Error calling: AudioObjectAddPropertyListenerBlock") } } override func viewDidLoad() { super.viewDidLoad() addListenerBlock(audioObjectPropertyListenerBlock, onAudioObjectID: AudioObjectID(bitPattern: kAudioObjectSystemObject), forPropertyAddress: AudioObjectPropertyAddress( mSelector: kAudioHardwarePropertyDefaultOutputDevice, mScope: kAudioObjectPropertyScopeGlobal, mElement: kAudioObjectPropertyElementMaster)) } ...
Proporcione una función de bloque de escucha para recibir las notificaciones. Te dan una matriz que podría tener más de una dirección de propiedad, así que ve y busca la que quieras:
func audioObjectPropertyListenerBlock (numberAddresses: UInt32, addresses: UnsafePointer<AudioObjectPropertyAddress>) { var index: UInt32 = 0 while index < numberAddresses { let address: AudioObjectPropertyAddress = addresses[0] switch address.mSelector { case kAudioHardwarePropertyDefaultOutputDevice: let deviceID = getDefaultAudioOutputDevice() print("kAudioHardwarePropertyDefaultOutputDevice: /(deviceID)") default: print("We didn''t expect this!") } index += 1 } // Utility function to get default audio output device: func getDefaultAudioOutputDevice () -> AudioObjectID { var devicePropertyAddress = AudioObjectPropertyAddress(mSelector: kAudioHardwarePropertyDefaultOutputDevice, mScope: kAudioObjectPropertyScopeGlobal, mElement: kAudioObjectPropertyElementMaster) var deviceID: AudioObjectID = 0 var dataSize = UInt32(truncatingBitPattern: sizeof(AudioDeviceID)) let systemObjectID = AudioObjectID(bitPattern: kAudioObjectSystemObject) if (kAudioHardwareNoError != AudioObjectGetPropertyData(systemObjectID, &devicePropertyAddress, 0, nil, &dataSize, &deviceID)) { return 0 } return deviceID } }
Por supuesto, puede simplemente agregar más cases
a la declaración de switch
si desea monitorear otras propiedades del dispositivo de audio. Llame a addListenerBlock
para agregar los dispositivos y las direcciones de propiedad que le interesen.