__mpSyncReadDataPtr(NULL),
__mSyncReadIndex(0),
__mSyncReadLength(0),
- __mIsUsedSyncRead(false) {
+ __mIsUsedSyncRead(false),
+ __mIsFirstStream(false) {
}
CPulseAudioClient::~CPulseAudioClient() {
case PA_STREAM_READY:
AUDIO_IO_LOGD("The stream is ready");
pClient->__mpListener->onStateChanged(CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING);
+ if (pClient->__mDirection == EStreamDirection::STREAM_DIRECTION_PLAYBACK)
+ pClient->__mIsFirstStream = true;
+ pClient->__mIsInit = true;
pa_threaded_mainloop_signal(pClient->__mpMainloop, 0);
break;
// End of synchronous
pa_threaded_mainloop_unlock(__mpMainloop);
- __mIsInit = true;
+ // __mIsInit = true; // Moved to __streamStateChangeCb()
} catch (CAudioError e) {
finalize();
throw e;
ret = pa_stream_write(__mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
pa_threaded_mainloop_unlock(__mpMainloop);
} else {
+ if (__mIsFirstStream) {
+ const pa_buffer_attr* attr = pa_stream_get_buffer_attr(__mpStream);
+ uint32_t prebuf = attr->prebuf;
+ // Compensate amount of prebuf in first stream callback when audio-io use prebuf(-1)
+ // Because a stream will never start when an application wrote less than prebuf at first
+ if (length < prebuf) {
+ char* dummy = new char[prebuf - length];
+ memset(dummy, 0, prebuf - length);
+ pa_stream_write(__mpStream, dummy, prebuf - length, NULL, 0LL, PA_SEEK_RELATIVE);
+ delete [] dummy;
+ }
+ __mIsFirstStream = false;
+ AUDIO_IO_LOGD("FIRST STREAM CALLBACK : length[%d], prebuf[%d], dummy[%d]", length, prebuf, (length < prebuf) ? prebuf - length : 0);
+ }
ret = pa_stream_write(__mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
}
checkRunningState();
+ // Set __mIsFirstStream flag when uncork(resume) stream, because prebuf will be enable again
+ if (cork == false)
+ __mIsFirstStream = true;
+
if (isInThread() == false) {
pa_threaded_mainloop_lock(__mpMainloop);
pa_operation_unref(pa_stream_cork(__mpStream, static_cast<int>(cork), __successStreamCb, this));
if (__mpStream == NULL || PA_STREAM_IS_GOOD(pa_stream_get_state(__mpStream)) == 0) {
THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_INITIALIZED, "The stream[%p] is not created or not good state", __mpStream);
}
- if (pa_context_get_state(__mpContext) != PA_CONTEXT_READY || pa_stream_get_state(__mpStream) != PA_STREAM_READY) {
+ if (pa_context_get_state(__mpContext) != PA_CONTEXT_READY || pa_stream_get_state(__mpStream) != PA_STREAM_READY) {
THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_INITIALIZED, "The context[%p] or stream[%p] state is not ready", __mpContext, __mpStream);
}