From ac1f67289150c83e7acba37d01c30675ab22603e Mon Sep 17 00:00:00 2001 From: Daniel Prows Date: Wed, 9 Aug 2023 20:33:48 -0600 Subject: [PATCH] Implement core audio methods for getting/setting volume settings --- src/volume/coreAudio.go | 134 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/volume/coreAudio.go diff --git a/src/volume/coreAudio.go b/src/volume/coreAudio.go new file mode 100644 index 0000000..a327259 --- /dev/null +++ b/src/volume/coreAudio.go @@ -0,0 +1,134 @@ +package volume + +/* + #cgo CFLAGS: -x objective-c + #cgo LDFLAGS: -framework CoreAudio + #include +*/ +import "C" +import ( + "unsafe" +) + +type OSStatus C.OSStatus + +const ( + AudioHardwareNoError = C.kAudioHardwareNoError +) + +type AudioObjectID uint32 + +func GetDefaultOutputDevice() (AudioObjectID, OSStatus) { + properties := C.AudioObjectPropertyAddress{ + C.kAudioHardwarePropertyDefaultOutputDevice, + C.kAudioObjectPropertyScopeGlobal, + C.kAudioObjectPropertyElementMain, + } + + var data C.AudioObjectID + dataSize := C.UInt32(unsafe.Sizeof(data)) + + result := C.AudioObjectGetPropertyData( + C.kAudioObjectSystemObject, + &properties, + C.UInt32(0), + unsafe.Pointer(nil), + &dataSize, + unsafe.Pointer(&data), + ) + + return AudioObjectID(data), OSStatus(result) +} + +func GetVolume(objectID AudioObjectID) (float32, OSStatus) { + + properties := C.AudioObjectPropertyAddress{ + C.kAudioDevicePropertyVolumeScalar, + C.kAudioDevicePropertyScopeOutput, + 0, //main channel + } + + var data C.Float32 + dataSize := C.UInt32(unsafe.Sizeof(data)) + + result := C.AudioObjectGetPropertyData( + C.AudioObjectID(objectID), + &properties, + C.UInt32(0), + unsafe.Pointer(nil), + &dataSize, + unsafe.Pointer(&data), + ) + + return float32(data), OSStatus(result) +} + +func SetVolume(objectID AudioObjectID, volume float32) OSStatus { + + properties := C.AudioObjectPropertyAddress{ + C.kAudioDevicePropertyVolumeScalar, + C.kAudioDevicePropertyScopeOutput, + 0, //main channel + } + + data := C.Float32(volume) + + result := C.AudioObjectSetPropertyData( + C.AudioObjectID(objectID), + &properties, + C.UInt32(0), + unsafe.Pointer(nil), + C.UInt32(unsafe.Sizeof(data)), + unsafe.Pointer(&data), + ) + + return OSStatus(result) +} + +func GetMute(objectID AudioObjectID) (bool, OSStatus) { + + properties := C.AudioObjectPropertyAddress{ + C.kAudioDevicePropertyMute, + C.kAudioDevicePropertyScopeOutput, + 0, //main channel + } + + var data C.UInt32 + dataSize := C.UInt32(unsafe.Sizeof(data)) + + result := C.AudioObjectGetPropertyData( + C.AudioObjectID(objectID), + &properties, + C.UInt32(0), + unsafe.Pointer(nil), + &dataSize, + unsafe.Pointer(&data), + ) + + dataAsBool := uint32(data) != 0 + return dataAsBool, OSStatus(result) +} + +func SetMute(objectID AudioObjectID, mute bool) OSStatus { + + properties := C.AudioObjectPropertyAddress{ + C.kAudioDevicePropertyMute, + C.kAudioDevicePropertyScopeOutput, + 0, //main channel + } + + data := C.UInt32(0) + if mute { + data = C.UInt32(1) + } + + result := C.AudioObjectSetPropertyData( + C.AudioObjectID(objectID), + &properties, + C.UInt32(0), + unsafe.Pointer(nil), + C.UInt32(unsafe.Sizeof(data)), + unsafe.Pointer(&data), + ) + return OSStatus(result) +}