From 376708b5864f85590cb1e0d618238572f8f96b9a Mon Sep 17 00:00:00 2001 From: Oleg Dubinskiy Date: Fri, 28 Mar 2025 15:47:16 +0100 Subject: [PATCH] [MMIXER] Fix improperly working volume control Fix broken volume level changing and left/right speakers balance level changing. Get and set volume level value for all available output channels instead of only the 1st channel (available in MIXERCONTROLDETAILS.cChannels member), so other channels don't have a non-set volume values now. This allows to control the volume for all channels. So now the volume control works correctly and hence, the volume level can be properly changed from Sound Properties (mmsys.cpl) and Volume Mixer (sndvol32.exe) as well. Note that the volume level settings changed by user are not saved after reboot yet. We need to save (write) and then load (read) them at next boot from HKLM/System/CurrentControlSet/Control/DeviceClasses/KSCATEGORY_AUDIO/.../DeviceParameters/Mixer/.../* keys inside wdmaud.sys, similarly to as it's done in Windows XP/2003. It can be tested (and is tested sveral times by me and is confirmed) by using MS wdmaud.sys in ReactOS. It writes the values in that key, so the actual volume values are stored there. Another key, HKCU/SOFTWARE/Microsoft/Windows/Applets/Volume Control/, is created and managed by sndvol32.exe instead, so it does not contain the actual values of volume levels. CORE-17976 --- sdk/lib/drivers/sound/mmixer/sup.c | 59 +++++++++++++----------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/sdk/lib/drivers/sound/mmixer/sup.c b/sdk/lib/drivers/sound/mmixer/sup.c index 9b6852a4d23..27e26ba4bb2 100644 --- a/sdk/lib/drivers/sound/mmixer/sup.c +++ b/sdk/lib/drivers/sound/mmixer/sup.c @@ -673,59 +673,52 @@ MMixerSetGetVolumeControlDetails( { LPMIXERCONTROLDETAILS_UNSIGNED Input; LONG Value; - ULONG Index, Channel = 0; - ULONG dwValue; + ULONG Index, Channel; MIXER_STATUS Status; LPMIXERVOLUME_DATA VolumeData; - if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_SIGNED)) + if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_UNSIGNED)) return MM_STATUS_INVALID_PARAMETER; VolumeData = (LPMIXERVOLUME_DATA)MixerControl->ExtraData; if (!VolumeData) return MM_STATUS_UNSUCCESSFUL; - /* get input */ + /* Get input */ Input = (LPMIXERCONTROLDETAILS_UNSIGNED)MixerControlDetails->paDetails; if (!Input) - return MM_STATUS_UNSUCCESSFUL; /* to prevent dereferencing NULL */ + return MM_STATUS_UNSUCCESSFUL; /* To prevent dereferencing NULL */ - if (bSet) + /* Loop for each channel */ + for (Channel = 0; Channel < MixerControlDetails->cChannels; Channel++) { - /* FIXME SEH */ - Value = Input->dwValue; - Index = Value / VolumeData->InputSteppingDelta; - - if (Index >= VolumeData->ValuesCount) + if (bSet) { - DPRINT1("Index %u out of bounds %u \n", Index, VolumeData->ValuesCount); - return MM_STATUS_INVALID_PARAMETER; + /* FIXME SEH */ + Index = Input[Channel].dwValue / VolumeData->InputSteppingDelta; + + if (Index >= VolumeData->ValuesCount) + { + DPRINT1("Index %u out of bounds %u \n", Index, VolumeData->ValuesCount); + return MM_STATUS_INVALID_PARAMETER; + } + + Value = VolumeData->Values[Index]; } - Value = VolumeData->Values[Index]; + /* Get/set control details */ + Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value); + + if (!bSet) + { + /* FIXME SEH */ + Input[Channel].dwValue = MMixerGetVolumeControlIndex(VolumeData, Value); + } } - /* set control details */ if (bSet) { - /* TODO */ - Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value); - Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value); - } - else - { - Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value); - } - - if (!bSet) - { - dwValue = MMixerGetVolumeControlIndex(VolumeData, (LONG)Value); - /* FIXME SEH */ - Input->dwValue = dwValue; - } - else - { - /* notify clients of a line change MM_MIXM_CONTROL_CHANGE with MixerControl->dwControlID */ + /* Notify clients of a line change */ MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->Control.dwControlID); } return Status;