Author |
Topic: Get and set master sound level (Read 450 times) |
|
RobM
Junior Member
member is offline


Posts: 91
|
 |
Re: Get and set master sound level
« Reply #8 on: Oct 12th, 2016, 5:56pm » |
|
Speaking for myself I would have to say I don't know if I would use it for anything other than this current idea. Knowing in the back of my mind that COM objects weren't possible with LB I never looked into what was possible in using them.
Offhand, do you have a general list of things that could be accomplished.
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 1348
|
 |
Re: Get and set master sound level
« Reply #9 on: Oct 13th, 2016, 7:29pm » |
|
on Oct 12th, 2016, 5:56pm, RobM wrote:| Speaking for myself I would have to say I don't know if I would use it for anything other than this current idea. |
|
OK, fair enough. There's a huge range of COM-based Windows API functions - pretty much any API introduced in the last ten years or so is probably a COM interface - but if it's not something you've ever wanted up to now, you probably never will.
Here's a direct, but not heavily commented, translation of the C++ code; it works in both LB 4 and LBB. It should be compatible with Windows Vista onwards:
Code: ' Translated to Liberty BASIC by Richard Russell from the code here, 13-Oct-2016:
' http://www.codeproject.com/Tips/233484/Change-Master-Volume-in-Visual-Cplusplus
result = ChangeVolume(0.5, 1)
end
function ChangeVolume(nVolume, bScalar)
open "ole32.dll" for dll as #ole32
open "oleaut32.dll" for dll as #oleaut32
calldll #ole32, "CoInitialize", 0 as long, r as void
IID.MMDeviceEnumerator$ = UUID$("{A95664D2-9614-4F35-A746-DE8DB63617E6}")
CLSID.MMDeviceEnumerator$ = UUID$("{BCDE0395-E52F-467C-8E3D-C4579291692E}")
IID.IAudioEndpointVolume$ = UUID$("{5CDF2C82-841E-4546-9722-0CF74078229A}")
CLSCTX.INPROC.SERVER = 1
eRender = 0
eConsole = 0
Release = 2
Activate = 3
GetDefaultAudioEndpoint = 4
SetMasterVolumeLevel = 6
SetMasterVolumeLevelScalar = 7
GetMasterVolumeLevel = 8
GetMasterVolumeLevelScalar = 9
struct IMM, deviceEnumerator as ulong
calldll #ole32, "CoCreateInstance", CLSID.MMDeviceEnumerator$ as ptr, _
0 as long, CLSCTX.INPROC.SERVER as long, IID.MMDeviceEnumerator$ as ptr, _
IMM as struct, hr as long
' hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
struct default, Device as ulong
struct parms, dataFlow as long, role as long, ppDevice as ptr
parms.dataFlow.struct = eRender
parms.role.struct = eConsole
parms.ppDevice.struct = default.struct
hr = CallMethod(IMM.deviceEnumerator.struct, GetDefaultAudioEndpoint, parms.struct)
default.struct = parms.ppDevice.struct
' hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume),
' CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
struct Iaudio, endpointVolume as ulong
struct parms, iid as ptr, dwClsCtx as long, _
pActivationParams as ulong, ppInterface as ptr
parms.iid.struct = IID.IAudioEndpointVolume$
parms.dwClsCtx.struct = CLSCTX.INPROC.SERVER
parms.ppInterface.struct = Iaudio.struct
hr = CallMethod(default.Device.struct, Activate, parms.struct)
Iaudio.struct = parms.ppInterface.struct
' defaultDevice->Release();
hr = CallMethod(default.Device.struct, Release, "")
default.Device.struct = 0
' endpointVolume->GetMasterVolumeLevel(¤tVolume);
struct Volume, float as long
struct parms, pfLevel as ptr
parms.pfLevel.struct = Volume.struct
hr = CallMethod(Iaudio.endpointVolume.struct, GetMasterVolumeLevel, parms.struct)
Volume.struct = parms.pfLevel.struct
' Convert float to double:
struct current, Volume as double
float = Volume.float.struct
calldll #oleaut32, "VarR8FromR4", float as long, current as struct, r as void
print "Current volume (dB) = "; current.Volume.struct
' hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume);
hr = CallMethod(Iaudio.endpointVolume.struct, GetMasterVolumeLevelScalar, parms.struct)
Volume.struct = parms.pfLevel.struct
' Convert float to double:
float = Volume.float.struct
calldll #oleaut32, "VarR8FromR4", float as long, current as struct, r as void
print "Current volume (scalar) = "; current.Volume.struct
' Set new volume:
struct parms, fLevel as ptr, EventContext as long
calldll #oleaut32, "VarR4FromR8", nVolume as double, parms as struct, r as void
if bScalar = 0 then
hr = CallMethod(Iaudio.endpointVolume.struct, SetMasterVolumeLevel, parms.struct)
else
hr = CallMethod(Iaudio.endpointVolume.struct, SetMasterVolumeLevelScalar, parms.struct)
end if
' endpointVolume->Release();
hr = CallMethod(Iaudio.endpointVolume.struct, Release, "")
Iaudio.endpointVolume.struct = 0
calldll #ole32, "CoUninitialize", r as void
close #oleaut32
close #ole32
end function
function UUID$(iid$)
l = len(iid$) + 1
wide$ = space$(2 * l) + chr$(0)
calldll #kernel32, "MultiByteToWideChar", 0 as long, 0 as long, _
iid$ as ptr, -1 as long, wide$ as ptr, l as long, r as long
UUID$ = space$(16) + chr$(0)
calldll #ole32, "CLSIDFromString", wide$ as ptr, UUID$ as ptr, r as long
end function
function CallMethod(object, method, parm$)
code$ = chr$(139)+"D$"+chr$(4)+chr$(139)+"T$"+chr$(8)+chr$(139)+"L$" _
+ chr$(16)+"VW"+chr$(139)+"t$"+chr$(20)+chr$(43)+chr$(225)+chr$(139) _
+ chr$(252)+chr$(243)+chr$(164)+chr$(80)+chr$(139)+chr$(0)+chr$(255) _
+ chr$(20)+chr$(144)+chr$(95)+chr$(94)+chr$(194)+chr$(16)+chr$(0)
p$ = parm$
n = len(p$)
calldll #user32, "CallWindowProcA", code$ as ptr, object as long,_
method as long, p$ as ptr, n as long, CallMethod as long
end function It's really annoying that structs are global in LB, since it means I can't make this a library function that can safely be called from any program.
Richard.
|
|
|
|
RobM
Junior Member
member is offline


Posts: 91
|
 |
Re: Get and set master sound level
« Reply #10 on: Oct 13th, 2016, 10:59pm » |
|
Thanks Richard!
I think I will add one more parameter to the function to specify whether it should check the sound level or change it. Looks like that should be easy enough.
|
|
Logged
|
|
|
|
RobM
Junior Member
member is offline


Posts: 91
|
 |
Re: Get and set master sound level
« Reply #11 on: Oct 14th, 2016, 03:15am » |
|
I ended up splitting it into a function & a sub and removed some (but not all) unneeded code. As is, this code will lower your volume 6 seconds after it sees it over 10.
My loops here are pretty ugly coding but this is just a quick demo :)
Thanks again Richard.
Code: DesiredVolume=10'volume as a percentage from 0 to 100, as Windows shows it in the master volume control
ResetTime=.1'time in minutes to wait after volume has been increased
[loop1]
scan
calldll #kernel32, "Sleep", 10 as long, re as void
CurrentVolume=GetVolume()
if CurrentVolume > DesiredVolume then
StartTime=GetTickCount()
goto [loop2]
end if
goto [loop1]
[loop2]
scan
calldll #kernel32, "Sleep", 10 as long, re as void
CurrentTime=GetTickCount()
if CurrentTime-StartTime > ResetTime*60*1000 then
call SetVolume DesiredVolume,1
goto [loop1]
end if
goto [loop2]
function GetVolume()
open "ole32.dll" for dll as #ole32
open "oleaut32.dll" for dll as #oleaut32
calldll #ole32, "CoInitialize", 0 as long, r as void
IID.MMDeviceEnumerator$ = UUID$("{A95664D2-9614-4F35-A746-DE8DB63617E6}")
CLSID.MMDeviceEnumerator$ = UUID$("{BCDE0395-E52F-467C-8E3D-C4579291692E}")
IID.IAudioEndpointVolume$ = UUID$("{5CDF2C82-841E-4546-9722-0CF74078229A}")
CLSCTX.INPROC.SERVER = 1
eRender = 0
eConsole = 0
Release = 2
Activate = 3
GetDefaultAudioEndpoint = 4
GetMasterVolumeLevel = 8
GetMasterVolumeLevelScalar = 9
struct IMM, deviceEnumerator as ulong
calldll #ole32, "CoCreateInstance", CLSID.MMDeviceEnumerator$ as ptr, _
0 as long, CLSCTX.INPROC.SERVER as long, IID.MMDeviceEnumerator$ as ptr, _
IMM as struct, hr as long
' hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
struct default, Device as ulong
struct parms, dataFlow as long, role as long, ppDevice as ptr
parms.dataFlow.struct = eRender
parms.role.struct = eConsole
parms.ppDevice.struct = default.struct
hr = CallMethod(IMM.deviceEnumerator.struct, GetDefaultAudioEndpoint, parms.struct)
default.struct = parms.ppDevice.struct
' hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume),
' CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
struct Iaudio, endpointVolume as ulong
struct parms, iid as ptr, dwClsCtx as long, _
pActivationParams as ulong, ppInterface as ptr
parms.iid.struct = IID.IAudioEndpointVolume$
parms.dwClsCtx.struct = CLSCTX.INPROC.SERVER
parms.ppInterface.struct = Iaudio.struct
hr = CallMethod(default.Device.struct, Activate, parms.struct)
Iaudio.struct = parms.ppInterface.struct
' defaultDevice->Release();
hr = CallMethod(default.Device.struct, Release, "")
default.Device.struct = 0
' endpointVolume->GetMasterVolumeLevel(¤tVolume);
struct Volume, float as long
struct parms, pfLevel as ptr
parms.pfLevel.struct = Volume.struct
hr = CallMethod(Iaudio.endpointVolume.struct, GetMasterVolumeLevel, parms.struct)
Volume.struct = parms.pfLevel.struct
' Convert float to double:
struct current, Volume as double
float = Volume.float.struct
calldll #oleaut32, "VarR8FromR4", float as long, current as struct, r as void
' hr = endpointVolume->GetMasterVolumeLevelScalar(¤tVolume);
hr = CallMethod(Iaudio.endpointVolume.struct, GetMasterVolumeLevelScalar, parms.struct)
Volume.struct = parms.pfLevel.struct
' Convert float to double:
float = Volume.float.struct
calldll #oleaut32, "VarR8FromR4", float as long, current as struct, r as void
GetVolume=int(current.Volume.struct*100+1)
' endpointVolume->Release();
hr = CallMethod(Iaudio.endpointVolume.struct, Release, "")
Iaudio.endpointVolume.struct = 0
calldll #ole32, "CoUninitialize", r as void
close #oleaut32
close #ole32
end function
sub SetVolume nVolume, bScalar
nVolume=nVolume/100
open "ole32.dll" for dll as #ole32
open "oleaut32.dll" for dll as #oleaut32
calldll #ole32, "CoInitialize", 0 as long, r as void
IID.MMDeviceEnumerator$ = UUID$("{A95664D2-9614-4F35-A746-DE8DB63617E6}")
CLSID.MMDeviceEnumerator$ = UUID$("{BCDE0395-E52F-467C-8E3D-C4579291692E}")
IID.IAudioEndpointVolume$ = UUID$("{5CDF2C82-841E-4546-9722-0CF74078229A}")
CLSCTX.INPROC.SERVER = 1
eRender = 0
eConsole = 0
Release = 2
Activate = 3
GetDefaultAudioEndpoint = 4
SetMasterVolumeLevelScalar = 7
struct IMM, deviceEnumerator as ulong
calldll #ole32, "CoCreateInstance", CLSID.MMDeviceEnumerator$ as ptr, _
0 as long, CLSCTX.INPROC.SERVER as long, IID.MMDeviceEnumerator$ as ptr, _
IMM as struct, hr as long
' hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
struct default, Device as ulong
struct parms, dataFlow as long, role as long, ppDevice as ptr
parms.dataFlow.struct = eRender
parms.role.struct = eConsole
parms.ppDevice.struct = default.struct
hr = CallMethod(IMM.deviceEnumerator.struct, GetDefaultAudioEndpoint, parms.struct)
default.struct = parms.ppDevice.struct
' hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume),
' CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
struct Iaudio, endpointVolume as ulong
struct parms, iid as ptr, dwClsCtx as long, _
pActivationParams as ulong, ppInterface as ptr
parms.iid.struct = IID.IAudioEndpointVolume$
parms.dwClsCtx.struct = CLSCTX.INPROC.SERVER
parms.ppInterface.struct = Iaudio.struct
hr = CallMethod(default.Device.struct, Activate, parms.struct)
Iaudio.struct = parms.ppInterface.struct
' defaultDevice->Release();
hr = CallMethod(default.Device.struct, Release, "")
default.Device.struct = 0
' Set new volume:
struct Volume, float as long
struct parms, fLevel as ptr, EventContext as long
calldll #oleaut32, "VarR4FromR8", nVolume as double, parms as struct, r as void
hr = CallMethod(Iaudio.endpointVolume.struct, SetMasterVolumeLevelScalar, parms.struct)
' endpointVolume->Release();
hr = CallMethod(Iaudio.endpointVolume.struct, Release, "")
Iaudio.endpointVolume.struct = 0
calldll #ole32, "CoUninitialize", r as void
close #oleaut32
close #ole32
end sub
function UUID$(iid$)
l = len(iid$) + 1
wide$ = space$(2 * l) + chr$(0)
calldll #kernel32, "MultiByteToWideChar", 0 as long, 0 as long, _
iid$ as ptr, -1 as long, wide$ as ptr, l as long, r as long
UUID$ = space$(16) + chr$(0)
calldll #ole32, "CLSIDFromString", wide$ as ptr, UUID$ as ptr, r as long
end function
function CallMethod(object, method, parm$)
code$ = chr$(139)+"D$"+chr$(4)+chr$(139)+"T$"+chr$(8)+chr$(139)+"L$" _
+ chr$(16)+"VW"+chr$(139)+"t$"+chr$(20)+chr$(43)+chr$(225)+chr$(139) _
+ chr$(252)+chr$(243)+chr$(164)+chr$(80)+chr$(139)+chr$(0)+chr$(255) _
+ chr$(20)+chr$(144)+chr$(95)+chr$(94)+chr$(194)+chr$(16)+chr$(0)
p$ = parm$
n = len(p$)
calldll #user32, "CallWindowProcA", code$ as ptr, object as long,_
method as long, p$ as ptr, n as long, CallMethod as long
end function
function GetTickCount()
calldll #kernel32, "GetTickCount",_
GetTickCount as ulong
end function
|
| « Last Edit: Oct 14th, 2016, 03:16am by RobM » |
Logged
|
|
|
|
RobM
Junior Member
member is offline


Posts: 91
|
 |
Re: Get and set master sound level
« Reply #12 on: Oct 14th, 2016, 06:12am » |
|
The two loops in the code above can be replaced with this this. Makes it easier to insert into a program with a single loop ;)
Code:[loop]
scan
calldll #kernel32, "Sleep", 10 as long, re as void
CurrentTime=GetTickCount()
CurrentVolume=GetVolume()
if CurrentVolume>DesiredVolume and CountDownStarted=0 then
StartTime=GetTickCount()
CountDownStarted=1
end if
if CurrentTime-StartTime > ResetTime*60*1000 then
call SetVolume DesiredVolume, 1
CountDownStarted=0
end if
goto [loop]
|
| « Last Edit: Oct 14th, 2016, 06:13am by RobM » |
Logged
|
|
|
|
|