Created
July 19, 2016 18:00
-
-
Save Jaykul/c3bd8580df8ea49cd3ac737008a9bcef to your computer and use it in GitHub Desktop.
Playing With Volume...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add-Type -Path C:\Users\JBennett\Source\Repos\SoundUtils\SoundUtils\SoundUtils.cs | |
$volume = [WOSI.Utilities.EndpointVolume]::new() | |
$volume | gm | |
foreach($channel in 0..($volume.GetChannelCount()-1)) { | |
[PSCustomObject]@{Channel = $channel; Volume = $volume.GetChannelVolume($channel) } | |
} | |
$volume.SetChannelVolume(0, 0.5) | |
foreach($channel in 0..($volume.GetChannelCount()-1)) { | |
[PSCustomObject]@{Channel = $channel; Volume = $volume.GetChannelVolume($channel) } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/////////////////////////////////////////////////////////////////////////////////////////////// | |
// | |
// This File is Part of the CallButler Open Source PBX (http://www.codeplex.com/callbutler | |
// | |
// Copyright (c) 2005-2008, Jim Heising | |
// All rights reserved. | |
// | |
// Redistribution and use in source and binary forms, with or without modification, | |
// are permitted provided that the following conditions are met: | |
// | |
// * Redistributions of source code must retain the above copyright notice, | |
// this list of conditions and the following disclaimer. | |
// | |
// * Redistributions in binary form must reproduce the above copyright notice, | |
// this list of conditions and the following disclaimer in the documentation and/or | |
// other materials provided with the distribution. | |
// | |
// * Neither the name of Jim Heising nor the names of its contributors may be | |
// used to endorse or promote products derived from this software without specific prior | |
// written permission. | |
// | |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
// POSSIBILITY OF SUCH DAMAGE. | |
// | |
/////////////////////////////////////////////////////////////////////////////////////////////// | |
using System; | |
using System.Runtime.InteropServices; | |
using System.IO; | |
namespace WOSI.Utilities | |
{ | |
/// <summary> | |
/// Summary description for SoundUtilities. | |
/// </summary> | |
public sealed class SoundUtils | |
{ | |
public const int MMSYSERR_NOERROR = 0; | |
public const int MAXPNAMELEN = 32; | |
public const int MIXER_LONG_NAME_CHARS = 64; | |
public const int MIXER_SHORT_NAME_CHARS = 16; | |
public const int MIXER_GETLINEINFOF_COMPONENTTYPE = 0x3; | |
public const int MIXER_GETCONTROLDETAILSF_VALUE = 0x0; | |
public const int MIXER_GETLINECONTROLSF_ONEBYTYPE = 0x2; | |
public const int MIXER_SETCONTROLDETAILSF_VALUE = 0x0; | |
public const int MIXERLINE_COMPONENTTYPE_DST_FIRST = 0x0; | |
public const int MIXERLINE_COMPONENTTYPE_SRC_FIRST = 0x1000; | |
public const int MIXERLINE_COMPONENTTYPE_DST_SPEAKERS = (MIXERLINE_COMPONENTTYPE_DST_FIRST + 4); | |
public const int MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 3); | |
public const int MIXERLINE_COMPONENTTYPE_SRC_LINE = (MIXERLINE_COMPONENTTYPE_SRC_FIRST + 2); | |
public const int MIXERCONTROL_CT_CLASS_FADER = 0x50000000; | |
public const int MIXERCONTROL_CT_UNITS_UNSIGNED = 0x30000; | |
public const int MIXERCONTROL_CT_CLASS_SWITCH = 0x20000000; | |
public const int MIXERCONTROL_CT_SC_SWITCH_BOOLEAN = 0x0; | |
public const int MIXERCONTROL_CT_UNITS_BOOLEAN = 0x10000; | |
public const int MIXERCONTROL_CONTROLTYPE_FADER = (MIXERCONTROL_CT_CLASS_FADER | MIXERCONTROL_CT_UNITS_UNSIGNED); | |
public const int MIXERCONTROL_CONTROLTYPE_VOLUME = (MIXERCONTROL_CONTROLTYPE_FADER + 1); | |
public const int MIXERCONTROL_CONTROLTYPE_BOOLEAN = (MIXERCONTROL_CT_CLASS_SWITCH | MIXERCONTROL_CT_SC_SWITCH_BOOLEAN | MIXERCONTROL_CT_UNITS_BOOLEAN); | |
public const int MIXERCONTROL_CONTROLTYPE_MUTE = (MIXERCONTROL_CONTROLTYPE_BOOLEAN + 2); | |
public struct MIXERCAPS | |
{ | |
public int wMid; | |
public int wPid; | |
public int vDriverVersion; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXPNAMELEN)] | |
public string szPname; | |
public int fdwSupport; | |
public int cDestinations; | |
} | |
public struct MIXERCONTROL | |
{ | |
public int cbStruct; | |
public int dwControlID; | |
public int dwControlType; | |
public int fdwControl; | |
public int cMultipleItems; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_SHORT_NAME_CHARS)] | |
public string szShortName; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_LONG_NAME_CHARS)] | |
public string szName; | |
public int lMinimum; | |
public int lMaximum; | |
[MarshalAs(UnmanagedType.U4, SizeConst = 10)] | |
public int reserved; | |
} | |
public struct MIXERCONTROLDETAILS | |
{ | |
public int cbStruct; | |
public int dwControlID; | |
public int cChannels; | |
public int item; | |
public int cbDetails; | |
public IntPtr paDetails; | |
} | |
public struct MIXERCONTROLDETAILS_UNSIGNED | |
{ | |
public int dwValue; | |
} | |
public struct MIXERCONTROLDETAILS_BOOLEAN | |
{ | |
public int dwValue; | |
} | |
public struct MIXERLINE | |
{ | |
public int cbStruct; | |
public int dwDestination; | |
public int dwSource; | |
public int dwLineID; | |
public int fdwLine; | |
public int dwUser; | |
public int dwComponentType; | |
public int cChannels; | |
public int cConnections; | |
public int cControls; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_SHORT_NAME_CHARS)] | |
public string szShortName; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MIXER_LONG_NAME_CHARS)] | |
public string szName; | |
public int dwType; | |
public int dwDeviceID; | |
public int wMid; | |
public int wPid; | |
public int vDriverVersion; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXPNAMELEN)] | |
public string szPname; | |
} | |
public struct MIXERLINECONTROLS | |
{ | |
public int cbStruct; | |
public int dwLineID; | |
public int dwControl; | |
public int cControls; | |
public int cbmxctrl; | |
public IntPtr pamxctrl; | |
} | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerClose(int hmx); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerGetControlDetailsA(int hmxobj, ref MIXERCONTROLDETAILS pmxcd, int fdwDetails); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerGetDevCapsA(int uMxId, MIXERCAPS pmxcaps, int cbmxcaps); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerGetID(int hmxobj, int pumxID, int fdwId); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerGetLineControlsA(int hmxobj, ref MIXERLINECONTROLS pmxlc, int fdwControls); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerGetLineInfoA(int hmxobj, ref MIXERLINE pmxl, int fdwInfo); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerGetNumDevs(); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerMessage(int hmx, int uMsg, int dwParam1, int dwParam2); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerOpen(out int phmx, int uMxId, int dwCallback, int dwInstance, int fdwOpen); | |
[DllImport("winmm.dll", CharSet = CharSet.Ansi)] | |
public static extern int mixerSetControlDetails(int hmxobj, ref MIXERCONTROLDETAILS pmxcd, int fdwDetails); | |
[DllImport("winmm.dll", EntryPoint = "sndPlaySoundA")] | |
public static extern int sndPlaySound(string lpszSoundName, int uFlags); | |
public const int SND_ASYNC = 0x1; | |
public const int SND_LOOP = 0x8; | |
public SoundUtils() | |
{ | |
} | |
public static void PlaySound(string filename, bool loop) | |
{ | |
if (File.Exists(filename)) | |
{ | |
if (loop) | |
sndPlaySound(filename, SND_ASYNC | SND_LOOP); | |
else | |
sndPlaySound(filename, SND_ASYNC); | |
} | |
} | |
public static void StopSound() | |
{ | |
sndPlaySound(null, SND_ASYNC); | |
} | |
public static void Mute(bool mute) | |
{ | |
// Check if this is vista or XP | |
if (System.Environment.OSVersion.Version.Major >= 6) | |
{ | |
EndpointVolume epVol = new EndpointVolume(); | |
epVol.Mute = mute; | |
epVol.Dispose(); | |
} | |
else | |
{ | |
int mixerID = 0; | |
if (mixerOpen(out mixerID, 0, 0, 0, 0) == MMSYSERR_NOERROR) | |
{ | |
MIXERLINE line = new MIXERLINE(); | |
line.cbStruct = Marshal.SizeOf(line); | |
line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; | |
if (mixerGetLineInfoA(mixerID, ref line, MIXER_GETLINEINFOF_COMPONENTTYPE) == MMSYSERR_NOERROR) | |
{ | |
int sizeofMIXERCONTROL = 152; | |
MIXERCONTROL mixerControl = new MIXERCONTROL(); | |
MIXERLINECONTROLS lineControl = new MIXERLINECONTROLS(); | |
lineControl.pamxctrl = Marshal.AllocCoTaskMem(sizeofMIXERCONTROL); | |
lineControl.cbStruct = Marshal.SizeOf(lineControl); | |
lineControl.dwLineID = line.dwLineID; | |
lineControl.dwControl = MIXERCONTROL_CONTROLTYPE_MUTE; | |
lineControl.cControls = 1; | |
lineControl.cbmxctrl = sizeofMIXERCONTROL; | |
mixerControl.cbStruct = sizeofMIXERCONTROL; | |
if (mixerGetLineControlsA(mixerID, ref lineControl, MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR) | |
{ | |
mixerControl = (MIXERCONTROL)Marshal.PtrToStructure(lineControl.pamxctrl, typeof(MIXERCONTROL)); | |
MIXERCONTROLDETAILS controlDetails = new MIXERCONTROLDETAILS(); | |
MIXERCONTROLDETAILS_BOOLEAN muteValue = new MIXERCONTROLDETAILS_BOOLEAN(); | |
controlDetails.item = 0; | |
controlDetails.dwControlID = mixerControl.dwControlID; | |
controlDetails.cbStruct = Marshal.SizeOf(controlDetails); | |
controlDetails.cbDetails = Marshal.SizeOf(muteValue); | |
controlDetails.cChannels = 1; | |
muteValue.dwValue = Convert.ToInt32(mute); | |
controlDetails.paDetails = Marshal.AllocCoTaskMem(Marshal.SizeOf(muteValue)); | |
Marshal.StructureToPtr(muteValue, controlDetails.paDetails, false); | |
int rc = mixerSetControlDetails(mixerID, ref controlDetails, MIXER_SETCONTROLDETAILSF_VALUE); | |
Marshal.FreeCoTaskMem(controlDetails.paDetails); | |
Marshal.FreeCoTaskMem(lineControl.pamxctrl); | |
} | |
} | |
} | |
} | |
} | |
} | |
public class EndpointVolume | |
{ | |
private readonly Guid GuidEventContext = Guid.NewGuid(); | |
#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(int 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"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] //[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E"), | |
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 | |
// public 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 public internal functions | |
public 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 | |
{ | |
// TODO | |
// Problem #2 : This function always terminate with an internal error! | |
int retVal = iAudioEndpoint.SetMute(Convert.ToInt32(value), GuidEventContext); | |
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 | |
{ | |
int retVal = iAudioEndpoint.SetMasterVolumeLevelScalar(value, GuidEventContext); | |
if (retVal != 0) | |
{ | |
throw new Exception("IAudioEndpointVolume.SetMasterVolumeLevelScalar()"); | |
} | |
} | |
} | |
public uint GetChannelCount() | |
{ | |
uint result = 0; | |
int retVal = iAudioEndpoint.GetChannelCount(ref result); | |
Marshal.ThrowExceptionForHR(retVal); | |
return result; | |
} | |
public float GetChannelVolume(uint channel) | |
{ | |
float level = 0.0F; | |
int retVal = iAudioEndpoint.GetChannelVolumeLevelScalar(channel, ref level); | |
Marshal.ThrowExceptionForHR(retVal); | |
return level; | |
} | |
public void SetChannelVolume(uint channel, float level) | |
{ | |
int retVal = iAudioEndpoint.SetChannelVolumeLevelScalar(channel, level, GuidEventContext); | |
Marshal.ThrowExceptionForHR(retVal); | |
} | |
#endregion | |
#region Public Methods | |
/// <summary> | |
/// Increase the master volume | |
/// </summary> | |
public void VolumeUp() | |
{ | |
int retVal = iAudioEndpoint.VolumeStepUp(GuidEventContext); | |
Marshal.ThrowExceptionForHR(retVal); | |
} | |
/// <summary> | |
/// Decrease the master volume | |
/// </summary> | |
public void VolumeDown() | |
{ | |
int retVal = iAudioEndpoint.VolumeStepDown(GuidEventContext); | |
Marshal.ThrowExceptionForHR(retVal); | |
} | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment