tono tener sonido notificación notificaciones notificacion llamada las distinto cómo como celular cambiar cada aplicación macos cocoa notifications core-audio

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:

  1. 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ámetro forPropertyAddress . Al llamar a addListenerBlock , 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)) } ...

  2. 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.