Unverified Commit 680fdb03 authored by Yue Wang's avatar Yue Wang Committed by GitHub

enable macOS to use Hardware Mixer

- Update the mixer to set on device property instead of audio unit property. When user choose "hardware" as mixer type, they will be able to change the hardware device volume instead of the software (AudioUnit) volume. - We don't use square root scale in volume calculation as previous code did. This will make the volume level in line with system volume meter --- That is, MPD will have the same percentage volume reading compared to System Setting (Either in "System Preference" or in "Audio Midi Setup" app)
parent 727078f6
...@@ -174,35 +174,47 @@ OSXOutput::Create(EventLoop &, const ConfigBlock &block) ...@@ -174,35 +174,47 @@ OSXOutput::Create(EventLoop &, const ConfigBlock &block)
int int
OSXOutput::GetVolume() OSXOutput::GetVolume()
{ {
AudioUnitParameterValue dvolume; Float32 vol;
char errormsg[1024]; AudioObjectPropertyAddress aopa = {
.mSelector = kAudioDevicePropertyVolumeScalar,
.mScope = kAudioObjectPropertyScopeOutput,
.mElement = kAudioObjectPropertyElementMaster,
};
UInt32 size = sizeof(vol);
OSStatus status = AudioObjectGetPropertyData(dev_id,
&aopa,
0,
NULL,
&size,
&vol);
OSStatus status = AudioUnitGetParameter(au, kHALOutputParam_Volume,
kAudioUnitScope_Global, 0, &dvolume);
if (status != noErr) { if (status != noErr) {
char errormsg[1024];
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
throw FormatRuntimeError("unable to get volume: %s", errormsg); throw FormatRuntimeError("unable to get volume: %s", errormsg);
} }
/* see the explanation in SetVolume, below */ return static_cast<int>(vol * 100.0);
return static_cast<int>(dvolume * dvolume * 100.0);
} }
void void
OSXOutput::SetVolume(unsigned new_volume) { OSXOutput::SetVolume(unsigned new_volume) {
char errormsg[1024]; Float32 vol = new_volume / 100.0;
AudioObjectPropertyAddress aopa = {
/* The scaling below makes shifts in volume greater at the lower end .mSelector = kAudioDevicePropertyVolumeScalar,
* of the scale. This mimics the "feel" of physical volume levers. This is .mScope = kAudioObjectPropertyScopeOutput,
* generally what users of audio software expect. .mElement = kAudioObjectPropertyElementMaster
*/ };
UInt32 size = sizeof(vol);
AudioUnitParameterValue scaled_volume = OSStatus status = AudioObjectSetPropertyData(dev_id,
sqrt(static_cast<AudioUnitParameterValue>(new_volume) / 100.0); &aopa,
0,
NULL,
size,
&vol);
OSStatus status = AudioUnitSetParameter(au, kHALOutputParam_Volume,
kAudioUnitScope_Global, 0, scaled_volume, 0);
if (status != noErr) { if (status != noErr) {
char errormsg[1024];
osx_os_status_to_cstring(status, errormsg, sizeof(errormsg)); osx_os_status_to_cstring(status, errormsg, sizeof(errormsg));
throw FormatRuntimeError( "unable to set new volume %u: %s", throw FormatRuntimeError( "unable to set new volume %u: %s",
new_volume, errormsg); new_volume, errormsg);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment