void ca_Flush(audio_output_t *p_aout, bool wait) { struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys; if (wait) { int32_t i_bytes; while (TPCircularBufferTail(&p_sys->circular_buffer, &i_bytes) != NULL) { /* Calculate the duration of the circular buffer, in order to wait * for the render thread to play it all */ const mtime_t i_frame_us = FramesToUs(p_sys, BytesToFrames(p_sys, i_bytes)) + 10000; msleep(i_frame_us / 2); } } else { /* flush circular buffer if data is left */ TPCircularBufferClear(&p_sys->circular_buffer); } }
int coreaudio_object_flush(struct audio_object *object) { struct coreaudio_object *self = to_coreaudio_object(object); if (!self->initialized) return noErr; OSStatus err = AudioOutputUnitStop(self->outputUnit); TPCircularBufferClear(&(self->circularBuffer)); self->running = FALSE; return err; }
int coreaudio_object_write(struct audio_object *object, const void *data, size_t bytes) { struct coreaudio_object *self = to_coreaudio_object(object); if (!self->initialized) return noErr; bool runningAtStart = self->running; if(!runningAtStart) { TPCircularBufferClear(&(self->circularBuffer)); } char *dataPtr = (char*)data; // copy data to our circular buffer // Poll while we don't have space in the buffer. AudioBufferList *bufferList; UInt32 available; while(bytes > 0) { while((!runningAtStart || self->running) && (available = TPCircularBufferGetAvailableSpace(&(self->circularBuffer), &(self->format))) == 0) usleep(10000); // check we didn't stop if(runningAtStart && (!self->running)) return noErr; bufferList = TPCircularBufferPrepareEmptyAudioBufferListWithAudioFormat(&(self->circularBuffer), &(self->format), available, NULL); // we are writing mono/interleaved data so we have one buffer UInt32 bytesToWrite = min(bytes, bufferList->mBuffers[0].mDataByteSize); bufferList->mBuffers[0].mNumberChannels = (self->format).mChannelsPerFrame; bufferList->mBuffers[0].mDataByteSize = bytesToWrite; memcpy(bufferList->mBuffers[0].mData, dataPtr, bytesToWrite); TPCircularBufferProduceAudioBufferList(&(self->circularBuffer), NULL); dataPtr += bytesToWrite; bytes -= bytesToWrite; if(! runningAtStart) { OSStatus err = AudioOutputUnitStart(self->outputUnit); if(err == noErr) { self->running = TRUE; runningAtStart = TRUE; } else { return err; } } } return noErr; }