UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
coreaudio.cpp File Reference
#include "config_unix.h"
#include "config_win32.h"
#include <AudioUnit/AudioUnit.h>
#include <Availability.h>
#include <chrono>
#include <cinttypes>
#include <climits>
#include <CoreAudio/AudioHardware.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <string.h>
#include "audio/audio_playback.h"
#include "audio/playback/coreaudio.h"
#include "audio/types.h"
#include "debug.h"
#include "lib_common.h"
#include "utils/audio_buffer.h"
#include "utils/color_out.h"
#include "utils/macos.h"
#include "utils/ring_buffer.h"
Include dependency graph for coreaudio.cpp:

Go to the source code of this file.

Classes

struct  state_ca_playback
 

Macros

#define MOD_NAME   "[CoreAudio play.] "
 
#define NO_DATA_STOP_SEC   2
 

Functions

 ADD_TO_PARAM ("ca-disable-adaptive-buf", "* ca-disable-adaptive-buf\n" " Core Audio - use fixed audio playback buffer instead of an adaptive one\n")
 
AudioDeviceID audio_ca_get_device_by_name (const char *name, int dir)
 
void audio_ca_get_device_name (AudioDeviceID dev_id, size_t namebuf_len, char *namebuf)
 
void audio_ca_probe (struct device_info **available_devices, int *count, int dir)
 
static bool audio_play_ca_ctl (void *state, int request, void *data, size_t *len)
 
static void audio_play_ca_done (void *state)
 
static void audio_play_ca_help ()
 
static void * audio_play_ca_init (const char *cfg)
 
static void audio_play_ca_probe (struct device_info **available_devices, int *count, void(**deleter)(void *))
 
static void audio_play_ca_put_frame (void *state, const struct audio_frame *frame)
 
static bool audio_play_ca_reconfigure (void *state, struct audio_desc desc)
 
static bool is_requested_direction (AudioObjectPropertyAddress propertyAddress, AudioDeviceID *audioDevice)
 
 REGISTER_MODULE (coreaudio, &aplay_coreaudio_info, LIBRARY_CLASS_AUDIO_PLAYBACK, AUDIO_PLAYBACK_ABI_VERSION)
 
static OSStatus theRenderProc (void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData)
 

Variables

static const struct audio_playback_info aplay_coreaudio_info
 
constexpr int CA_DIR = 1
 
constexpr int DEFAULT_BUFLEN_MS = 50
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z
Todo
Remove deprecated instances of ca-disable-adaptive-buf after some transitio period.

Definition in file coreaudio.cpp.

Macro Definition Documentation

◆ MOD_NAME

#define MOD_NAME   "[CoreAudio play.] "

◆ NO_DATA_STOP_SEC

#define NO_DATA_STOP_SEC   2

Definition at line 76 of file coreaudio.cpp.

Referenced by theRenderProc().

Function Documentation

◆ ADD_TO_PARAM()

ADD_TO_PARAM ( "ca-disable-adaptive-buf" ,
"* ca-disable-adaptive-buf\n" " Core Audio - use fixed audio playback buffer instead of an adaptive one\n"  )

◆ audio_ca_get_device_by_name()

AudioDeviceID audio_ca_get_device_by_name ( const char * name,
int dir )

@briew tries to get device id from device name

Parameters
namename of the device to be looked up
dirdirection -
See also
audio_ca_probe for values; dir is needed only for deafult device names

Definition at line 369 of file coreaudio.cpp.

370{
371 struct device_info *devices = NULL;
372 int count = 0;
373 audio_ca_probe(&devices, &count, dir);
374 for (int i = 0; i < count; ++i) {
375 if (strstr(devices[i].name, name) != NULL) {
376 return atoi(devices[i].dev + 1);
377 }
378 }
379 return UINT_MAX;
380}
void audio_ca_probe(struct device_info **available_devices, int *count, int dir)
int count
Definition hd-rum.c:44
const char * name
Definition settings.cpp:193
char dev[1024]
Definition types.h:383

References audio_ca_probe(), count, device_info::dev, and name.

Referenced by audio_cap_ca_init(), and audio_play_ca_init().

Here is the call graph for this function:

◆ audio_ca_get_device_name()

void audio_ca_get_device_name ( AudioDeviceID dev_id,
size_t namebuf_len,
char * namebuf )

Definition at line 281 of file coreaudio.cpp.

282{
283 AudioObjectPropertyAddress propertyAddress{};
284 propertyAddress.mSelector = kAudioHardwarePropertyDevices;
285 propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
286 propertyAddress.mElement = kAudioObjectPropertyElementMain;
287 propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
288 CFStringRef deviceName = NULL;
289 UInt32 size = sizeof(deviceName);
290 if (OSStatus ret = AudioObjectGetPropertyData(dev_id, &propertyAddress, 0, NULL, &size, &deviceName)) {
291 log_msg(LOG_LEVEL_WARNING, "[CoreAudio] Cannot get device %" PRIu32 " name: %s\n",
292 dev_id, get_osstatus_str(ret));
293 snprintf(namebuf, namebuf_len, "CoreAudio device #%" PRIu32 " (unable to get name)", dev_id);
294 return;
295 }
296 CFStringGetCString(deviceName, namebuf, namebuf_len, kCFStringEncodingMacRoman);
297 CFRelease(deviceName);
298}
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define kAudioObjectPropertyElementMain
Definition macos.h:50
const char * get_osstatus_str(OSStatus err)
Definition macos.m:106

References get_osstatus_str(), kAudioObjectPropertyElementMain, LOG_LEVEL_WARNING, and log_msg().

Referenced by audio_ca_probe(), audio_cap_ca_init(), and audio_play_ca_init().

Here is the call graph for this function:

◆ audio_ca_probe()

void audio_ca_probe ( struct device_info ** available_devices,
int * count,
int dir )

@briew probe for available capture/playback devices (direction given by parameter dir)

Parameters
dir-1 capture, 1 playback

Definition at line 305 of file coreaudio.cpp.

306{
307 assert(dir == -1 || dir == 1);
308 *available_devices =
309 (struct device_info *) calloc(1, sizeof(struct device_info));
310 snprintf((*available_devices)[0].dev, sizeof(*available_devices)[0].dev,
311 "");
312 snprintf((*available_devices)[0].name,
313 sizeof(*available_devices)[0].name, "Default CoreAudio %s",
314 dir == -1 ? "capture" : "playback");
315 *count = 1;
316
317 int dev_count;
318 AudioDeviceID *dev_ids;
319 OSStatus ret;
320 UInt32 size;
321 AudioObjectPropertyAddress propertyAddress;
322
323 propertyAddress.mSelector = kAudioHardwarePropertyDevices;
324 propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
325 propertyAddress.mElement = kAudioObjectPropertyElementMain;
326 ret = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size);
327 if (ret) {
328 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot get device list size: %s\n", get_osstatus_str(ret));
329 goto error;
330 }
331 dev_ids = (AudioDeviceID *) malloc(size);
332 dev_count = size / sizeof(AudioDeviceID);
333 ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size, dev_ids);
334 if (ret) {
335 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot get device list: %s\n", get_osstatus_str(ret));
336 goto error;
337 }
338
339 propertyAddress.mScope = dir == -1 ? kAudioObjectPropertyScopeInput : kAudioObjectPropertyScopeOutput;
340 for (int i = 0; i < dev_count; ++i) {
341 if (dir != 0 && !is_requested_direction(propertyAddress, &dev_ids[i])) {
342 continue;
343 }
344
345 (*count)++;
346 *available_devices = (struct device_info *) realloc(*available_devices, *count * sizeof(struct device_info));
347 memset(&(*available_devices)[*count - 1], 0, sizeof(struct device_info));
348
349 audio_ca_get_device_name(dev_ids[i], sizeof (*available_devices)[*count - 1].name,
350 (char *) (*available_devices)[*count - 1].name);
351 snprintf((*available_devices)[*count - 1].dev, sizeof (*available_devices)[*count - 1].dev,
352 ":%" PRIu32, dev_ids[i]);
353 }
354 free(dev_ids);
355
356 return;
357
358error:
359 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Error obtaining device list.\n";
360}
void audio_ca_get_device_name(AudioDeviceID dev_id, size_t namebuf_len, char *namebuf)
#define MOD_NAME
Definition coreaudio.cpp:77
static bool is_requested_direction(AudioObjectPropertyAddress propertyAddress, AudioDeviceID *audioDevice)
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG(level)
Definition debug.h:313

References audio_ca_get_device_name(), count, device_info::dev, get_osstatus_str(), is_requested_direction(), kAudioObjectPropertyElementMain, LOG, LOG_LEVEL_ERROR, log_msg(), MOD_NAME, and name.

Referenced by audio_ca_get_device_by_name(), audio_cap_ca_probe(), and audio_play_ca_probe().

Here is the call graph for this function:

◆ audio_play_ca_ctl()

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

Definition at line 133 of file coreaudio.cpp.

134{
135 switch (request) {
137 if (*len >= sizeof(struct audio_desc)) {
138 struct audio_desc desc;
139 memcpy(&desc, data, sizeof desc);
140 desc.codec = AC_PCM;
141 memcpy(data, &desc, sizeof desc);
142 *len = sizeof desc;
143 return true;
144 } else{
145 return false;
146 }
147 default:
148 return false;
149 }
150}
struct video_desc desc
int void size_t * len
@ AC_PCM
Definition types.h:53
#define AUDIO_PLAYBACK_CTL_QUERY_FORMAT

References AC_PCM, AUDIO_PLAYBACK_CTL_QUERY_FORMAT, desc, and len.

◆ audio_play_ca_done()

static void audio_play_ca_done ( void * state)
static

Definition at line 524 of file coreaudio.cpp.

525{
526 struct state_ca_playback *s = (struct state_ca_playback *)state;
527
528 if (s->initialized) {
529 AudioOutputUnitStop(s->auHALComponentInstance);
530 AudioUnitUninitialize(s->auHALComponentInstance);
531 }
532 if (s->buffer_fns) {
533 s->buffer_fns->destroy(s->buffer);
534 }
535 delete s;
536}
void ** state
void(* destroy)(void *buf)
AudioComponentInstance auHALComponentInstance
Definition coreaudio.cpp:80
struct audio_buffer_api * buffer_fns
Definition coreaudio.cpp:83

References state_ca_playback::auHALComponentInstance, state_ca_playback::buffer, state_ca_playback::buffer_fns, audio_buffer_api::destroy, state_ca_playback::initialized, and state.

◆ audio_play_ca_help()

static void audio_play_ca_help ( )
static

Definition at line 388 of file coreaudio.cpp.

389{
390 cout << "Core Audio playback usage:\n";
391 col() << SBOLD(SRED("\t-r coreaudio") << "[:<index>|:<name>] "
392 "[--param audio-buffer-len=<len_ms>] [--param audio-disable-adaptive-buffer]") << "\n";
393 col() << "where\n\t" << SBOLD("<name>") << " - device name substring (case sensitive)\n\n";
394 printf("Available CoreAudio playback devices:\n");
395 struct device_info *available_devices;
396 int count;
397 void (*deleter)(void *);
398 audio_play_ca_probe(&available_devices, &count, &deleter);
399
400 for (int i = 0; i < count; ++i) {
401 color_printf("\t" TBOLD("coreaudio%-4s") ": %s\n", available_devices[i].dev, available_devices[i].name);
402 }
403 deleter ? deleter(available_devices) : free(available_devices);
404}
int void(** deleter)(void *))
int color_printf(const char *format,...)
#define SRED(x)
Definition color_out.h:85
#define SBOLD(x)
Definition color_out.h:80
#define TBOLD(x)
Definition color_out.h:70
static void audio_play_ca_probe(struct device_info **available_devices, int *count, void(**deleter)(void *))

References audio_play_ca_probe(), color_printf(), count, deleter, device_info::dev, name, SBOLD, SRED, and TBOLD.

Referenced by audio_play_ca_init().

Here is the call graph for this function:

◆ audio_play_ca_init()

static void * audio_play_ca_init ( const char * cfg)
static

Definition at line 407 of file coreaudio.cpp.

408{
409 OSStatus ret = noErr;
410 AudioComponent comp;
411 AudioComponentDescription comp_desc;
412 AudioDeviceID device;
413
414 struct state_ca_playback *s = new struct state_ca_playback();
415
416 if (const char *val = get_commandline_param("audio-buffer-len")) {
417 s->buf_len_ms = atoi(val);
418 if (s->buf_len_ms <= 0 || s->buf_len_ms >= 10000) {
419 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Wrong value \"" << val << "\" given to \"audio-buffer-len\", allowed range (0, 10000).\n";
420 goto error;
421 }
422 }
423
424 //There are several different types of Audio Units.
425 //Some audio units serve as Outputs, Mixers, or DSP
426 //units. See AUComponent.h for listing
427 comp_desc.componentType = kAudioUnitType_Output;
428
429 //Every Component has a subType, which will give a clearer picture
430 //of what this components function will be.
431 //comp_desc.componentSubType = kAudioUnitSubType_DefaultOutput;
432 comp_desc.componentSubType = kAudioUnitSubType_HALOutput;
433
434 //all Audio Units in AUComponent.h must use
435 //"kAudioUnitManufacturer_Apple" as the Manufacturer
436 comp_desc.componentManufacturer = kAudioUnitManufacturer_Apple;
437 comp_desc.componentFlags = 0;
438 comp_desc.componentFlagsMask = 0;
439
440 comp = AudioComponentFindNext(NULL, &comp_desc);
441 if (!comp) {
442 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot find audio component!\n");
443 goto error;
444 }
445 ret = AudioComponentInstanceNew(comp, &s->auHALComponentInstance);
446 if (ret != noErr) {
447 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot open audio component: %s\n", get_osstatus_str(ret));
448 goto error;
449 }
450
451 s->buffer = NULL;
452
453 if ((ret = AudioUnitUninitialize(s->auHALComponentInstance)) != noErr) {
454 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot initialize audio unit: %s\n", get_osstatus_str(ret));
455 goto error;
456 }
457
458 if (strcmp(cfg, "help") == 0) {
460 delete s;
461 return INIT_NOERR;
462 }
463 if (strlen(cfg) > 0) {
464 try {
465 device = stoi(cfg);
466 } catch (std::invalid_argument &e) {
467 device = audio_ca_get_device_by_name(cfg, CA_DIR);
468 if (device == UINT_MAX) {
471 "Wrong device index "
472 "or unrecognized name \"%s\"!\n",
473 cfg);
474 goto error;
475 }
476 }
477 } else {
478 AudioObjectPropertyAddress propertyAddress;
479 UInt32 size = sizeof device;
480 propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
481 propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
482 propertyAddress.mElement = kAudioObjectPropertyElementMain;
483 if ((ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &size, &device)) != noErr) {
484 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot get default audio device: %s\n", get_osstatus_str(ret));
485 goto error;
486 }
487 }
488 char device_name[128];
489 audio_ca_get_device_name(device, sizeof device_name, device_name);
490 log_msg(LOG_LEVEL_INFO, MOD_NAME "Using device: %s\n", device_name);
491
492 if (get_commandline_param("ca-disable-adaptive-buf") == nullptr &&
493 get_commandline_param("audio-disable-adaptive-buffer") == nullptr) {
494 LOG(LOG_LEVEL_WARNING) << MOD_NAME "Using adaptive buffer. "
495 "In case of problems, try \"--param audio-disable-adaptive-buffer\" "
496 "option.\n";
497 }
498
499 ret = AudioUnitSetProperty(s->auHALComponentInstance,
500 kAudioOutputUnitProperty_CurrentDevice,
501 kAudioUnitScope_Global,
502 1,
503 &device,
504 sizeof(device));
505 if (ret) {
506 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot set audio properties: %s\n", get_osstatus_str(ret));
507 goto error;
508 }
509
510 return s;
511
512error:
513 delete s;
514 return NULL;
515}
int void * val
constexpr int CA_DIR
Definition coreaudio.cpp:75
AudioDeviceID audio_ca_get_device_by_name(const char *name, int dir)
static void audio_play_ca_help()
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
const char * get_commandline_param(const char *key)
Definition host.cpp:894
#define INIT_NOERR
Definition host.h:73

References audio_ca_get_device_by_name(), audio_ca_get_device_name(), audio_play_ca_help(), state_ca_playback::auHALComponentInstance, state_ca_playback::buf_len_ms, state_ca_playback::buffer, CA_DIR, get_commandline_param(), get_osstatus_str(), INIT_NOERR, kAudioObjectPropertyElementMain, LOG, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, and val.

Here is the call graph for this function:

◆ audio_play_ca_probe()

static void audio_play_ca_probe ( struct device_info ** available_devices,
int * count,
void(** deleter )(void *) )
static

Definition at line 382 of file coreaudio.cpp.

383{
384 *deleter = free;
385 audio_ca_probe(available_devices, count, 1);
386}

References audio_ca_probe(), count, and deleter.

Referenced by audio_play_ca_help().

Here is the call graph for this function:

◆ audio_play_ca_put_frame()

static void audio_play_ca_put_frame ( void * state,
const struct audio_frame * frame )
static

Definition at line 517 of file coreaudio.cpp.

518{
519 struct state_ca_playback *s = (struct state_ca_playback *)state;
520
521 s->buffer_fns->write(s->buffer, frame->data, frame->data_len);
522}
struct video_frame * frame
void(* write)(void *buf, const char *in, int len)

References state_ca_playback::buffer, state_ca_playback::buffer_fns, frame, state, and audio_buffer_api::write.

◆ audio_play_ca_reconfigure()

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

Definition at line 154 of file coreaudio.cpp.

155{
156 struct state_ca_playback *s = (struct state_ca_playback *)state;
157 AudioStreamBasicDescription stream_desc;
158 UInt32 size;
159 OSStatus ret = noErr;
160 AURenderCallbackStruct renderStruct;
161
162 LOG(LOG_LEVEL_NOTICE) << MOD_NAME "Audio reinitialized to " << desc.bps * 8 << "-bit, " << desc.ch_count << " channels, " << desc.sample_rate << " Hz\n";
163
164 if (s->initialized) {
165 ret = AudioOutputUnitStop(s->auHALComponentInstance);
166 if(ret) {
167 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Cannot stop AUHAL instance: " << get_osstatus_str(ret) << ".\n";
168 goto error;
169 }
170
171 ret = AudioUnitUninitialize(s->auHALComponentInstance);
172 if(ret) {
173 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Cannot uninitialize AUHAL instance: " << get_osstatus_str(ret) << ".\n";
174 goto error;
175 }
176 s->initialized = false;
177 }
178
179 s->desc = desc;
180
181 if (s->buffer_fns) {
182 s->buffer_fns->destroy(s->buffer);
183 s->buffer_fns = nullptr;
184 s->buffer = nullptr;
185 }
186
187 {
188 if (get_commandline_param("audio-disable-adaptive-buffer") != nullptr || get_commandline_param("ca-disable-adaptive-buf") != nullptr) {
189 if (get_commandline_param("ca-disable-adaptive-buf") != nullptr) {
190 LOG(LOG_LEVEL_WARNING) << MOD_NAME "Param \"ca-disable-adaptive-buf\" is deprecated, use audio-disable-adaptive-bufer instead.\n";
191 }
192 int buf_len = desc.bps * desc.ch_count * (desc.sample_rate * s->buf_len_ms / 1000);
193 s->buffer = ring_buffer_init(buf_len);
195 } else {
196 s->buffer = audio_buffer_init(desc.sample_rate, desc.bps, desc.ch_count, s->buf_len_ms);
198 }
199 }
200
201 size = sizeof(stream_desc);
202 ret = AudioUnitGetProperty(s->auHALComponentInstance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
203 0, &stream_desc, &size);
204 if(ret) {
205 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Cannot get device format from AUHAL instance: " << get_osstatus_str(ret) << ".\n";
206 goto error;
207 }
208 stream_desc.mSampleRate = desc.sample_rate;
209 stream_desc.mFormatID = kAudioFormatLinearPCM;
210 stream_desc.mChannelsPerFrame = desc.ch_count;
211 stream_desc.mBitsPerChannel = desc.bps * 8;
212 stream_desc.mFormatFlags = kAudioFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked;
213 stream_desc.mFramesPerPacket = 1;
214 s->audio_packet_size = stream_desc.mBytesPerFrame = stream_desc.mBytesPerPacket = stream_desc.mFramesPerPacket * desc.ch_count * desc.bps;
215
216 ret = AudioUnitSetProperty(s->auHALComponentInstance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
217 0, &stream_desc, sizeof(stream_desc));
218 if(ret) {
219 LOG(LOG_LEVEL_ERROR) << "Cannot set device format to AUHAL instance: " << get_osstatus_str(ret) << ".\n";
220 goto error;
221 }
222
223 renderStruct.inputProc = theRenderProc;
224 renderStruct.inputProcRefCon = s;
225 ret = AudioUnitSetProperty(s->auHALComponentInstance, kAudioUnitProperty_SetRenderCallback,
226 kAudioUnitScope_Input, 0, &renderStruct, sizeof(AURenderCallbackStruct));
227 if(ret) {
228 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Cannot register audio processing callback: " << get_osstatus_str(ret) << ".\n";
229 goto error;
230 }
231
232 ret = AudioUnitInitialize(s->auHALComponentInstance);
233 if(ret) {
234 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Cannot initialize AUHAL: " << get_osstatus_str(ret) << ".\n";
235 goto error;
236 }
237
238 ret = AudioOutputUnitStart(s->auHALComponentInstance);
239 if(ret) {
240 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Cannot start AUHAL: " << get_osstatus_str(ret) << ".\n";
241 goto error;
242 }
243
244 s->initialized = true;
245
246 return true;
247
248error:
249 return false;
250}
struct audio_buffer_api audio_buffer_fns
struct audio_buffer * audio_buffer_init(int sample_rate, int bps, int ch_count, int suggested_latency_ms)
static OSStatus theRenderProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData)
Definition coreaudio.cpp:97
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
struct audio_buffer_api ring_buffer_fns
struct ring_buffer * ring_buffer_init(int size)
struct audio_desc desc
Definition coreaudio.cpp:81

References audio_buffer_fns, audio_buffer_init(), state_ca_playback::audio_packet_size, state_ca_playback::auHALComponentInstance, state_ca_playback::buf_len_ms, state_ca_playback::buffer, state_ca_playback::buffer_fns, desc, state_ca_playback::desc, audio_buffer_api::destroy, get_commandline_param(), get_osstatus_str(), state_ca_playback::initialized, LOG, LOG_LEVEL_ERROR, LOG_LEVEL_NOTICE, LOG_LEVEL_WARNING, MOD_NAME, ring_buffer_fns, ring_buffer_init(), state, and theRenderProc().

Here is the call graph for this function:

◆ is_requested_direction()

static bool is_requested_direction ( AudioObjectPropertyAddress propertyAddress,
AudioDeviceID * audioDevice )
static

Definition at line 254 of file coreaudio.cpp.

254 {
255 // Determine if the device is an input/output device (it is an input/output device if it has input/output channels)
256 UInt32 size = 0;
257 OSStatus status;
258 propertyAddress.mSelector = kAudioDevicePropertyStreamConfiguration;
259 status = AudioObjectGetPropertyDataSize(*audioDevice, &propertyAddress, 0, NULL, &size);
260 if(kAudioHardwareNoError != status) {
261 LOG(LOG_LEVEL_ERROR) << MOD_NAME "AudioObjectGetPropertyDataSize (kAudioDevicePropertyStreamConfiguration) failed: " << status << "\n";
262 return false;
263 }
264
265 AudioBufferList *bufferList = static_cast<AudioBufferList *>(malloc(size));
266 if(NULL == bufferList) {
267 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Unable to allocate memory\n";
268 return false;
269 }
270 status = AudioObjectGetPropertyData(*audioDevice, &propertyAddress, 0, NULL, &size, bufferList);
271 if(kAudioHardwareNoError != status || 0 == bufferList->mNumberBuffers) {
272 if(kAudioHardwareNoError != status)
273 LOG(LOG_LEVEL_ERROR) << MOD_NAME "AudioObjectGetPropertyData (kAudioDevicePropertyStreamConfiguration) failed: " << status << "\n";
274 free(bufferList);
275 return false;
276 }
277 free(bufferList);
278 return true;
279}

References LOG, LOG_LEVEL_ERROR, and MOD_NAME.

Referenced by audio_ca_probe().

◆ REGISTER_MODULE()

REGISTER_MODULE ( coreaudio ,
& aplay_coreaudio_info,
LIBRARY_CLASS_AUDIO_PLAYBACK ,
AUDIO_PLAYBACK_ABI_VERSION  )

◆ theRenderProc()

static OSStatus theRenderProc ( void * inRefCon,
AudioUnitRenderActionFlags * inActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumFrames,
AudioBufferList * ioData )
static

Definition at line 97 of file coreaudio.cpp.

102{
103 UNUSED(inActionFlags);
104 UNUSED(inTimeStamp);
105 UNUSED(inBusNumber);
106
107 struct state_ca_playback * s = (struct state_ca_playback *) inRefCon;
108 int write_bytes = inNumFrames * s->audio_packet_size;
109
110 int ret = s->buffer_fns->read(s->buffer, (char *) ioData->mBuffers[0].mData, write_bytes);
111 ioData->mBuffers[0].mDataByteSize = ret;
112
113 if(ret < write_bytes) {
114 if (!s->quiet) {
115 LOG(LOG_LEVEL_WARNING) << MOD_NAME "Audio buffer underflow (" << write_bytes << " requested, " << ret << " written).\n";
116 }
117 //memset(ioData->mBuffers[0].mData, 0, write_bytes);
118 ioData->mBuffers[0].mDataByteSize = ret;
119 if (!s->quiet && duration_cast<seconds>(steady_clock::now() - s->last_audio_read).count() > NO_DATA_STOP_SEC) {
120 LOG(LOG_LEVEL_WARNING) << MOD_NAME "No data for " << NO_DATA_STOP_SEC << " seconds! Stopping.\n";
121 s->quiet = true;
122 }
123 } else {
124 if (s->quiet) {
125 LOG(LOG_LEVEL_NOTICE) << MOD_NAME "Starting again.\n";
126 }
127 s->quiet = false;
128 s->last_audio_read = steady_clock::now();
129 }
130 return noErr;
131}
#define UNUSED(x)
#define NO_DATA_STOP_SEC
Definition coreaudio.cpp:76
int(* read)(void *buf, char *out, int max_len)
bool quiet
do not report buffer underruns if we do not receive data at all for a long period
Definition coreaudio.cpp:86
steady_clock::time_point last_audio_read
Definition coreaudio.cpp:85

References state_ca_playback::audio_packet_size, state_ca_playback::buffer, state_ca_playback::buffer_fns, state_ca_playback::last_audio_read, LOG, LOG_LEVEL_NOTICE, LOG_LEVEL_WARNING, MOD_NAME, NO_DATA_STOP_SEC, state_ca_playback::quiet, audio_buffer_api::read, and UNUSED.

Referenced by audio_play_ca_reconfigure().

Variable Documentation

◆ aplay_coreaudio_info

const struct audio_playback_info aplay_coreaudio_info
static
Initial value:
= {
}
static bool audio_play_ca_ctl(void *state, int request, void *data, size_t *len)
static void audio_play_ca_put_frame(void *state, const struct audio_frame *frame)
static void audio_play_ca_done(void *state)
static void * audio_play_ca_init(const char *cfg)
static bool audio_play_ca_reconfigure(void *state, struct audio_desc desc)

Definition at line 538 of file coreaudio.cpp.

◆ CA_DIR

int CA_DIR = 1
constexpr

Definition at line 75 of file coreaudio.cpp.

Referenced by audio_play_ca_init().

◆ DEFAULT_BUFLEN_MS

int DEFAULT_BUFLEN_MS = 50
constexpr

Definition at line 74 of file coreaudio.cpp.