Page 2 of 3
Re: Get/Set Sound volume level programmatically
Posted: Sat Feb 09, 2013 6:11 pm
by luis
netmaestro wrote:... and my wife is very impressed.
Thanks for sharing the result. Any idea if this works for a limited account too ? After all it's changing a system wide setting.
Re: Get/Set Sound volume level programmatically
Posted: Sat Feb 09, 2013 7:09 pm
by netmaestro
You raise a good point, one I confess I didn't think of

I logged out of my admin account and logged in as guest. I was unable to change any files, though I could read them and I wasn't allowed to change the system time. However, I was allowed to mute the speakers. I did that and then ran the QuickAlarm program. When the alarm time came it successfully turned on the speakers and turned them up, so I'm going to assume that user privilege level isn't going to affect it. Thanks for the heads up!
Re: Get/Set Sound volume level programmatically
Posted: Sat Feb 09, 2013 9:10 pm
by luis
That's good to know thank you

Re: Get/Set Sound volume level programmatically
Posted: Sun Feb 10, 2013 12:29 pm
by Joris
netmaestro wrote:@Joris: Thanks, I'll encase the new sound stuff in a CompilerIf block for the windows version to prevent crashes and include a note in the About box saying that for XP and earlier it won't force the sound.
That would be nice.
Quest: Speaker Output VU Meter - Who know how?
Posted: Thu Jul 18, 2013 7:40 pm
by minimy
Very good topic!
Someone knows how to get the values of the speaker output.
volume changes in the sound as a vumeter.
I saw a topic, very good indeed, that of metergadget, but only talk about the mic input and output nothing about.
sourceforge is an example in the Core Audio API, but is in C.
You can use coreaudioapi.dll with PureBasic?
I think that's the way you and I see you know a lot about.
Can anyone help?
Re: Get/Set Sound volume level programmatically
Posted: Tue May 06, 2014 1:31 am
by DarkRookie
Saw this and thought I could use it. Tried code in DEMO 5.21, but it is not working.
Get the following error
Is this a limitation of the demo version?
Re: Get/Set Sound volume level programmatically
Posted: Tue May 06, 2014 2:27 am
by TI-994A
DarkRookie wrote:Is this a limitation of the demo version?
Hi DarkRookie. Yes, it is. The demo version does not support constants, interfaces or structures, and there're no predefined API functions.
Re: Get/Set Sound volume level programmatically
Posted: Sun May 05, 2024 2:42 am
by BarryG
I'm getting an occasional crash ("Access violation") with this procedure on the "hr=defaultDevice\[...]" line:
Code: Select all
Procedure GetEndPointVolume(*endpointvolume)
Protected deviceEnumerator.IMMDeviceEnumerator
Protected hr,defaultDevice.IMMDevice
CoInitialize_(#Null)
hr=CoCreateInstance_(?uuidof_MMDeviceEnumerator,#Null,#CLSCTX_INPROC_SERVER,?uuidof_IMMDeviceEnumerator,@deviceEnumerator)
hr=deviceEnumerator\GetDefaultAudioEndpoint(0,1,@defaultDevice)
deviceEnumerator\release()
hr=defaultDevice\Activate(?uuidof_IAudioEndpointVolume,#CLSCTX_INPROC_SERVER,#Null,*endpointVolume) ; <<< CRASH!
defaultDevice\release()
ProcedureReturn *endpointvolume
EndProcedure
Is the variable "hr" meant to be of ".i" type maybe? The crash doesn't happen all the time so I can't test if ".i" will make a difference. Windows 11 Pro.
Re: Get/Set Sound volume level programmatically
Posted: Sun May 05, 2024 4:38 am
by idle
maybe you should check the return value hr to see if it got the defaultDevice interface
Code: Select all
Procedure GetEndPointVolume(*endpointvolume)
Protected deviceEnumerator.IMMDeviceEnumerator
Protected hr, defaultDevice.IMMDevice
CoInitialize_(#Null)
hr = CoCreateInstance_(?uuidof_MMDeviceEnumerator, #Null, #CLSCTX_INPROC_SERVER, ?uuidof_IMMDeviceEnumerator,@deviceEnumerator);#CLSCTX_ALL
If hr = 0
hr = deviceEnumerator\GetDefaultAudioEndpoint(0, 1, @defaultDevice)
deviceEnumerator\Release()
If hr = 0
hr = defaultDevice\Activate(?uuidof_IAudioEndpointVolume, #CLSCTX_INPROC_SERVER, #Null, *endpointVolume);
defaultDevice\release()
EndIf
EndIf
ProcedureReturn *endpointvolume
EndProcedure
Re: Get/Set Sound volume level programmatically
Posted: Sun May 05, 2024 6:25 am
by BarryG
Thanks, Idle! My Win 11 laptop does have some sound issues so I will use your error-checking version and see how it goes.
Re: Get/Set Sound volume level programmatically
Posted: Tue Jun 11, 2024 2:58 pm
by pthien
netmaestro wrote: Sat Feb 09, 2013 8:10 am
All replies are much appreciated. The code from ts-soft works well but misses a couple of procedures, namely MediaGetMute() and MediaSetMute(), which if were included would make it perfect for my needs. I really don't need to support XP and earlier anyway and it would be a fair amount of work to put an include together that would serve both XP and Vista+ equally well. So I added the needed procs to ts-soft's code and now I have a complete working solution, which I have implemented in my alarm clock and now it's "mute-proof" and my wife is very impressed.
This is my SoundControls.pbi, most of it by ts-soft:
Code: Select all
#CLSCTX_INPROC_SERVER = $01
#CLSCTX_INPROC_HANDLER = $02
#CLSCTX_LOCAL_SERVER = $04
#CLSCTX_REMOTE_SERVER = $10
#CLSCTX_ALL = #CLSCTX_INPROC_SERVER|#CLSCTX_INPROC_HANDLER|#CLSCTX_LOCAL_SERVER|#CLSCTX_REMOTE_SERVER
#CLSCTX_INPROC = #CLSCTX_INPROC_SERVER|#CLSCTX_INPROC_HANDLER
#CLSCTX_SERVER = #CLSCTX_INPROC_SERVER|#CLSCTX_LOCAL_SERVER|#CLSCTX_REMOTE_SERVER
Interface IMMDeviceEnumerator Extends IUnknown
EnumAudioEndpoints(dataFlow, dwStateMask, *ppDevices)
GetDefaultAudioEndpoint(dataFlow, role, ppEndpoint)
GetDevice(pwstrId, ppDevice)
RegisterEndpointNotificationCallback(pClient)
UnregisterEndpointNotificationCallback(pClient)
EndInterface
Interface IAudioEndpointVolume Extends IUnknown
RegisterControlChangeNotify( *pNotify)
UnregisterControlChangeNotify( *pNotify)
GetChannelCount( *pnChannelCount)
SetMasterVolumeLevel( fLevelDB.f)
SetMasterVolumeLevelScalar( fLevel.f,pguidEventContext)
GetMasterVolumeLevel(*pfLevelDB)
GetMasterVolumeLevelScalar(*pfLevel)
SetChannelVolumeLevel(nChannel,fLevelDB.f,pguidEventContext)
SetChannelVolumeLevelScalar( nChannel,fLevel.f,pguidEventContext)
GetChannelVolumeLevel( nChannel,*pfLevelDB.f)
GetChannelVolumeLevelScalar( nChannel,*pfLevel.f)
SetMute( bMute, pguidEventContext)
GetMute( *pbMute)
GetVolumeStepInfo( *pnStep, *pnStepCount)
VolumeStepUp( pguidEventContext)
VolumeStepDown( pguidEventContext)
QueryHardwareSupport( *pdwHardwareSupportMask)
GetVolumeRange( *pflVolumeMindB, *pflVolumeMaxdB, *pflVolumeIncrementdB)
EndInterface
Interface IMMDevice Extends IUnknown
Activate(iid, dwClsCtx, pActivationParams, ppInterface);
OpenPropertyStore( stgmAccess, ppProperties);
GetId(ppstrId);
GetState(pdwState);
EndInterface
Procedure GetEndPointVolume(*endpointvolume)
Protected deviceEnumerator.IMMDeviceEnumerator
Protected hr, defaultDevice.IMMDevice
CoInitialize_(#Null)
hr = CoCreateInstance_(?uuidof_MMDeviceEnumerator, #Null, #CLSCTX_INPROC_SERVER, ?uuidof_IMMDeviceEnumerator,@deviceEnumerator);#CLSCTX_ALL
hr = deviceEnumerator\GetDefaultAudioEndpoint(0, 1, @defaultDevice)
deviceEnumerator\Release()
hr = defaultDevice\Activate(?uuidof_IAudioEndpointVolume, #CLSCTX_INPROC_SERVER, #Null, *endpointVolume);
defaultDevice\release()
ProcedureReturn *endpointvolume
EndProcedure
Procedure FreeEndPointVolume(*endpointvolume.IAudioEndpointVolume)
*endpointvolume\release()
CoUninitialize_()
EndProcedure
Procedure MediaGetVolume()
Protected Volume.IAudioEndpointVolume
Protected volf.f
GetEndPointVolume(@Volume)
Volume\GetMasterVolumeLevelScalar(@volf)
volf = Round(volf * 100, #PB_Round_Nearest)
FreeEndPointVolume(Volume)
ProcedureReturn Int(volf)
EndProcedure
Procedure MediaGetMute()
Protected Volume.IAudioEndpointVolume
Protected mute.i
GetEndPointVolume(@Volume)
Volume\GetMute(@mute)
FreeEndPointVolume(Volume)
ProcedureReturn mute
EndProcedure
Procedure MediaSetVolume(vol)
Protected Volume.IAudioEndpointVolume
Protected volf.f
If vol < 0 : vol = 0 : EndIf
If vol > 100 : vol = 100 : EndIf
GetEndPointVolume(@Volume)
volf = vol / 100
Volume\SetMasterVolumeLevelScalar(volf, #Null)
FreeEndPointVolume(Volume)
EndProcedure
Procedure MediaSetMute(value)
Protected Volume.IAudioEndpointVolume
Protected mute.i=1
GetEndPointVolume(@Volume)
Volume\SetMute(value, #Null)
FreeEndPointVolume(Volume)
EndProcedure
DataSection
uuidof_IAudioEndpointVolume:
Data.l $5CDF2C82
Data.w $841E,$4546
Data.b $97,$22,$0C,$F7,$40,$78,$22,$9A
uuidof_MMDeviceEnumerator:
Data.l $BCDE0395
Data.w $E52F,$467C
Data.b $8E,$3D,$C4,$57,$92,$91,$69,$2E
uuidof_IMMDeviceEnumerator:
Data.l $A95664D2
Data.w $9614
Data.w $4F35
Data.b $A7,$46,$DE,$8D,$B6,$36,$17,$E6
EndDataSection
; Test prog: Set volume to 10% and mute the speakers, this should play loudly anyway...
If MediaGetMute()
MediaSetMute(0)
EndIf
MediaSetVolume(100)
Beep_(2500,500)
This code only seems to actually set mute, if I've already done so using the mute key on my keyboard. That is, if I reboot and use the MediaSetMute(1) function, the audio is not muted. If, OTOH, I mute and then unmute the audio via my keyboard, THEN the MediaSetMute(1) seems to work fine.
Any ideas?
Re: Get/Set Sound volume level programmatically
Posted: Sat Feb 22, 2025 8:43 am
by BarryG
The code here (in this topic) no longer compiles with PureBasic 6.20 ->
https://www.purebasic.fr/english/viewto ... 65#p403765
It's by ts-soft. If you're here, can you maybe fix it, please? The error -> "Line 30: Native types can't be used with pointers."
Re: Get/Set Sound volume level programmatically
Posted: Sat Feb 22, 2025 9:12 am
by Fred
Just remove the type and it should work
Re: Get/Set Sound volume level programmatically
Posted: Sat Feb 22, 2025 1:56 pm
by BarryG
Oh, I see. I did that and it works! Thanks, Fred.

I originally didn't know what that error message meant.
Old lines:
Code: Select all
GetChannelVolumeLevel(nChannel,*pfLevelDB.f)
GetChannelVolumeLevelScalar(nChannel,*pfLevel.f)
New lines:
Code: Select all
GetChannelVolumeLevel(nChannel,*pfLevelDB)
GetChannelVolumeLevelScalar(nChannel,*pfLevel)
Re: Get/Set Sound volume level programmatically
Posted: Sun May 11, 2025 1:24 am
by BarryG
Just a heads-up: if your PC does not have a sound card, or if it's disabled in Device Manager, then the below crash will occur. Took me forever to work out this problem - who would've guessed that some PCs run without audio!

So now I just need a reliable way to detect if a sound card is present or enabled so I can prevent this crash occurring. Anyone know?
Code: Select all
Procedure MediaGetVolume()
Protected Volume.IAudioEndpointVolume
Protected volf.f
GetEndPointVolume(@Volume)
Volume\GetMasterVolumeLevelScalar(@volf) ; Invalid access 0x3221225477 due to no sound card.
volf=Round(volf*100,#PB_Round_Nearest)
FreeEndPointVolume(Volume)
ProcedureReturn Int(volf)
EndProcedure