Hi,
I have write a class wrapper to Vista API audio functions to control the master volume (level and mute).
All functions of IAudioEndpointVolume Interface apper to work ok except the SetMute function.
The problem apper to be the parameter pguidEventContext of type Guid.
If I set the following value :
Guid nullGuid;
nullGuid = Guid.Empty;
int retVal = iAudioEndpoint.SetMute(true, nullGuid);
I obtain the error "value dows not fall within the expected range" while executin the SetMute function.
If I set a different guid value I obtain the error
"exception from HRESULT : 0x88890004" (error inside the COM library).All other functions work ok with null guid. Only the SetMute function apper to have problems even if the Microsoft documentation allow to use the null value.
This is the C# interface declaration
[
Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioEndpointVolume{
//virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RegisterControlChangeNotify(/* [in] */__in IAudioEndpointVolumeCallback *pNotify) = 0; int RegisterControlChangeNotify(IntPtr pNotify); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UnregisterControlChangeNotify(/* [in] */ __in IAudioEndpointVolumeCallback *pNotify) = 0; int UnregisterControlChangeNotify(IntPtr pNotify); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelCount(/* [out] */ __out UINT *pnChannelCount) = 0; int GetChannelCount(ref uint pnChannelCount); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMasterVolumeLevel( /* [in] */ __in float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetMasterVolumeLevel(float fLevelDB, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMasterVolumeLevelScalar( /* [in] */ __in float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetMasterVolumeLevelScalar(float fLevel, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMasterVolumeLevel(/* [out] */ __out float *pfLevelDB) = 0; int GetMasterVolumeLevel(ref float pfLevelDB); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMasterVolumeLevelScalar( /* [out] */ __out float *pfLevel) = 0; int GetMasterVolumeLevelScalar(ref float pfLevel); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetChannelVolumeLevel(/* [in] */__in UINT nChannel,float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetChannelVolumeLevel(uint nChannel, float fLevelDB, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetChannelVolumeLevelScalar(/* [in] */ __in UINT nChannel,float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelVolumeLevel(/* [in] */ __in UINT nChannel,/* [out] */__out float *pfLevelDB) = 0; int GetChannelVolumeLevel(uint nChannel, ref float pfLevelDB); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelVolumeLevelScalar(/* [in] */__in UINT nChannel,/* [out] */__out float *pfLevel) = 0; int GetChannelVolumeLevelScalar(uint nChannel, ref float pfLevel); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMute( /* [in] *__in BOOL bMute, /* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetMute(bool bMute, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMute( /* [out] */ __out BOOL *pbMute) = 0; int GetMute(ref bool pbMute); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVolumeStepInfo( /* [out] */ __out UINT *pnStep,/* [out] */__out UINT *pnStepCount) = 0; int GetVolumeStepInfo(ref uint pnStep, ref uint pnStepCount); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE VolumeStepUp( /* [unique][in] */ LPCGUID pguidEventContext) = 0; int VolumeStepUp(Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE VolumeStepDown(/* [unique][in] */ LPCGUID pguidEventContext) = 0; int VolumeStepDown(Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE QueryHardwareSupport(/* [out] */ __out DWORD *pdwHardwareSupportMask) = 0; int QueryHardwareSupport(ref uint pdwHardwareSupportMask); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVolumeRange( /* [out] */ __out float *pflVolumeMindB,/* [out] */ __out float *pflVolumeMaxdB,/* [out] */ __out float *pflVolumeIncrementdB) = 0; int GetVolumeRange(ref float pflVolumeMindB, ref float pflVolumeMaxdB, ref float pflVolumeIncrementdB);}
If someone have the same problem please replay to this message. I can provide the full C# class source code to verify the problem and to search a solution together.
Many thanks and have a nice Day
Max

Vista Master Volume Control with C#
Philipp Lamp
Note about the class usage :
1) Insert the class in your application.
2) Be sure you are working this Vista OS
3) Create a new instance to the object EndPointVolume (protected with a try-catch block)
4) Use the properties / methods of the object to control sound volume (run SndVol.exe to compare values)
5) Run the .Dispose(); methods before to close your application to release com objects
Jerod Moemeka
Additonal note : all other functions, that have the same "LPCGUID pguidEventContext" parameter declared by value are working correctly.
fighter92
Would you consider making your volume wrapper public
Daryl Faulkner
imran ud din
Jessica Alba
Hi Larry,
many thanks for your suggest. The pguidEventContext parameter is declared (by value) as described in the Microsoft on line documentation. See this link : http://msdn2.microsoft.com/en-us/library/ms678759.aspx
The SetMute method sets the muting state of the audio stream.
Parameters
bMute
[in] The new muting state. If bMute is TRUE, the method mutes the stream. If FALSE, the method turns off muting.
pguidEventContext
[in] Context value for the IAudioEndpointVolumeCallback::OnNotify method. This parameter points to an event-context GUID. If the SetMute call changes the muting state of the endpoint, all clients that have registered IAudioEndpointVolumeCallback interfaces with that endpoint will receive notifications. In its implementation of the OnNotify method, a client can inspect the event-context GUID to discover whether it or another client is the source of the control-change event. If the caller supplies a NULL pointer for this parameter, the notification routine receives the context GUID GUID_NULL.
Return Value
If the method succeeds, it returns S_OK. If it fails, it returns an error code.
Requirements
Client: Windows Vista
RaviKanthReddy
Max, did you try making the ref GUID change I mentioned above - I believe that your interops as posted above won't actually work.
Lovens
OK. Many thanks.
Max.
EwingMCSD
Hello,
I have written a delphi application in Vista to change the master volume. The application is developed using Delphi 5.
I have written a _TLB file for the MMDEVAPI.dll.
But I am getting the access violation exception for the FDevice.Activate call.
In the code,
FDevice.GetState function is working properly but for the activate call I am getting access violation in module mmdevapi.dll.
It is failing while 'write of some address'.
Following is the code for the MMDevApi_tlb.pas.
//------------------------------------------------------------------------
unit MMDevApi_tlb;
interface
uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL,ComObj;
const
// TypeLibrary Major and minor versions
CLASS_IMMDeviceEnumerator: TGUID = '{BCDE0395-E52F-467C-8E3D-C4579291692E}';
IID_IMMDeviceEnumerator: TGUID = '{A95664D2-9614-4F35-A746-DE8DB63617E6}';
IID_IMMDevice: TGUID = '{D666063F-1587-4E43-81F1-B948E807363F}';
IID_IMMDeviceCollection: TGUID = '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}';
IID_IAudioEndpointVolume: TGUID = '{5CDF2C82-841E-4546-9722-0CF74078229A}';
IID_IAudioMeterInformation : TGUID = '{C02216F6-8C67-4B5B-9D00-D008E73E0064}';
IID_IAudioEndpointVolumeCallback: TGUID = '{657804FA-D6AD-4496-8A60-352752AF4F89}';
DEVICE_STATE_ACTIVE = $00000001;
DEVICE_STATE_UNPLUGGED = $00000002;
DEVICE_STATE_NOTPRESENT = $00000004;
DEVICE_STATEMASK_ALL = $00000007;
type
EDataFlow = TOleEnum;
const
eRender = $00000000;
eCapture = $00000001;
eAll = $00000002;
EDataFlow_enum_count = $00000003;
type
ERole = TOleEnum;
const
eConsole = $00000000;
eMultimedia = $00000001;
eCommunications = $00000002;
ERole_enum_count = $00000003;
type
IAudioEndpointVolumeCallback = interface(IUnknown)
['{657804FA-D6AD-4496-8A60-352752AF4F89}']
end;
IMMAudioEndpointVolume = interface(IUnknown)
['{5CDF2C82-841E-4546-9722-0CF74078229A}']
Function RegisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
Function UnregisterControlChangeNotify( AudioEndPtVol: IAudioEndpointVolumeCallback): Integer; stdcall;
Function GetChannelCount(out PInteger): Integer; stdcall;
Function SetMasterVolumeLevel(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
Function SetMasterVolumeLevelScalar(fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
Function GetMasterVolumeLevel(out fLevelDB: double):Integer; stdcall;
Function GetMasterVolumeLevelScaler(out fLevel: double):Integer; stdcall;
Function SetChannelVolumeLevel(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
Function SetChannelVolumeLevelScalar(nChannel: Integer; fLevelDB: double; pguidEventContext: TGUID):Integer; stdcall;
Function GetChannelVolumeLevel(nChannel: Integer; out fLevelDB: double) : Integer; stdcall;
Function GetChannelVolumeLevelScalar(nChannel: Integer; out fLevel: double) : Integer; stdcall;
Function SetMute(bMute: Boolean ; pguidEventContext: TGUID) :Integer; stdcall;
Function GetMute(out bMute: Boolean ) :Integer; stdcall;
Function GetVolumeStepInfo( pnStep: Integer; out pnStepCount: Integer):Integer; stdcall;
Function VolumeStepUp(pguidEventContext: TGUID) :Integer; stdcall;
Function VolumeStepDown(pguidEventContext: TGUID) :Integer; stdcall;
Function QueryHardwareSupport(out pdwHardwareSupportMask): Integer; stdcall;
Function GetVolumeRange(out pflVolumeMindB: double; out pflVolumeMaxdB: double; out pflVolumeIncrementdB: double): Integer; stdcall;
end;
IPropertyStore = interface(IUnknown)
end;
type
IMMDevice = interface(IUnknown)
['{D666063F-1587-4E43-81F1-B948E807363F}']
Function Activate( refId :TGUID;
dwClsCtx: DWORD;
pActivationParams: PInteger ;
out pEndpointVolume: IMMAudioEndpointVolume): Hresult; stdCall;
Function OpenPropertyStore(stgmAccess: DWORD; out ppProperties :IPropertyStore): Hresult; stdcall;
Function GetId(out ppstrId: PLPWSTR ): Hresult; stdcall;
Function GetState(out State :Integer): Hresult; stdcall;
end;
IMMDeviceCollection = interface(IUnknown)
['{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}']
end;
IMMNotificationClient = interface (IUnknown)
['{7991EEC9-7E89-4D85-8390-6C703CEC60C0}']
end;
IMMDeviceEnumerator = interface(IUnknown)
['{A95664D2-9614-4F35-A746-DE8DB63617E6}']
Function EnumAudioEndpoints( dataFlow: EDataFlow; deviceState: SYSUINT; DevCollection:IMMDeviceCollection ): Hresult ; stdcall;
Function GetDefaultAudioEndpoint(EDF: SYSUINT; ER: SYSUINT; out Dev :IMMDevice ): Hresult ; stdcall;
Function GetDevice( pwstrId: pointer ; out Dev :IMMDevice) : HResult; stdcall;
Function RegisterEndpointNotificationCallback(pClient :IMMNotificationClient) :Hresult; stdcall;
end;
implementation
end.
//----------------------------------------------------------------------------------
Thanks in advance,
Mukta...
GeorgeOu
Here you are the C# class.
Look for the "TODO" string inside the lines code.
using
System;using
System.Collections.Generic;using
System.Text;using
System.Runtime.InteropServices;namespace
VistaVolumeControl{
/// <summary> /// This class allows to read and change the master volume in Vista (End Point Volume) /// </summary> public class EndpointVolume{
#region
Interface to COM objects const int DEVICE_STATE_ACTIVE = 0x00000001; const int DEVICE_STATE_DISABLE = 0x00000002; const int DEVICE_STATE_NOTPRESENT = 0x00000004; const int DEVICE_STATE_UNPLUGGED = 0x00000008; const int DEVICE_STATEMASK_ALL = 0x0000000f;[
DllImport("ole32.Dll")] static public extern uint CoCreateInstance(ref Guid clsid,[
MarshalAs(UnmanagedType.IUnknown)] object inner, uint context, ref Guid uuid,[
MarshalAs(UnmanagedType.IUnknown)] out object rReturnedComObject);
// C Header file : Include Mmdeviceapi.h (Windows Vista SDK)[
Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioEndpointVolume{
//virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RegisterControlChangeNotify(/* [in] */__in IAudioEndpointVolumeCallback *pNotify) = 0; //int RegisterControlChangeNotify(IntPtr pNotify); int RegisterControlChangeNotify(DelegateMixerChange pNotify); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UnregisterControlChangeNotify(/* [in] */ __in IAudioEndpointVolumeCallback *pNotify) = 0; //int UnregisterControlChangeNotify(IntPtr pNotify); int UnregisterControlChangeNotify(DelegateMixerChange pNotify); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelCount(/* [out] */ __out UINT *pnChannelCount) = 0; int GetChannelCount(ref uint pnChannelCount); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMasterVolumeLevel( /* [in] */ __in float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetMasterVolumeLevel(float fLevelDB, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMasterVolumeLevelScalar( /* [in] */ __in float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetMasterVolumeLevelScalar(float fLevel, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMasterVolumeLevel(/* [out] */ __out float *pfLevelDB) = 0; int GetMasterVolumeLevel(ref float pfLevelDB); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMasterVolumeLevelScalar( /* [out] */ __out float *pfLevel) = 0; int GetMasterVolumeLevelScalar(ref float pfLevel); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetChannelVolumeLevel(/* [in] */__in UINT nChannel,float fLevelDB,/* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetChannelVolumeLevel(uint nChannel, float fLevelDB, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetChannelVolumeLevelScalar(/* [in] */ __in UINT nChannel,float fLevel,/* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelVolumeLevel(/* [in] */ __in UINT nChannel,/* [out] */__out float *pfLevelDB) = 0; int GetChannelVolumeLevel(uint nChannel, ref float pfLevelDB); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetChannelVolumeLevelScalar(/* [in] */__in UINT nChannel,/* [out] */__out float *pfLevel) = 0; int GetChannelVolumeLevelScalar(uint nChannel, ref float pfLevel); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SetMute( /* [in] *__in BOOL bMute, /* [unique][in] */ LPCGUID pguidEventContext) = 0; int SetMute(bool bMute, Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMute( /* [out] */ __out BOOL *pbMute) = 0; int GetMute(ref bool pbMute); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVolumeStepInfo( /* [out] */ __out UINT *pnStep,/* [out] */__out UINT *pnStepCount) = 0; int GetVolumeStepInfo(ref uint pnStep, ref uint pnStepCount); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE VolumeStepUp( /* [unique][in] */ LPCGUID pguidEventContext) = 0; int VolumeStepUp(Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE VolumeStepDown(/* [unique][in] */ LPCGUID pguidEventContext) = 0; int VolumeStepDown(Guid pguidEventContext); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE QueryHardwareSupport(/* [out] */ __out DWORD *pdwHardwareSupportMask) = 0; int QueryHardwareSupport(ref uint pdwHardwareSupportMask); //virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetVolumeRange( /* [out] */ __out float *pflVolumeMindB,/* [out] */ __out float *pflVolumeMaxdB,/* [out] */ __out float *pflVolumeIncrementdB) = 0; int GetVolumeRange(ref float pflVolumeMindB, ref float pflVolumeMaxdB, ref float pflVolumeIncrementdB);}
[
Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMMDeviceCollection{
//HRESULT GetCount([out, annotation("__out")] UINT* pcDevices); int GetCount(ref uint pcDevices); //HRESULT Item([in, annotation("__in")]UINT nDevice, [out, annotation("__out")] IMMDevice** ppDevice); int Item(uint nDevice, ref IntPtr ppDevice);}
[
Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMMDevice{
//HRESULT Activate([in, annotation("__in")] REFIID iid, [in, annotation("__in")] DWORD dwClsCtx, [in,unique, annotation("__in_opt")] PROPVARIANT* pActivationParams, [out,iid_is(iid), annotation("__out")] void** ppInterface); int Activate(ref Guid iid, uint dwClsCtx, IntPtr pActivationParams, ref IntPtr ppInterface); //HRESULT OpenPropertyStore([in, annotation("__in")] DWORD stgmAccess, [out, annotation("__out")] IPropertyStore** ppProperties); int OpenPropertyStore(int stgmAccess, ref IntPtr ppProperties); //HRESULT GetId([out,annotation("__deref_out")] LPWSTR* ppstrId); int GetId(ref string ppstrId); //HRESULT GetState([out, annotation("__out")] DWORD* pdwState); int GetState(ref int pdwState);}
[
Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), //[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMMDeviceEnumerator{
//HRESULT EnumAudioEndpoints([in, annotation("__in")] EDataFlow dataFlow, [in, annotation("__in")] DWORD dwStateMask, [out, annotation("__out")] IMMDeviceCollection** ppDevices); int EnumAudioEndpoints(EDataFlow dataFlow, int dwStateMask, ref IntPtr ppDevices); //HRESULT GetDefaultAudioEndpoint([in, annotation("__in")] EDataFlow dataFlow, [in, annotation("__in")] ERole role, [out, annotation("__out")] IMMDevice** ppEndpoint); int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, ref IntPtr ppEndpoint); //HRESULT GetDevice([, annotation("__in")]LPCWSTR pwstrId, [out, annotation("__out")] IMMDevice** ppDevice); int GetDevice(string pwstrId, ref IntPtr ppDevice); //HRESULT RegisterEndpointNotificationCallback([in, annotation("__in")] IMMNotificationClient* pClient); int RegisterEndpointNotificationCallback(IntPtr pClient); //HRESULT UnregisterEndpointNotificationCallback([in, annotation("__in")] IMMNotificationClient* pClient); int UnregisterEndpointNotificationCallback(IntPtr pClient);}
[
Flags] enum CLSCTX : uint{
CLSCTX_INPROC_SERVER = 0x1,
CLSCTX_INPROC_HANDLER = 0x2,
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_INPROC_SERVER16 = 0x8,
CLSCTX_REMOTE_SERVER = 0x10,
CLSCTX_INPROC_HANDLER16 = 0x20,
CLSCTX_RESERVED1 = 0x40,
CLSCTX_RESERVED2 = 0x80,
CLSCTX_RESERVED3 = 0x100,
CLSCTX_RESERVED4 = 0x200,
CLSCTX_NO_CODE_DOWNLOAD = 0x400,
CLSCTX_RESERVED5 = 0x800,
CLSCTX_NO_CUSTOM_MARSHAL = 0x1000,
CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000,
CLSCTX_NO_FAILURE_LOG = 0x4000,
CLSCTX_DISABLE_AAA = 0x8000,
CLSCTX_ENABLE_AAA = 0x10000,
CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000,
CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
CLSCTX_ALL = CLSCTX_SERVER | CLSCTX_INPROC_HANDLER
}
public enum EDataFlow{
eRender,
eCapture,
eAll,
EDataFlow_enum_count
}
public enum ERole{
eConsole,
eMultimedia,
eCommunications,
ERole_enum_count
}
#endregion
// Private internal var object oEnumerator = null; IMMDeviceEnumerator iMde = null; object oDevice = null; IMMDevice imd = null; object oEndPoint = null; IAudioEndpointVolume iAudioEndpoint = null; // TODO // Problem #1 : I can't handle a volume changed event by other applications // (example while using the program SndVol.exe) public delegate void DelegateMixerChange(); //public DelegateMixerChange delMixerChange = null; public delegate void MixerChangedEventHandler(); //public event MixerChangedEventHandler MixerChanged;#region
Class Constructor and Dispose public methods /// <summary> /// Constructor /// </summary> public EndpointVolume(){
const uint CLSCTX_INPROC_SERVER = 1; Guid clsid = new Guid("BCDE0395-E52F-467C-8E3D-C4579291692E"); Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");oEnumerator =
null; uint hResult = CoCreateInstance(ref clsid, null, CLSCTX_INPROC_SERVER, ref IID_IUnknown, out oEnumerator); if (hResult != 0 || oEnumerator == null){
throw new Exception("CoCreateInstance() pInvoke failed");}
iMde = oEnumerator
as IMMDeviceEnumerator; if (iMde == null){
throw new Exception("COM cast failed to IMMDeviceEnumerator");}
IntPtr pDevice = IntPtr.Zero; int retVal = iMde.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole, ref pDevice); if (retVal != 0){
throw new Exception("IMMDeviceEnumerator.GetDefaultAudioEndpoint()");}
int dwStateMask = DEVICE_STATE_ACTIVE | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED; IntPtr pCollection = IntPtr.Zero;retVal = iMde.EnumAudioEndpoints(
EDataFlow.eRender, dwStateMask, ref pCollection); if (retVal != 0){
throw new Exception("IMMDeviceEnumerator.EnumAudioEndpoints()");}
oDevice = System.Runtime.InteropServices.
Marshal.GetObjectForIUnknown(pDevice);imd = oDevice
as IMMDevice; if (imd == null){
throw new Exception("COM cast failed to IMMDevice");}
Guid iid = new Guid("5CDF2C82-841E-4546-9722-0CF74078229A"); uint dwClsCtx = (uint)CLSCTX.CLSCTX_ALL; IntPtr pActivationParams = IntPtr.Zero; IntPtr pEndPoint = IntPtr.Zero;retVal = imd.Activate(
ref iid, dwClsCtx, pActivationParams, ref pEndPoint); if (retVal != 0){
throw new Exception("IMMDevice.Activate()");}
oEndPoint = System.Runtime.InteropServices.
Marshal.GetObjectForIUnknown(pEndPoint);iAudioEndpoint = oEndPoint
as IAudioEndpointVolume; if (iAudioEndpoint == null){
throw new Exception("COM cast failed to IAudioEndpointVolume");}
/*delMixerChange = new DelegateMixerChange(MixerChange);
retVal = iAudioEndpoint.RegisterControlChangeNotify(delMixerChange);
if (retVal != 0)
{
throw new Exception("iAudioEndpoint.RegisterControlChangeNotify(delMixerChange)");
}
*/
}
/// <summary> /// Call this method to release all com objetcs /// </summary> public virtual void Dispose(){
/*if (delMixerChange != null && iAudioEndpoint != null)
{
iAudioEndpoint.UnregisterControlChangeNotify(delMixerChange);
}
*/
if (iAudioEndpoint != null){
System.Runtime.InteropServices.
Marshal.ReleaseComObject(iAudioEndpoint);iAudioEndpoint =
null;}
if (oEndPoint != null){
System.Runtime.InteropServices.
Marshal.ReleaseComObject(oEndPoint);oEndPoint =
null;}
if (imd != null){
System.Runtime.InteropServices.
Marshal.ReleaseComObject(imd);imd =
null;}
if (oDevice != null){
System.Runtime.InteropServices.
Marshal.ReleaseComObject(oDevice);oDevice =
null;}
//System.Runtime.InteropServices.Marshal.ReleaseComObject(pCollection); if (iMde != null){
System.Runtime.InteropServices.
Marshal.ReleaseComObject(iMde);iMde =
null;}
if (oEnumerator != null){
System.Runtime.InteropServices.
Marshal.ReleaseComObject(oEnumerator);oEnumerator =
null;}
}
#endregion
#region
Private internal functions private void MixerChange(){
/*if (MixerChanged != null)
// Notify (raise) event
MixerChanged();
*/
}
#endregion
#region
Public properties /// <summary> /// Get/set the master mute. WARNING : The set mute do NOT work! /// </summary> public bool Mute{
get{
bool mute = false; int retVal = iAudioEndpoint.GetMute(ref mute); if (retVal != 0){
throw new Exception("IAudioEndpointVolume.GetMute() failed!");}
return mute;}
set{
//nullGuid = new Guid("{00000000-0000-0000-0000-000000000000}"); // null // {dddddddd-dddd-dddd-dddd-dddddddddddd} Guid nullGuid = Guid.Empty; bool mute = value; // TODO // Problem #2 : This function always terminate with an internal error! int retVal = iAudioEndpoint.SetMute(mute, nullGuid); if (retVal != 0){
throw new Exception("IAudioEndpointVolume.SetMute() failed!");}
}
}
/// <summary> /// Get/set the master volume level. Valid range is from 0.00F (0%) to 1.00F (100%). /// </summary> public float MasterVolume{
get{
float level = 0.0F; int retVal = iAudioEndpoint.GetMasterVolumeLevelScalar(ref level); if (retVal != 0){
throw new Exception("IAudioEndpointVolume.GetMasterVolumeLevelScalar()");}
return level;}
set{
float level = value; Guid nullGuid; //nullGuid = new Guid("{00000000-0000-0000-0000-000000000000}"); // null // {dddddddd-dddd-dddd-dddd-dddddddddddd}nullGuid =
Guid.Empty; int retVal = iAudioEndpoint.SetMasterVolumeLevelScalar(level, nullGuid); if (retVal != 0){
throw new Exception("IAudioEndpointVolume.SetMasterVolumeLevelScalar()");}
}
}
#endregion
#region
Public Methods /// <summary> /// Increase the master volume /// </summary> public void VolumeUp(){
Guid nullGuid; //nullGuid = new Guid("{00000000-0000-0000-0000-000000000000}"); // null // {dddddddd-dddd-dddd-dddd-dddddddddddd}nullGuid =
Guid.Empty; int retVal = iAudioEndpoint.VolumeStepUp(nullGuid); if (retVal != 0){
throw new Exception("IAudioEndpointVolume.SetMute()");}
}
/// <summary> /// Decrease the master volume /// </summary> public void VolumeDown(){
Guid nullGuid; //nullGuid = new Guid("{00000000-0000-0000-0000-000000000000}"); // null // {dddddddd-dddd-dddd-dddd-dddddddddddd}nullGuid =
Guid.Empty; int retVal = iAudioEndpoint.VolumeStepDown(nullGuid);}
#endregion
#region
GetSystemMute Example Function /*public static bool GetSystemMute()
{
bool mute = false;
object oEnumerator = null;
IMMDeviceEnumerator iMde = null;
object oDevice = null;
IMMDevice imd = null;
object oEndPoint = null;
IAudioEndpointVolume iAudioEndpoint = null;
try
{
//CoInitialize(NULL);
//IMMDeviceEnumerator* pEnumerator = NULL;
//IMMDeviceCollection* pCollection = NULL;
//HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,CLSCTX_INPROC_SERVER,__uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
//printf("Sucessfully created enumerator\n");
const uint CLSCTX_INPROC_SERVER = 1;
//Guid clsid = new Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"); //2147746132 - class is not registered
Guid clsid = new Guid("BCDE0395-E52F-467C-8E3D-C4579291692E");
Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
oEnumerator = null;
uint hResult = CoCreateInstance(ref clsid, null, CLSCTX_INPROC_SERVER, ref IID_IUnknown, out oEnumerator);
if (hResult != 0 || oEnumerator == null)
{
throw new Exception("CoCreateInstance() pInvoke failed");
}
iMde = oEnumerator as IMMDeviceEnumerator;
if (iMde == null)
{
throw new Exception("COM cast failed to IMMDeviceEnumerator");
}
//IMMDevice* pDevice = NULL;
//hr = pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice);
//EXIT_ON_ERROR(hr)
IntPtr pDevice = IntPtr.Zero;
int retVal = iMde.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eConsole, ref pDevice);
if (retVal != 0)
{
throw new Exception("IMMDeviceEnumerator.GetDefaultAudioEndpoint()");
}
//hr = pEnumerator->EnumAudioEndpoints(eCapture,DEVICE_STATE_ACTIVE | DEVICE_STATE_NOTPRESENT |DEVICE_STATE_UNPLUGGED,&pDevice );
int dwStateMask = DEVICE_STATE_ACTIVE | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED;
IntPtr pCollection = IntPtr.Zero;
retVal = iMde.EnumAudioEndpoints(EDataFlow.eRender, dwStateMask, ref pCollection);
if (retVal != 0)
{
throw new Exception("IMMDeviceEnumerator.EnumAudioEndpoints()");
}
oDevice = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pDevice);
imd = oDevice as IMMDevice;
if (imd == null)
{
throw new Exception("COM cast failed to IMMDevice");
}
//IAudioEndpointVolume* pEndPoint = NULL;
//hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL,NULL, (void **)&pEndPoint);
Guid iid = new Guid("5CDF2C82-841E-4546-9722-0CF74078229A");
uint dwClsCtx = (uint)CLSCTX.CLSCTX_ALL;
IntPtr pActivationParams = IntPtr.Zero;
IntPtr pEndPoint = IntPtr.Zero;
retVal = imd.Activate(ref iid, dwClsCtx, pActivationParams, ref pEndPoint);
if (retVal != 0)
{
throw new Exception("IMMDevice.Activate()");
}
oEndPoint = System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pEndPoint);
iAudioEndpoint = oEndPoint as IAudioEndpointVolume;
if (iAudioEndpoint == null)
{
throw new Exception("COM cast failed to IAudioEndpointVolume");
}
//float fLevelDB = 0.10;
//RetVal = pEndPoint->SetMasterVolumeLevel(&fLevelDB)
retVal = iAudioEndpoint.GetMute(ref mute);
if (retVal != 0)
{
throw new Exception("IAudioEndpointVolume.GetMute()");
}
//CoInitialize(NULL);
//IMMDeviceEnumerator* pEnumerator = NULL;
//IMMDeviceCollection* pCollection = NULL;
//HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),NULL,CLSCTX_INPROC_SERVER,__uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
//printf("Sucessfully created enumerator\n");
//IMMDevice* pDevice = NULL;
//hr = pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice);
//hr = pEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED, &pCollection);
//IAudioEndpointVolume* pEndPoint = NULL;
//hr = pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL,NULL,(void**)&pEndPoint);
//float fLevelDB = 0.00;
//HRESULT RetVal = pEndPoint->SetMasterVolumeLevel(fLevelDB, NULL);
//RetVal = pEndPoint->GetMasterVolumeLevel(&fLevelDB);
}
catch (Exception ex)
{
System.Console.WriteLine(ex.ToString());
throw;
}
finally
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(iAudioEndpoint);
iAudioEndpoint = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(oEndPoint);
oEndPoint = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(imd);
imd = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(oDevice);
oDevice = null;
//System.Runtime.InteropServices.Marshal.ReleaseComObject(pCollection);
System.Runtime.InteropServices.Marshal.ReleaseComObject(iMde);
iMde = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(oEnumerator);
oEnumerator = null;
}
return mute;
}
*/
#endregion
}
}
Deedhun
int SetMute(int bMute, Guid pguidEventContext);Instead. BOOL is actually a int, unless told otherwise to the marshaller. This'll work.
-- Jay
Bizzdreamer
And, as I've said several times before, the Guid parameter MUST be defined as "ref Guid" - it's a pointer to a guid, not the value of a GUID.
brad.p
An LPCGUID is a pointer to a const guid (const GUID *pguidEventContext). So you need to provide a pointer in the function signature, which means that you need to declare it as a ref parameter in managed code.
As I suggested above: Write your code in C++/CLR, which will allow you to use the actual function prototypes from AudioVolume.h instead of guessing what they might be.
Attila Fogel
I believe that your managed signatures are incorrect. In particular, I don't beleve that passing the pguidEventContext parameter in by value will work correctly - it needs to be passed in by reference (it's a pointer in unmanaged code).
Why not use C++/CLR and wrap the interface with your own