버전

menu_open
Wwise SDK 2024.1.0
AkMMDevice.h
이 파일의 문서화 페이지로 가기
1 /*******************************************************************************
2 The content of this file includes portions of the AUDIOKINETIC Wwise Technology
3 released in source code form as part of the SDK installer package.
4 
5 Commercial License Usage
6 
7 Licensees holding valid commercial licenses to the AUDIOKINETIC Wwise Technology
8 may use this file in accordance with the end user license agreement provided
9 with the software or, alternatively, in accordance with the terms contained in a
10 written agreement between you and Audiokinetic Inc.
11 
12 Apache License Usage
13 
14 Alternatively, this file may be used under the Apache License, Version 2.0 (the
15 "Apache License"); you may not use this file except in compliance with the
16 Apache License. You may obtain a copy of the Apache License at
17 http://www.apache.org/licenses/LICENSE-2.0.
18 
19 Unless required by applicable law or agreed to in writing, software distributed
20 under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
21 OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License for
22 the specific language governing permissions and limitations under the License.
23 
24  Copyright (c) 2024 Audiokinetic Inc.
25 *******************************************************************************/
26 
27 // AkMMDevice.h -- C++ RIAA object wrappers for Win32 MMDevice enumeration APIs
28 
29 #pragma once
30 
34 
35 // Fix for Windows SDK 10.0.17763.0
36 #if !defined(_DEBUG)
37 namespace Microsoft {
38  namespace WRL {
39  namespace Details {
40  template <typename T>
41  inline void CheckForDuplicateEntries() {}
42  }
43  }
44 }
45 #endif
46 
47 #include <mmdeviceapi.h>
48 
49 namespace AK
50 {
51  namespace Win32
52  {
54  {
55  public:
56  // Default constructor
58  {
59  PropVariantInit(&variant);
60  }
61 
62  // Construct a property from an existing property store
63  DeviceProperty(const PROPERTYKEY &key, IPropertyStore* in_pProps)
64  {
65  PropVariantInit(&variant);
66  if (in_pProps) in_pProps->GetValue(key, &variant);
67  }
68 
69  // Move constructor
71  {
72  variant = other.variant;
73  PropVariantInit(&other.variant);
74  }
75 
76  // Copy construction is not allowed
77  DeviceProperty(const DeviceProperty& other) = delete;
78 
79  // Destructor
81  {
82  PropVariantClear(&variant);
83  }
84 
85  // Move assignment
87  {
88  PropVariantClear(&variant);
89  variant = other.variant;
90  PropVariantInit(&other.variant);
91  return *this;
92  }
93 
94  // Copy assignment is not allowed
95  DeviceProperty& operator=(const DeviceProperty& other) = delete;
96 
97  bool IsEmpty() const { return variant.vt == VT_EMPTY; }
98 
99  PROPVARIANT variant;
100  };
101 
103  {
104  public:
105  // Default constructor
107  : pProps(nullptr)
108  {
109  }
110 
111  // Construct properties from an IMMDevice
112  DeviceProperties(IMMDevice* in_pDevice)
113  {
114  in_pDevice->OpenPropertyStore(STGM_READ, &pProps);
115  }
116 
117  // Move constructor
119  {
120  pProps = other.pProps;
121  other.pProps = nullptr;
122  }
123 
124  // Copy construction is not allowed
125  DeviceProperties(const DeviceProperties& other) = delete;
126 
127  // Destructor
129  {
130  if (pProps)
131  {
132  pProps->Release();
133  pProps = nullptr;
134  }
135  }
136 
137  // Move assignment
139  {
140  if (pProps)
141  pProps->Release();
142  pProps = other.pProps;
143  other.pProps = nullptr;
144  return *this;
145  }
146 
147  // Copy assignment is not allowed
148  DeviceProperties& operator=(const DeviceProperties& other) = delete;
149 
150  bool IsValid() { return pProps != nullptr; }
151 
152  DeviceProperty GetProperty(const PROPERTYKEY& key)
153  {
154  return DeviceProperty(key, pProps);
155  }
156 
157  IPropertyStore* pProps;
158  };
159  class Device
160  {
161  public:
162  // Default constructor
164  : pDevice(nullptr)
166  {
167  }
168 
169  // Move constructor
170  Device(Device&& other)
171  : pDevice(nullptr)
172  {
173  SetDevice(other.pDevice);
174  other.pDevice = nullptr;
175  }
176 
177  Device(const Device& other)
178  : pDevice(nullptr)
179  {
180  *this = other;
181  }
182 
183  // Destructor
185  {
186  if (pDevice)
187  {
188  pDevice->Release();
189  pDevice = nullptr;
190  }
191  }
192 
193  // Move assignment
195  {
196  if (pDevice)
197  {
198  pDevice->Release();
199  pDevice = nullptr; // Do not remove, protects against this == &other
200  }
201  pDevice = other.pDevice;
202  idDevice = other.idDevice;
203  other.pDevice = nullptr;
204  return *this;
205  }
206 
207  Device& operator=(const Device& other)
208  {
209  if (pDevice)
210  {
211  pDevice->Release();
212  pDevice = nullptr; // Do not remove, protects against this == &other
213  }
214  pDevice = other.pDevice;
215  if (pDevice)
216  pDevice->AddRef();
217  idDevice = other.idDevice;
218  return *this;
219  }
220 
221  Device& operator=(IMMDevice* pOther)
222  {
223  SetDevice(pOther);
224  if (pDevice)
225  pDevice->AddRef();
226  return *this;
227  }
228 
229  bool IsValid() const { return pDevice != nullptr; }
230 
232  {
234  }
235 
237  {
238  return DeviceProperties(pDevice);
239  }
240 
241  void ComputeId()
242  {
244  if (pDevice)
245  {
246  //Inlined version of GetDeviceID.
247  LPWSTR pwszID = NULL;
248  if (pDevice->GetId(&pwszID) == S_OK)
249  {
250  char szString[260];
251  AKPLATFORM::AkWideCharToChar(pwszID, 260 - 1, szString);
252  szString[260 - 1] = 0;
253 
254  idDevice = FNVHash32::ComputeLowerCase((const char*)szString);
255  CoTaskMemFree(pwszID);
256  }
257  }
258  }
259 
260  void SetDevice(IMMDevice* in_pNew)
261  {
262  if (pDevice)
263  pDevice->Release();
264  pDevice = in_pNew;
265  ComputeId();
266  }
267 
268  interface IMMDevice* pDevice;
270  };
272  {
273  public:
274  class Iterator
275  {
276  public:
277  Iterator(IMMDeviceCollection* in_pDevices, UINT in_i)
278  : pDevices(in_pDevices)
279  , i(in_i)
280  {
281  }
282 
283  /// + operator
285  {
286  Iterator returnedIt(pDevices, i + inc);
287  return returnedIt;
288  }
289 
290  /// - operator
291  AkUInt32 operator-(Iterator const& rhs) const
292  {
293  return (AkUInt32)(i - rhs.i);
294  }
295 
296  /// ++ operator
298  {
299  ++i;
300  return *this;
301  }
302 
303  /// -- operator
305  {
306  --i;
307  return *this;
308  }
309 
310  /// == operator
311  bool operator ==(const Iterator& in_rOp) const
312  {
313  return (pDevices == in_rOp.pDevices && i == in_rOp.i);
314  }
315 
316  /// != operator
317  bool operator !=(const Iterator& in_rOp) const
318  {
319  return (pDevices != in_rOp.pDevices || i != in_rOp.i);
320  }
321 
323  {
324  Device pDevice;
325  pDevices->Item(i, (IMMDevice**)&pDevice.pDevice); //Transfer the ref
326  if (pDevice.pDevice)
327  pDevice.ComputeId();
328  return pDevice;
329  }
330 
331  interface IMMDeviceCollection* pDevices; //Keep first.
332  UINT i;
333  };
334 
335  DeviceCollection(IMMDeviceEnumerator* pEnumerator)
336  : pDevices(nullptr)
337  , uCount(0)
338  {
339  pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATEMASK_ALL, &pDevices);
340  if (pDevices)
341  pDevices->GetCount(&uCount);
342  }
343  DeviceCollection(IMMDeviceEnumerator* pEnumerator, EDataFlow eFlow, DWORD dwStateMask)
344  : pDevices(nullptr)
345  , uCount(0)
346  {
347 
348  pEnumerator->EnumAudioEndpoints(eFlow, dwStateMask, &pDevices);
349  if (pDevices)
350  pDevices->GetCount(&uCount);
351  }
352 
353  // Move constructor
355  {
356  pDevices = other.pDevices;
357  uCount = other.uCount;
358  other.pDevices = nullptr;
359  other.uCount = 0;
360  }
361 
362  // Copy construction is not allowed
363  DeviceCollection(const DeviceCollection& other) = delete;
364 
365  // Destructor
367  {
368  if (pDevices)
369  {
370  pDevices->Release();
371  pDevices = nullptr;
372  }
373  }
374 
375  // Move assignment
377  {
378  if (pDevices)
379  {
380  pDevices->Release();
381  }
382  pDevices = other.pDevices;
383  uCount = other.uCount;
384  other.pDevices = nullptr;
385  other.uCount = 0;
386  return *this;
387  }
388 
389  // Copy assignment is not allowed
390  DeviceCollection& operator=(const DeviceCollection& other) = delete;
391 
392  bool IsValid() const { return pDevices != nullptr; }
393 
394  UINT Count() const
395  {
396  return uCount;
397  }
398 
400  {
401  Iterator it(pDevices, 0);
402  return it;
403  }
405  {
406  Iterator it(pDevices, uCount);
407  return it;
408  }
409 
410  interface IMMDeviceCollection* pDevices;
411  UINT uCount;
412  };
413 
415  {
416  public:
417 
419  : pEnumerator(nullptr)
420  {
421  CoCreateInstance(
422  __uuidof(MMDeviceEnumerator), NULL,
423  CLSCTX_ALL, __uuidof(IMMDeviceEnumerator),
424  (void**)&pEnumerator);
425  }
426 
427  // Move constructor
429  {
430  pEnumerator = other.pEnumerator;
431  other.pEnumerator = nullptr;
432  }
433 
434  // Copy construction is not allowed
435  DeviceEnumerator(const DeviceEnumerator& other) = delete;
436 
437  // Destructor
439  {
440  if (pEnumerator)
441  {
442  pEnumerator->Release();
443  pEnumerator = nullptr;
444  }
445  }
446 
447  // Move assignment
449  {
450  if (pEnumerator)
451  {
452  pEnumerator->Release();
453  }
454  pEnumerator = other.pEnumerator;
455  other.pEnumerator = nullptr;
456  return *this;
457  }
458 
459  // Copy assignment is not allowed
460  DeviceEnumerator& operator=(const DeviceEnumerator& other) = delete;
461 
462  bool IsValid() { return pEnumerator != nullptr; }
463 
464  Device GetDefaultDevice(ERole in_eRole)
465  {
466  Device pDevice;
467  pEnumerator->GetDefaultAudioEndpoint(eRender, in_eRole, (IMMDevice**)&pDevice.pDevice); //Transfer the ref
468  if (pDevice.pDevice)
469  pDevice.ComputeId();
470  return pDevice;
471  }
472 
473  interface IMMDeviceEnumerator* pEnumerator;
474  };
475 
476  /// Interface to access the IMMDevice cache. This avoids driver accesses.
478  {
479  public:
480  virtual AkUInt32 Count() = 0; ///Returns the number of devices. This function can block.
481  virtual Device Item(AkUInt32 in_idx) = 0; ///Gets item in_idx from the cache. Must be smaller than Count(). This function can block.
482  virtual void Lock() = 0; /// For thread safety. If you iterate through all the devices, lock the enumerator to avoid changes. However, if only accessing one single item, Item() is thread safe in itself.
483  virtual void Unlock() = 0; /// For thread safety. See \ref Lock()
484  virtual Device FindDevice(AkUInt32 in_id) = 0; ///Find a device that has this unique ID. The Id is one returned by AK::GetDeviceID.
485  };
486  }
487 };
AkUInt32 idDevice
Definition: AkMMDevice.h:269
AkUInt32 GetDeviceID() const
Definition: AkMMDevice.h:231
Definition of data structures for AkAudioObject
virtual Device Item(AkUInt32 in_idx)=0
Returns the number of devices. This function can block.
DeviceProperty(const PROPERTYKEY &key, IPropertyStore *in_pProps)
Definition: AkMMDevice.h:63
DeviceCollection(IMMDeviceEnumerator *pEnumerator, EDataFlow eFlow, DWORD dwStateMask)
Definition: AkMMDevice.h:343
DeviceProperties(const DeviceProperties &other)=delete
DeviceEnumerator & operator=(const DeviceEnumerator &other)=delete
Iterator(IMMDeviceCollection *in_pDevices, UINT in_i)
Definition: AkMMDevice.h:277
void SetDevice(IMMDevice *in_pNew)
Definition: AkMMDevice.h:260
DeviceProperty GetProperty(const PROPERTYKEY &key)
Definition: AkMMDevice.h:152
virtual void Lock()=0
Gets item in_idx from the cache. Must be smaller than Count(). This function can block.
Device & operator=(const Device &other)
Definition: AkMMDevice.h:207
DeviceProperties & operator=(DeviceProperties &&other)
Definition: AkMMDevice.h:138
static const AkDeviceID AK_INVALID_DEVICE_ID
Invalid streaming device ID
Definition: AkTypes.h:106
DeviceCollection(const DeviceCollection &other)=delete
DeviceProperties GetProperties() const
Definition: AkMMDevice.h:236
interface IMMDevice * pDevice
Definition: AkMMDevice.h:268
#define NULL
Definition: AkTypes.h:46
Device(const Device &other)
Definition: AkMMDevice.h:177
DeviceCollection & operator=(DeviceCollection &&other)
Definition: AkMMDevice.h:376
DeviceCollection(DeviceCollection &&other)
Definition: AkMMDevice.h:354
DeviceProperties & operator=(const DeviceProperties &other)=delete
Interface to access the IMMDevice cache. This avoids driver accesses.
Definition: AkMMDevice.h:478
DeviceProperty(const DeviceProperty &other)=delete
Iterator operator+(AkUInt32 inc) const
Definition: AkMMDevice.h:284
DeviceEnumerator(DeviceEnumerator &&other)
Definition: AkMMDevice.h:428
interface IMMDeviceCollection * pDevices
Definition: AkMMDevice.h:331
interface IMMDeviceEnumerator * pEnumerator
Definition: AkMMDevice.h:473
Device & operator=(Device &&other)
Definition: AkMMDevice.h:194
virtual AkUInt32 Count()=0
interface IMMDeviceCollection * pDevices
Definition: AkMMDevice.h:410
bool IsValid() const
Definition: AkMMDevice.h:229
bool operator!=(const Iterator &in_rOp) const
!= operator
Definition: AkMMDevice.h:317
IPropertyStore * pProps
Definition: AkMMDevice.h:157
DeviceProperty & operator=(const DeviceProperty &other)=delete
AkUInt32 operator-(Iterator const &rhs) const
Definition: AkMMDevice.h:291
DeviceEnumerator(const DeviceEnumerator &other)=delete
Iterator & operator++()
++ operator
Definition: AkMMDevice.h:297
DeviceProperties(IMMDevice *in_pDevice)
Definition: AkMMDevice.h:112
virtual void Unlock()=0
For thread safety. If you iterate through all the devices, lock the enumerator to avoid changes....
bool operator==(const Iterator &in_rOp) const
== operator
Definition: AkMMDevice.h:311
DeviceProperty(DeviceProperty &&other)
Definition: AkMMDevice.h:70
DeviceCollection(IMMDeviceEnumerator *pEnumerator)
Definition: AkMMDevice.h:335
uint32_t AkUInt32
Unsigned 32-bit integer
virtual Device FindDevice(AkUInt32 in_id)=0
For thread safety. See Lock()
Device & operator=(IMMDevice *pOther)
Definition: AkMMDevice.h:221
DeviceEnumerator & operator=(DeviceEnumerator &&other)
Definition: AkMMDevice.h:448
Device GetDefaultDevice(ERole in_eRole)
Definition: AkMMDevice.h:464
AkForceInline AkInt32 AkWideCharToChar(const wchar_t *in_pszUnicodeString, AkUInt32 in_uiOutBufferSize, char *io_pszAnsiString)
String conversion helper
DeviceCollection & operator=(const DeviceCollection &other)=delete
void CheckForDuplicateEntries()
Definition: AkMMDevice.h:41
Iterator & operator--()
– operator
Definition: AkMMDevice.h:304
static HashParams::HashType ComputeLowerCase(const char *in_pData)
Definition: AkFNVHash.h:130
Device(Device &&other)
Definition: AkMMDevice.h:170
DeviceProperty & operator=(DeviceProperty &&other)
Definition: AkMMDevice.h:86
DeviceProperties(DeviceProperties &&other)
Definition: AkMMDevice.h:118

이 페이지가 도움이 되었나요?

지원이 필요하신가요?

질문이 있으신가요? 문제를 겪고 계신가요? 더 많은 정보가 필요하신가요? 저희에게 문의해주시면 도와드리겠습니다!

지원 페이지를 방문해 주세요

작업하는 프로젝트에 대해 알려주세요. 언제든지 도와드릴 준비가 되어 있습니다.

프로젝트를 등록하세요. 아무런 조건이나 의무 사항 없이 빠른 시작을 도와드리겠습니다.

Wwise를 시작해 보세요