Get/Set Sound volume level programmatically

Just starting out? Need help? Post your questions and find answers here.
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Get/Set Sound volume level programmatically

Post by mk-soft »

Update the original code from ts-soft ;)

Code: Select all

;-TOP
; Comment   : Window Media Volume
; Author    : ts-soft
; Create    : 08.02.2013
; Link      : https://www.purebasic.fr/english/viewtopic.php?p=403765#p403765

; Author 2  : mk-soft
; Update    : 11.05.2025
; Link      : https://www.purebasic.fr/english/viewtopic.php?p=640610#p640610

EnableExplicit

#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)
  GetChannelVolumeLevelScalar( nChannel,*pfLevel)
  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
  
  If *endpointvolume = 0
    ProcedureReturn 0
  EndIf
  hr = CoInitialize_(#Null)
  If hr <> #S_OK And hr <> #S_FALSE
    ProcedureReturn 0
  EndIf
  hr = CoCreateInstance_(?uuidof_MMDeviceEnumerator, #Null, #CLSCTX_INPROC_SERVER, ?uuidof_IMMDeviceEnumerator,@deviceEnumerator);#CLSCTX_ALL
  If hr <> #S_OK
    ProcedureReturn 0
  EndIf
  hr = deviceEnumerator\GetDefaultAudioEndpoint(0, 1, @defaultDevice)
  If hr <> #S_OK
    ProcedureReturn 0
  EndIf
  deviceEnumerator\Release()

  hr = defaultDevice\Activate(?uuidof_IAudioEndpointVolume, #CLSCTX_INPROC_SERVER, #Null, *endpointVolume);
  If hr <> #S_OK
    ProcedureReturn 0
  EndIf
  defaultDevice\release()
 
  ProcedureReturn *endpointvolume
EndProcedure

Procedure FreeEndPointVolume(*endpointvolume.IAudioEndpointVolume) 
  If *endpointvolume
    *endpointvolume\release()
    CoUninitialize_()
  EndIf
EndProcedure

Procedure MediaGetVolume()
  Protected Volume.IAudioEndpointVolume
  Protected volf.f

  If GetEndPointVolume(@Volume)
    Volume\GetMasterVolumeLevelScalar(@volf)
    volf = Round(volf * 100, #PB_Round_Nearest)
    FreeEndPointVolume(Volume)
    ProcedureReturn Int(volf)
  Else
    ProcedureReturn -1
  EndIf
EndProcedure

Procedure MediaSetVolume(vol)
  Protected Volume.IAudioEndpointVolume
  Protected volf.f
  If vol < 0
    vol = 0
  EndIf
  If vol > 100
    vol = 100
  EndIf
  If GetEndPointVolume(@Volume)
    volf = vol / 100
    Volume\SetMasterVolumeLevelScalar(volf, #Null)
    FreeEndPointVolume(Volume)
  EndIf
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 

CompilerIf #PB_Compiler_IsMainFile
  Define Object, volume
  If Not GetEndPointVolume(@Object)
    MessageRequester("Warning", "No Sound Card!", #PB_MessageRequester_Warning)
    ;Debug MediaGetVolume()
  Else
    FreeEndPointVolume(Object)
    volume = MediaGetVolume()
    Debug volume
  EndIf
CompilerEndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 4123
Joined: Thu Apr 18, 2019 8:17 am

Re: Get/Set Sound volume level programmatically

Post by BarryG »

mk-soft wrote: Sun May 11, 2025 10:57 am

Code: Select all

If Not GetEndPointVolume(@Object)
Thanks, mk-soft! That does the trick. :) I did get some ChatGPT code to use WMIC to check, but your way is cleaner and better.
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Get/Set Sound volume level programmatically

Post by mk-soft »

The evaluation of whether the objects are also created and available was missing.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply