UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
wasapi.cpp File Reference
#include <audioclient.h>
#include <audiosessiontypes.h>
#include <basetsd.h>
#include <cassert>
#include <cctype>
#include <combaseapi.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <ksmedia.h>
#include <mediaobj.h>
#include <mmdeviceapi.h>
#include <mmeapi.h>
#include <mmreg.h>
#include <objbase.h>
#include <propidl.h>
#include <propsys.h>
#include <sstream>
#include <string>
#include <winerror.h>
#include "audio/audio_playback.h"
#include "audio/types.h"
#include "debug.h"
#include "host.h"
#include "lib_common.h"
#include "types.h"
#include "ug_runtime_error.hpp"
#include "utils/color_out.h"
#include "utils/windows.h"
Include dependency graph for wasapi.cpp:

Go to the source code of this file.

Classes

struct  state_aplay_wasapi
 

Macros

#define CHECK(cmd)
 
#define DEFAULT_WASAPI_BUFLEN_MS   67
 
#define FAIL_IF_NOT(cmd)
 
#define MOD_NAME   "[WASAPI play.] "
 
#define REFTIMES_PER_MILLISEC   10000
 
#define REFTIMES_PER_SEC   10000000
 
#define SAFE_RELEASE(u)
 
#define THROW_IF_FAILED(cmd)
 

Functions

static WAVEFORMATEXTENSIBLE audio_format_to_waveformatex (struct audio_desc *desc)
 
static bool audio_play_wasapi_ctl (void *state, int request, void *data, size_t *len)
 
static void audio_play_wasapi_done (void *state)
 
static void audio_play_wasapi_help ()
 
static void * audio_play_wasapi_init (const char *cfg)
 
static void audio_play_wasapi_probe (struct device_info **available_devices, int *dev_count, void(**deleter)(void *))
 
static void audio_play_wasapi_put_frame (void *state, const struct audio_frame *buffer)
 
static bool audio_play_wasapi_reconfigure (void *state, struct audio_desc desc)
 
static DWORD get_channel_mask (int *count)
 
static string get_name (IMMDevice *pDevice)
 
 REGISTER_MODULE (wasapi, &aplay_wasapi_info, LIBRARY_CLASS_AUDIO_PLAYBACK, AUDIO_PLAYBACK_ABI_VERSION)
 
string wasapi_get_default_device_id (EDataFlow dataFlow, IMMDeviceEnumerator *enumerator)
 

Variables

static const struct audio_playback_info aplay_wasapi_info
 
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator)
 
static const GUID IDevice_FriendlyName = { 0xa45c254e, 0xdf1c, 0x4efd, { 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0 } }
 
const IID IID_IAudioClient = __uuidof(IAudioClient)
 
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient)
 
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator)
 
static const PROPERTYKEY PKEY_Device_FriendlyName = { IDevice_FriendlyName, 14 }
 
static const GUID UG_KSDATAFORMAT_SUBTYPE_PCM = { STATIC_KSDATAFORMAT_SUBTYPE_PCM }
 

Detailed Description

Author
Martin Pulec marti.nosp@m.n.pu.nosp@m.lec@c.nosp@m.esne.nosp@m.t.cz
Todo

Code for probe and help is very similar - consolidate.

Audio buffer length should be rather adaptive to length of incoming frames.

Definition in file wasapi.cpp.

Macro Definition Documentation

◆ CHECK

#define CHECK ( cmd)
Value:
do {HRESULT hr = cmd; if (hr != S_OK) { LOG(LOG_LEVEL_ERROR) << MOD_NAME << #cmd ": " << hresult_to_str(hr) << "\n"; return;}} while(0)
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG(level)
Definition debug.h:313
#define MOD_NAME
Definition wasapi.cpp:64

Definition at line 374 of file wasapi.cpp.

Referenced by ultragrid::aja::display::display(), ultragrid::aja::display::~display(), audio_play_wasapi_put_frame(), ultragrid::aja::display::Init(), ultragrid::aja::display::process_frames(), ultragrid::aja::display::RouteOutputSignal(), ultragrid::aja::display::SetUpAudio(), and ultragrid::aja::display::SetUpVideo().

◆ DEFAULT_WASAPI_BUFLEN_MS

#define DEFAULT_WASAPI_BUFLEN_MS   67

Definition at line 63 of file wasapi.cpp.

Referenced by audio_play_wasapi_reconfigure().

◆ FAIL_IF_NOT

#define FAIL_IF_NOT ( cmd)
Value:
do {HRESULT hr = cmd; if (hr != S_OK) { LOG(LOG_LEVEL_ERROR) << MOD_NAME << #cmd << ": " << hresult_to_str(hr) << "\n"; return false;}} while(0)

Definition at line 351 of file wasapi.cpp.

Referenced by audio_play_wasapi_reconfigure().

◆ MOD_NAME

◆ REFTIMES_PER_MILLISEC

#define REFTIMES_PER_MILLISEC   10000

Definition at line 66 of file wasapi.cpp.

Referenced by audio_play_wasapi_reconfigure().

◆ REFTIMES_PER_SEC

#define REFTIMES_PER_SEC   10000000

Definition at line 65 of file wasapi.cpp.

◆ SAFE_RELEASE

#define SAFE_RELEASE ( u)
Value:
do { if ((u) != NULL) (u)->Release(); (u) = NULL; } while(0)

Definition at line 97 of file wasapi.cpp.

97#define SAFE_RELEASE(u) \
98 do { if ((u) != NULL) (u)->Release(); (u) = NULL; } while(0)

Referenced by audio_play_wasapi_help(), audio_play_wasapi_init(), audio_play_wasapi_probe(), and get_name().

◆ THROW_IF_FAILED

#define THROW_IF_FAILED ( cmd)
Value:
do { HRESULT hr = cmd; if (!SUCCEEDED(hr)) { ostringstream oss; oss << #cmd << ": " << hresult_to_str(hr); throw ug_runtime_error(oss.str()); } } while(0)

Definition at line 100 of file wasapi.cpp.

Referenced by audio_play_wasapi_help(), audio_play_wasapi_init(), and audio_play_wasapi_probe().

Function Documentation

◆ audio_format_to_waveformatex()

static WAVEFORMATEXTENSIBLE audio_format_to_waveformatex ( struct audio_desc * desc)
static

Definition at line 296 of file wasapi.cpp.

296 {
297 assert(desc->codec == AC_PCM);
298 WAVEFORMATEXTENSIBLE fmt;
300 fmt.dwChannelMask = get_channel_mask(&desc->ch_count);
301 fmt.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
302 fmt.Format.nChannels = desc->ch_count;
303 fmt.Format.wBitsPerSample = desc->bps * 8;
304 fmt.Format.nSamplesPerSec = desc->sample_rate;
305 fmt.Format.nBlockAlign = fmt.Format.nChannels * fmt.Format.wBitsPerSample / 8;
306 fmt.Format.nAvgBytesPerSec = fmt.Format.nSamplesPerSec * fmt.Format.nBlockAlign;
307 fmt.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); // at least 22 for extensible
308 fmt.Samples.wValidBitsPerSample = fmt.Format.wBitsPerSample;
309 return fmt;
310}
struct video_desc desc
const char * fmt
@ AC_PCM
Definition types.h:53
static DWORD get_channel_mask(int *count)
Definition wasapi.cpp:281
static const GUID UG_KSDATAFORMAT_SUBTYPE_PCM
Definition wasapi.cpp:76

References AC_PCM, desc, fmt, get_channel_mask(), and UG_KSDATAFORMAT_SUBTYPE_PCM.

Referenced by audio_play_wasapi_ctl(), and audio_play_wasapi_reconfigure().

Here is the call graph for this function:

◆ audio_play_wasapi_ctl()

static bool audio_play_wasapi_ctl ( void * state,
int request,
void * data,
size_t * len )
static

Definition at line 312 of file wasapi.cpp.

313{
314 auto s = static_cast<struct state_aplay_wasapi *>(state);
315 HRESULT hr;
316 WAVEFORMATEXTENSIBLE fmt;
317 WAVEFORMATEX *closestMatch;
318 switch (request) {
320 if (*len < sizeof(struct audio_desc)) {
321 return false;
322 }
323 struct audio_desc desc;
324 memcpy(&desc, data, sizeof desc);
325 desc.codec = AC_PCM;
326
328 hr = s->pAudioClient->IsFormatSupported(
329 AUDCLNT_SHAREMODE_SHARED,
330 (WAVEFORMATEX *) &fmt,
331 &closestMatch);
332 if (hr != S_OK && hr != S_FALSE) {
333 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Unable to get format: " << hresult_to_str(hr) << "\n";
334 return false;
335 }
336 if (hr == S_FALSE) {
337 desc.ch_count = closestMatch->nChannels;
338 desc.bps = closestMatch->wBitsPerSample / 8;
339 desc.sample_rate = closestMatch->nSamplesPerSec;
340 CoTaskMemFree(closestMatch);
341 }
342
343 memcpy(data, &desc, sizeof desc);
344 *len = sizeof desc;
345 return true;
346 default:
347 return false;
348 }
349}
void ** state
int void size_t * len
#define AUDIO_PLAYBACK_CTL_QUERY_FORMAT
static WAVEFORMATEXTENSIBLE audio_format_to_waveformatex(struct audio_desc *desc)
Definition wasapi.cpp:296

References AC_PCM, audio_format_to_waveformatex(), AUDIO_PLAYBACK_CTL_QUERY_FORMAT, desc, fmt, len, LOG, LOG_LEVEL_ERROR, MOD_NAME, and state.

Here is the call graph for this function:

◆ audio_play_wasapi_done()

static void audio_play_wasapi_done ( void * state)
static

Definition at line 275 of file wasapi.cpp.

276{
277 CoUninitialize();
278 delete static_cast<state_aplay_wasapi *>(state);
279}

References state.

◆ audio_play_wasapi_help()

static void audio_play_wasapi_help ( )
static

Definition at line 166 of file wasapi.cpp.

166 {
167 col() << "Usage:\n" <<
168 SBOLD(SRED("\t-r wasapi") << "[:<index>|:<ID>] --param audio-buffer-len=<ms>") << "\n" <<
169 "\nAvailable devices:\n";
170
171 bool com_initialized = false;
172 if (!com_initialize(&com_initialized, MOD_NAME)) {
173 return;
174 }
175 IMMDeviceEnumerator *enumerator = nullptr;
176 IMMDeviceCollection *pEndpoints = nullptr;
177
178 try {
179 THROW_IF_FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator,
180 (void **) &enumerator));
181
182 THROW_IF_FAILED(enumerator->EnumAudioEndpoints(eRender, DEVICE_STATEMASK_ALL, &pEndpoints));
183 string default_dev_id = wasapi_get_default_device_id(eRender, enumerator);
184 UINT count;
185 THROW_IF_FAILED(pEndpoints->GetCount(&count));
186 for (UINT i = 0; i < count; ++i) {
187 IMMDevice *pDevice = nullptr;
188 LPWSTR pwszID = NULL;
189 try {
190 THROW_IF_FAILED(pEndpoints->Item(i, &pDevice));
191 THROW_IF_FAILED(pDevice->GetId(&pwszID));
192 string dev_id = win_wstr_to_str(pwszID);
193 col() << (dev_id == default_dev_id ? "(*)" : "") << "\t" << SBOLD(i) << ") " << SBOLD(get_name(pDevice)) << " (ID: " << dev_id << ")\n";
194 } catch (ug_runtime_error &e) {
195 LOG(LOG_LEVEL_WARNING) << MOD_NAME << "Device " << i << ": " << e.what() << "\n";
196 }
197 SAFE_RELEASE(pDevice);
198 CoTaskMemFree(pwszID);
199 }
200 } catch (...) {
201 }
202 SAFE_RELEASE(enumerator);
203 SAFE_RELEASE(pEndpoints);
204 com_uninitialize(&com_initialized);
205}
#define SRED(x)
Definition color_out.h:85
#define SBOLD(x)
Definition color_out.h:80
u32 UINT
Definition cuda_dxt.cu:13
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
int count
Definition hd-rum.c:44
#define THROW_IF_FAILED(cmd)
Definition wasapi.cpp:100
#define SAFE_RELEASE(u)
Definition wasapi.cpp:97
const CLSID CLSID_MMDeviceEnumerator
Definition wasapi.cpp:68
string wasapi_get_default_device_id(EDataFlow dataFlow, IMMDeviceEnumerator *enumerator)
Definition wasapi.cpp:177
const IID IID_IMMDeviceEnumerator
Definition wasapi.cpp:69
static string get_name(IMMDevice *pDevice)
Definition wasapi.cpp:102
bool com_initialize(bool *com_initialized, const char *err_prefix)
Definition windows.c:65
void com_uninitialize(bool *com_initialized)
Definition windows.c:94

References CLSID_MMDeviceEnumerator, com_initialize(), com_uninitialize(), count, get_name(), IID_IMMDeviceEnumerator, LOG, LOG_LEVEL_WARNING, MOD_NAME, SAFE_RELEASE, SBOLD, SRED, THROW_IF_FAILED, and wasapi_get_default_device_id().

Referenced by audio_play_wasapi_init().

Here is the call graph for this function:

◆ audio_play_wasapi_init()

static void * audio_play_wasapi_init ( const char * cfg)
static

Definition at line 207 of file wasapi.cpp.

208{
209 wchar_t deviceID[1024] = L"";
210 int index = -1;
211 if (strlen(cfg) > 0) {
212 if (strcmp(cfg, "help") == 0) {
214 return INIT_NOERR;
215 }
216 if (isdigit(cfg[0])) {
217 index = atoi(cfg);
218 } else {
219 mbtowc(deviceID, cfg, (sizeof deviceID / 2) - 1);
220 }
221 }
222 auto s = new state_aplay_wasapi();
223 if (!com_initialize(&s->com_initialized, MOD_NAME)) {
224 delete s;
225 return nullptr;
226 }
227 IMMDeviceEnumerator *enumerator = nullptr;
228 try {
229
230 THROW_IF_FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator,
231 (void **) &enumerator));
232 if (wcslen(deviceID) > 0) {
233 THROW_IF_FAILED(enumerator->GetDevice(deviceID, &s->pDevice));
234 } else if (index != -1) {
235 IMMDeviceCollection *pEndpoints = nullptr;
236 try {
237 THROW_IF_FAILED(enumerator->EnumAudioEndpoints(eRender, DEVICE_STATEMASK_ALL, &pEndpoints));
238 UINT count;
239 THROW_IF_FAILED(pEndpoints->GetCount(&count));
240 for (UINT i = 0; i < count; ++i) {
241 if (i == (UINT) index) {
242 THROW_IF_FAILED(pEndpoints->Item(i, &s->pDevice));
243 break;
244 }
245 }
246 } catch (ug_runtime_error &e) { // just continue with the next
247 LOG(LOG_LEVEL_WARNING) << MOD_NAME << e.what() << "\n";
248 }
249 SAFE_RELEASE(pEndpoints);
250 } else { // default device
251 THROW_IF_FAILED(enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &s->pDevice));
252 }
253 if (!s->pDevice) {
254 throw ug_runtime_error("Device not found!");
255 }
256 THROW_IF_FAILED(s->pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL,
257 (void **)&s->pAudioClient));
258
259 auto friendlyName = get_name(s->pDevice);
260 if (!friendlyName.empty()) {
261 LOG(LOG_LEVEL_NOTICE) << MOD_NAME << "Using device: "
262 << friendlyName << "\n";
263 }
264 } catch (ug_runtime_error &e) {
265 LOG(LOG_LEVEL_ERROR) << MOD_NAME << e.what() << "\n";
266 com_uninitialize(&s->com_initialized);
267 delete s;
268 s = nullptr;
269 }
270 // print friendly name
271 SAFE_RELEASE(enumerator);
272 return s;
273}
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define INIT_NOERR
Definition host.h:73
const IID IID_IAudioClient
Definition wasapi.cpp:70
static void audio_play_wasapi_help()
Definition wasapi.cpp:166

References audio_play_wasapi_help(), CLSID_MMDeviceEnumerator, com_initialize(), com_uninitialize(), count, get_name(), IID_IAudioClient, IID_IMMDeviceEnumerator, INIT_NOERR, LOG, LOG_LEVEL_ERROR, LOG_LEVEL_NOTICE, LOG_LEVEL_WARNING, MOD_NAME, SAFE_RELEASE, and THROW_IF_FAILED.

Here is the call graph for this function:

◆ audio_play_wasapi_probe()

static void audio_play_wasapi_probe ( struct device_info ** available_devices,
int * dev_count,
void(** deleter )(void *) )
static

<

Todo
This may be rather id than index

Definition at line 122 of file wasapi.cpp.

123{
124 *deleter = free;
125 *available_devices = (struct device_info *) malloc(0);
126 *dev_count = 0;
127
128 IMMDeviceEnumerator *enumerator = nullptr;
129 IMMDeviceCollection *pEndpoints = nullptr;
130 bool com_initialized = false;
131 if (!com_initialize(&com_initialized, MOD_NAME)) {
132 return;
133 }
134
135 try {
136 THROW_IF_FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator,
137 (void **) &enumerator));
138
139 THROW_IF_FAILED(enumerator->EnumAudioEndpoints(eRender, DEVICE_STATEMASK_ALL, &pEndpoints));
140 UINT count;
141 THROW_IF_FAILED(pEndpoints->GetCount(&count));
142 for (UINT i = 0; i < count; ++i) {
143 IMMDevice *pDevice = nullptr;
144 LPWSTR pwszID = NULL;
145 try {
146 THROW_IF_FAILED(pEndpoints->Item(i, &pDevice));
147 THROW_IF_FAILED(pDevice->GetId(&pwszID));
148 *available_devices = (struct device_info *) realloc(*available_devices, (*dev_count + 1) * sizeof(struct device_info));
149 memset(&(*available_devices)[*dev_count], 0, sizeof(struct device_info));
150 snprintf((*available_devices)[*dev_count].dev, sizeof (*available_devices)[*dev_count].dev, ":%u", i);
151 snprintf((*available_devices)[*dev_count].name, sizeof (*available_devices)[*dev_count].name, "WASAPI %s", get_name(pDevice).c_str());
152 ++*dev_count;
153 } catch (ug_runtime_error &e) {
154 LOG(LOG_LEVEL_WARNING) << MOD_NAME << "Device " << i << ": " << e.what() << "\n";
155 }
156 SAFE_RELEASE(pDevice);
157 CoTaskMemFree(pwszID);
158 }
159 } catch (...) {
160 }
161 SAFE_RELEASE(enumerator);
162 SAFE_RELEASE(pEndpoints);
163 com_uninitialize(&com_initialized);
164}
int void(** deleter)(void *))
const char * name
Definition settings.cpp:193
char dev[1024]
Definition types.h:383

References CLSID_MMDeviceEnumerator, com_initialize(), com_uninitialize(), count, deleter, device_info::dev, get_name(), IID_IMMDeviceEnumerator, LOG, LOG_LEVEL_WARNING, MOD_NAME, name, SAFE_RELEASE, and THROW_IF_FAILED.

Here is the call graph for this function:

◆ audio_play_wasapi_put_frame()

static void audio_play_wasapi_put_frame ( void * state,
const struct audio_frame * buffer )
static

Definition at line 375 of file wasapi.cpp.

376{
377 auto s = static_cast<struct state_aplay_wasapi *>(state);
378 UINT32 numFramesPadding;
379
380 CHECK(s->pAudioClient->GetCurrentPadding(&numFramesPadding));
381
382 UINT32 NumFramesRequested = buffer->data_len / buffer->ch_count / buffer->bps;
383 if (s->bufferSize - numFramesPadding < NumFramesRequested) {
384 LOG(LOG_LEVEL_WARNING) << MOD_NAME "Buffer overflow!\n";
385 NumFramesRequested = s->bufferSize - numFramesPadding;
386 }
387 BYTE *data;
388 CHECK(s->pRenderClient->GetBuffer(NumFramesRequested, &data));
389 memcpy(data, buffer->data, NumFramesRequested * buffer->ch_count * buffer->bps);
390 CHECK(s->pRenderClient->ReleaseBuffer(NumFramesRequested, 0));
391
392}
unsigned char BYTE
Definition crypt_aes.h:71
#define CHECK(cmd)
Definition wasapi.cpp:374
char * data
Definition types.h:102
int ch_count
Definition types.h:104
int data_len
Definition types.h:103
int bps
Definition types.h:100

References audio_frame::bps, audio_frame::ch_count, CHECK, audio_frame::data, audio_frame::data_len, LOG, LOG_LEVEL_WARNING, MOD_NAME, and state.

◆ audio_play_wasapi_reconfigure()

static bool audio_play_wasapi_reconfigure ( void * state,
struct audio_desc desc )
static

Definition at line 352 of file wasapi.cpp.

353{
354 auto s = static_cast<struct state_aplay_wasapi *>(state);
355 int buflen_ms = DEFAULT_WASAPI_BUFLEN_MS;
356 if (get_commandline_param("audio-buffer-len") != nullptr) {
357 buflen_ms = atoi(get_commandline_param("audio-buffer-len"));
358 assert(buflen_ms > 0);
359 }
360 REFERENCE_TIME bufferDuration = buflen_ms * REFTIMES_PER_MILLISEC;
361 WAVEFORMATEXTENSIBLE fmt = audio_format_to_waveformatex(&desc);
362 FAIL_IF_NOT(s->pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, bufferDuration, 0,
363 (WAVEFORMATEX *) &fmt, NULL));
364 FAIL_IF_NOT(s->pAudioClient->GetService(IID_IAudioRenderClient, (void **) &s->pRenderClient));
365
366 FAIL_IF_NOT(s->pAudioClient->GetBufferSize(&s->bufferSize));
367 LOG(LOG_LEVEL_INFO) << MOD_NAME "Buffer size: " << s->bufferSize << " frames\n";
368
369 FAIL_IF_NOT(s->pAudioClient->Start());
370
371 return true;
372}
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
const char * get_commandline_param(const char *key)
Definition host.cpp:894
#define DEFAULT_WASAPI_BUFLEN_MS
Definition wasapi.cpp:63
const IID IID_IAudioRenderClient
Definition wasapi.cpp:71
#define FAIL_IF_NOT(cmd)
Definition wasapi.cpp:351
#define REFTIMES_PER_MILLISEC
Definition wasapi.cpp:66

References audio_format_to_waveformatex(), DEFAULT_WASAPI_BUFLEN_MS, desc, FAIL_IF_NOT, fmt, get_commandline_param(), IID_IAudioRenderClient, LOG, LOG_LEVEL_INFO, MOD_NAME, REFTIMES_PER_MILLISEC, and state.

Here is the call graph for this function:

◆ get_channel_mask()

static DWORD get_channel_mask ( int * count)
static

Definition at line 281 of file wasapi.cpp.

281 {
282 assert(*count > 0);
283 switch (*count) {
284 case 1: return KSAUDIO_SPEAKER_MONO;
285 case 2: return KSAUDIO_SPEAKER_STEREO;
286 case 3: *count = 4; return KSAUDIO_SPEAKER_SURROUND;
287 case 4: return KSAUDIO_SPEAKER_QUAD; // or SURROUND
288 case 5: *count = 6; return KSAUDIO_SPEAKER_5POINT1_SURROUND;
289 case 6: return KSAUDIO_SPEAKER_5POINT1; // ditto
290 case 7: *count = 7; return KSAUDIO_SPEAKER_5POINT1_SURROUND;
291 case 8: return KSAUDIO_SPEAKER_7POINT1; // ditto
292 default: *count = 8; return KSAUDIO_SPEAKER_7POINT1;
293 }
294}

References count.

Referenced by audio_format_to_waveformatex().

◆ get_name()

static string get_name ( IMMDevice * pDevice)
static

Definition at line 102 of file wasapi.cpp.

102 {
103 wstring out;
104 IPropertyStore *pProps = NULL;
105 PROPVARIANT varName;
106 LPWSTR pwszID = NULL;
107 // Initialize container for property value.
108 PropVariantInit(&varName);
109 HRESULT hr = pDevice->OpenPropertyStore(STGM_READ, &pProps);
110 if (!FAILED(hr)) {
111 hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName);
112 if (!FAILED(hr)) {
113 out = varName.pwszVal;
114 }
115 }
116 SAFE_RELEASE(pProps);
117 CoTaskMemFree(pwszID);
118 PropVariantClear(&varName);
119 return win_wstr_to_str(out.c_str());
120}
static const PROPERTYKEY PKEY_Device_FriendlyName
Definition wasapi.cpp:73
@ FAILED

References FAILED, PKEY_Device_FriendlyName, and SAFE_RELEASE.

Referenced by audio_play_wasapi_help(), audio_play_wasapi_init(), and audio_play_wasapi_probe().

◆ REGISTER_MODULE()

REGISTER_MODULE ( wasapi ,
& aplay_wasapi_info,
LIBRARY_CLASS_AUDIO_PLAYBACK ,
AUDIO_PLAYBACK_ABI_VERSION  )

◆ wasapi_get_default_device_id()

string wasapi_get_default_device_id ( EDataFlow dataFlow,
IMMDeviceEnumerator * enumerator )

Definition at line 177 of file wasapi.cpp.

177 {
178 IMMDevice *pDevice = nullptr;
179 if (!SUCCEEDED(enumerator->GetDefaultAudioEndpoint(dataFlow, eConsole, &pDevice))) {
180 return {};
181 }
182 LPWSTR pwszID = nullptr;
183 if (!SUCCEEDED(pDevice->GetId(&pwszID))) {
184 SAFE_RELEASE(pDevice);
185 return {};
186 }
187 string ret = win_wstr_to_str(pwszID);
188 SAFE_RELEASE(pDevice);
189
190 return ret;
191}
#define SAFE_RELEASE(u)
Definition wasapi.cpp:100

References SAFE_RELEASE.

Referenced by audio_play_wasapi_help(), and show_help().

Variable Documentation

◆ aplay_wasapi_info

const struct audio_playback_info aplay_wasapi_info
static
Initial value:
= {
}
static void * audio_play_wasapi_init(const char *cfg)
Definition wasapi.cpp:207
static void audio_play_wasapi_done(void *state)
Definition wasapi.cpp:275
static bool audio_play_wasapi_reconfigure(void *state, struct audio_desc desc)
Definition wasapi.cpp:352
static void audio_play_wasapi_put_frame(void *state, const struct audio_frame *buffer)
Definition wasapi.cpp:375
static void audio_play_wasapi_probe(struct device_info **available_devices, int *dev_count, void(**deleter)(void *))
Definition wasapi.cpp:122
static bool audio_play_wasapi_ctl(void *state, int request, void *data, size_t *len)
Definition wasapi.cpp:312

Definition at line 394 of file wasapi.cpp.

◆ CLSID_MMDeviceEnumerator

const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator)

◆ IDevice_FriendlyName

const GUID IDevice_FriendlyName = { 0xa45c254e, 0xdf1c, 0x4efd, { 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0 } }
static

Definition at line 72 of file wasapi.cpp.

72{ 0xa45c254e, 0xdf1c, 0x4efd, { 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0 } };

◆ IID_IAudioClient

const IID IID_IAudioClient = __uuidof(IAudioClient)

Definition at line 70 of file wasapi.cpp.

Referenced by audio_cap_wasapi_init(), and audio_play_wasapi_init().

◆ IID_IAudioRenderClient

const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient)

Definition at line 71 of file wasapi.cpp.

Referenced by audio_play_wasapi_reconfigure().

◆ IID_IMMDeviceEnumerator

const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator)

◆ PKEY_Device_FriendlyName

const PROPERTYKEY PKEY_Device_FriendlyName = { IDevice_FriendlyName, 14 }
static

Definition at line 73 of file wasapi.cpp.

static const GUID IDevice_FriendlyName
Definition wasapi.cpp:72

Referenced by get_name().

◆ UG_KSDATAFORMAT_SUBTYPE_PCM

const GUID UG_KSDATAFORMAT_SUBTYPE_PCM = { STATIC_KSDATAFORMAT_SUBTYPE_PCM }
static

Definition at line 76 of file wasapi.cpp.

76{ STATIC_KSDATAFORMAT_SUBTYPE_PCM };

Referenced by audio_format_to_waveformatex().