Skip to content

Instantly share code, notes, and snippets.

@dreness
Created October 6, 2024 23:21
Show Gist options
  • Save dreness/aeb979b566e5eefd50ad51301f8732ac to your computer and use it in GitHub Desktop.
Save dreness/aeb979b566e5eefd50ad51301f8732ac to your computer and use it in GitHub Desktop.
Swift CLI to get or set the sound volume of the main audio device using CoreAudio
// compile with: swiftcc swift_volume.swift -o swiftvol
import CoreAudio
import AudioToolbox
import Foundation
class SystemVolumeManager {
private let outputDeviceID: AudioDeviceID = AudioObjectID(kAudioObjectSystemObject)
private func getDefaultOutputDevice() -> AudioDeviceID? {
var deviceID = AudioDeviceID(0)
var propertyAddress = AudioObjectPropertyAddress(
mSelector: kAudioHardwarePropertyDefaultOutputDevice,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMain
)
var deviceIDSize = UInt32(MemoryLayout.size(ofValue: deviceID))
let status = AudioObjectGetPropertyData(
outputDeviceID,
&propertyAddress,
0,
nil,
&deviceIDSize,
&deviceID
)
guard status == noErr else {
print("Unable to get default output device: \(status)")
return nil
}
return deviceID
}
func getVolumeLevel() -> Float? {
guard let deviceID = getDefaultOutputDevice() else {
return nil
}
var volume: Float = 0
var propertyAddress = AudioObjectPropertyAddress(
mSelector: kAudioHardwareServiceDeviceProperty_VirtualMainVolume,
mScope: kAudioDevicePropertyScopeOutput,
mElement: kAudioObjectPropertyElementMain
)
var size = UInt32(MemoryLayout.size(ofValue: volume))
let status = AudioObjectGetPropertyData(deviceID, &propertyAddress, 0, nil, &size, &volume)
guard status == noErr else {
print("Unable to get volume level: \(status)")
return nil
}
return volume
}
func setVolumeLevel(to newVolume: Float) {
guard let deviceID = getDefaultOutputDevice() else {
return
}
var volume = newVolume
var propertyAddress = AudioObjectPropertyAddress(
mSelector: kAudioHardwareServiceDeviceProperty_VirtualMainVolume,
mScope: kAudioDevicePropertyScopeOutput,
mElement: kAudioObjectPropertyElementMain
)
let status = AudioObjectSetPropertyData(deviceID, &propertyAddress, 0, nil, UInt32(MemoryLayout.size(ofValue: volume)), &volume)
if status != noErr {
print("Unable to set volume level: \(status)")
}
}
}
// Usage example with CLI arguments
let arguments = CommandLine.arguments
let volumeManager = SystemVolumeManager()
if arguments.count > 1, let newVolume = Float(arguments[1]), newVolume >= 0.0, newVolume <= 1.0 {
volumeManager.setVolumeLevel(to: newVolume)
if let updatedVolume = volumeManager.getVolumeLevel() {
print("Updated volume level: \(updatedVolume)")
}
} else {
if let currentVolume = volumeManager.getVolumeLevel() {
print("Current volume level: \(currentVolume)")
}
print("Usage: \(arguments[0]) [volume_level (0.0 - 1.0)]")
}
@dreness
Copy link
Author

dreness commented Oct 6, 2024

(after copying swiftvol into a directory in $PATH)

andre@bust ~ % swiftvol .42
Updated volume level: 0.41999996

andre@bust ~ % swiftvol 
Current volume level: 0.41999996
Usage: swiftvol [volume_level (0.0 - 1.0)]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment