-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathMMDeviceAPI.cs
More file actions
211 lines (167 loc) · 8.41 KB
/
MMDeviceAPI.cs
File metadata and controls
211 lines (167 loc) · 8.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Collections;
using static FlowTimer.MMDeviceAPI;
namespace FlowTimer {
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WAVEFORMATEX {
public ushort wFormatTag;
public short nChannels;
public int nSamplesPerSec;
public int nAvgBytesPerSec;
public short nBlockAlign;
public short wBitsPerSample;
public short cbSize;
}
[StructLayout(LayoutKind.Explicit)]
public struct WAVEFORMATEXTENSIBLE {
[FieldOffset(0x00)] public WAVEFORMATEX Format;
[FieldOffset(0x12)] public short wValidBitsPerSample;
[FieldOffset(0x12)] public short wSamplesPerBlock;
[FieldOffset(0x12)] public short wValidBitsPewReservedrSample;
[FieldOffset(0x14)] public uint dwChannelMask;
[FieldOffset(0x18)] public Guid SubFormat;
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMDevice {
int Activate(ref Guid iid, uint dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
}
[Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMDeviceCollection {
int GetCount(out int pcDevices);
int Item(int nDevice, out IMMDevice ppDevice);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMMDeviceEnumerator {
int EnumAudioEndpoints(DataFlow dataFlow, uint dwStateMask, out IMMDeviceCollection ppDevices);
int GetDefaultAudioEndpoint(DataFlow dataFlow, Role role, out IMMDevice ppEndPoint);
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("7ED4EE07-8E67-4CD4-8C1A-2B7A5987AD42")]
public interface IAudioClient3 {
int Initialize(uint shareMode, uint streamFlags, long hnsBufferDuration, long hnsPeriodicity, WAVEFORMATEX pFormat, IntPtr audioSessionGuid);
int GetBufferSize(out uint bufferSize);
[return: MarshalAs(UnmanagedType.I8)] long GetStreamLatency();
int GetCurrentPadding(out int currentPadding);
int IsFormatSupported(uint shareMode, WAVEFORMATEX pFormat, out IntPtr closestMatchFormat);
int GetMixFormat(out IntPtr deviceFormatPointer);
int GetDevicePeriod(out long defaultDevicePeriod, out long minimumDevicePeriod);
int Start();
int Stop();
int Reset();
int SetEventHandle(IntPtr eventHandle);
int GetService([MarshalAs(UnmanagedType.LPStruct)] Guid interfaceId, [MarshalAs(UnmanagedType.IUnknown)] out object interfacePointer);
void IsOffloadCapable(int category, out bool pbOffloadCapable);
void SetClientProperties(IntPtr pProperties);
void GetBufferSizeLimits(IntPtr pFormat, bool bEventDriven, out long phnsMinBufferDuration, out long phnsMaxBufferDuration);
int GetSharedModeEnginePeriod(IntPtr pFormat, out int pDefaultPeriodInFrames, out int pFundementalPeriodInFrames, out int pMinPeriodInFrames, out int pMaxPeriodInFrames);
int GetCurrentSharedModeEnginePeriod(IntPtr ppFormat, out uint pCurrentPeriodInFrames);
}
public class MMDevice {
private IMMDevice Interface;
public MMDevice(IMMDevice interfaceIn) => Interface = interfaceIn;
public AudioClient CreateAudioCilent() {
Interface.Activate(ref IAudioClient3ID, CLSCTX_ALL, IntPtr.Zero, out object audioClientInterface);
return new AudioClient(audioClientInterface as IAudioClient3);
}
}
public class MMDeviceCollection : IEnumerable<MMDevice> {
private IMMDeviceCollection Interface;
public MMDeviceCollection(IMMDeviceCollection interfaceIn) => Interface = interfaceIn;
public int Count {
get {
Interface.GetCount(out int result);
return result;
}
}
public MMDevice this[int index] {
get {
Interface.Item(index, out IMMDevice result);
return new MMDevice(result);
}
}
public IEnumerator<MMDevice> GetEnumerator() {
for(int i = 0; i < Count; i++) {
yield return this[i];
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
public class MMDeviceEnumerator {
private IMMDeviceEnumerator Interface;
public MMDeviceEnumerator(IMMDeviceEnumerator interfaceIn) => Interface = interfaceIn;
public MMDeviceCollection EnumerateAudioEndPoints(DataFlow dataFlow, uint dwStateMask) {
Interface.EnumAudioEndpoints(dataFlow, dwStateMask, out IMMDeviceCollection result);
return new MMDeviceCollection(result);
}
public MMDevice GetDefaultAudioEndpoint(DataFlow dataFlow, Role role) {
Interface.GetDefaultAudioEndpoint(dataFlow, role, out IMMDevice result);
return new MMDevice(result);
}
}
public class AudioClient {
private IAudioClient3 Interface;
public AudioClient(IAudioClient3 interfaceIn) => Interface = interfaceIn;
public IntPtr MixFormat {
get {
Interface.GetMixFormat(out IntPtr result);
return result;
}
}
public void GetSharedModeEnginePeriod(out int defaultPeriod, out int fundementalPeriod, out int minPeriod, out int maxPeriod) {
Interface.GetSharedModeEnginePeriod(MixFormat, out defaultPeriod, out fundementalPeriod, out minPeriod, out maxPeriod);
}
}
public enum DataFlow : uint {
Render,
Capture,
All,
}
public enum Role : uint {
Console,
Multimedia,
Communications,
}
public static class MMDeviceAPI {
public static Guid MMDeviceEnumeratorID = new Guid("BCDE0395-E52F-467C-8E3D-C4579291692E");
public static Guid IAudioClient3ID = new Guid("7ED4EE07-8E67-4CD4-8C1A-2B7A5987AD42");
public const uint DEVICE_STATE_ACTIVATE = 0x1;
public const uint DEVICE_STATE_DISABLED = 0x2;
public const uint DEVICE_STATE_NOTPRESENT = 0x4;
public const uint DEVICE_STATE_UNPLUGGED = 0x8;
public const uint CLSCTX_INPROC_SERVER = 0x1;
public const uint CLSCTX_INPROC_HANDLER = 0x2;
public const uint CLSCTX_LOCAL_SERVER = 0x4;
public const uint CLSCTX_INPROC_SERVER16 = 0x8;
public const uint CLSCTX_REMOTE_SERVER = 0x10;
public const uint CLSCTX_INPROC_HANDLER16 = 0x20;
public const uint CLSCTX_RESERVED1 = 0x40;
public const uint CLSCTX_RESERVED2 = 0x80;
public const uint CLSCTX_RESERVED3 = 0x100;
public const uint CLSCTX_RESERVED4 = 0x200;
public const uint CLSCTX_NO_CODE_DOWNLOAD = 0x400;
public const uint CLSCTX_RESERVED5 = 0x800;
public const uint CLSCTX_NO_CUSTOM_MARSHAL = 0x1000;
public const uint CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000;
public const uint CLSCTX_NO_FAILURE_LOG = 0x4000;
public const uint CLSCTX_DISABLE_AAA = 0x8000;
public const uint CLSCTX_ENABLE_AAA = 0x10000;
public const uint CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000;
public const uint CLSCTX_ACTIVATE_32_BIT_SERVER = 0x40000;
public const uint CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000;
public const uint CLSCTX_ENABLE_CLOAKING = 0x100000;
public const uint CLSCTX_PS_DLL = 0x80000000;
public const uint CLSCTX_INPROC = CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER;
public const uint CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER;
public const uint CLSCTX_ALL = CLSCTX_SERVER | CLSCTX_INPROC_HANDLER;
public static MMDeviceEnumerator CreateMMDeviceEnumerator() {
return new MMDeviceEnumerator(CreateInternal<IMMDeviceEnumerator>(MMDeviceEnumeratorID));
}
private static T CreateInternal<T>(Guid guid) {
Type type = Type.GetTypeFromCLSID(guid);
return (T) Activator.CreateInstance(type);
}
}
}