2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include "CAudioIODef.h"
21 #include <sound_manager_internal.h>
24 using namespace tizen_media_audio;
31 CAudioIO::CAudioIO() :
32 mpPulseAudioClient(nullptr),
33 __mMutex(PTHREAD_MUTEX_INITIALIZER),
34 __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
35 __mCond(PTHREAD_COND_INITIALIZER),
37 mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
38 mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
39 mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
44 CAudioIO::CAudioIO(CAudioInfo& audioInfo) :
45 mpPulseAudioClient(nullptr),
46 __mMutex(PTHREAD_MUTEX_INITIALIZER),
47 __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
48 __mCond(PTHREAD_COND_INITIALIZER),
50 mAudioInfo = audioInfo;
51 mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
52 mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
53 mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
57 void CAudioIO::setInit(bool flag) {
61 bool CAudioIO::isInit() {
65 bool CAudioIO::IsReady() {
66 return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING ||
67 mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED));
70 void CAudioIO::internalLock() {
72 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
74 if (pthread_mutex_lock(&__mMutex) != 0)
75 THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()"); //LCOV_EXCL_LINE
77 #ifdef _AUDIO_IO_DEBUG_TIMING_
78 AUDIO_IO_LOGD(COLOR_RED "%p LOCKED" COLOR_END, &__mMutex);
82 void CAudioIO::internalUnlock() {
84 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
86 if (pthread_mutex_unlock(&__mMutex) != 0)
87 THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()"); //LCOV_EXCL_LINE
89 #ifdef _AUDIO_IO_DEBUG_TIMING_
90 AUDIO_IO_LOGD(COLOR_GREEN "%p UNLOCKED" COLOR_END, &__mMutex);
94 void CAudioIO::internalWait() {
96 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
98 #ifdef _AUDIO_IO_DEBUG_TIMING_
99 AUDIO_IO_LOGD(COLOR_RED "WAIT" COLOR_END);
102 pthread_mutex_lock(&__mCondMutex);
103 pthread_cond_wait(&__mCond, &__mCondMutex);
104 pthread_mutex_unlock(&__mCondMutex);
107 void CAudioIO::internalSignal() {
109 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
111 #ifdef _AUDIO_IO_DEBUG_TIMING_
112 AUDIO_IO_LOGD(COLOR_GREEN "SIGNAL" COLOR_END);
115 pthread_mutex_lock(&__mCondMutex);
116 pthread_cond_signal(&__mCond);
117 pthread_mutex_unlock(&__mCondMutex);
120 void CAudioIO::initialize() {
124 AUDIO_IO_LOGD("initialize");
126 int ret = pthread_mutex_init(&__mMutex, NULL);
128 THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_init()"); //LCOV_EXCL_LINE
130 ret = pthread_cond_init(&__mCond, NULL);
132 THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_init()"); //LCOV_EXCL_LINE
137 void CAudioIO::finalize() {
141 AUDIO_IO_LOGD("finalize");
143 bool error_occured = false;
144 int ret = pthread_mutex_destroy(&__mMutex);
147 AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mMutex, ret);
148 error_occured = true;
152 ret = pthread_mutex_destroy(&__mCondMutex);
155 AUDIO_IO_LOGE("Failed cond pthread_mutex_destroy(%p) errno:%d", &__mCondMutex, ret);
156 error_occured = true;
160 ret = pthread_cond_destroy(&__mCond);
163 AUDIO_IO_LOGE("Failed pthread_cond_destroy(%p) errno:%d", &__mCond, ret);
164 error_occured = true;
169 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Finalize Failed"); //LCOV_EXCL_LINE
174 void CAudioIO::onStream(CPulseAudioClient* pClient, size_t length) {
179 #ifdef _AUDIO_IO_DEBUG_TIMING_
180 AUDIO_IO_LOGD("mStreamCallback.onStream(%p), pClient(%p), length(%zu)", mStreamCallback.onStream, pClient, length);
183 if (mStreamCallback.onStream)
184 mStreamCallback.onStream(length, mStreamCallback.mUserData);
187 void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) {
189 assert(state >= CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE && state < CAudioInfo::EAudioIOState::AUDIO_IO_STATE_MAX);
193 mByPolicy = byPolicy;
195 if (mState == mStatePrev)
198 static const char* state_string[] = { "NONE", "IDLE", "RUNNING", "PAUSED" };
200 AUDIO_IO_LOGD("previous(%s,%d) ===> current(%s,%d), by_policy(%d)",
201 state_string[static_cast<int>(mStatePrev)],
202 static_cast<int>(mStatePrev),
203 state_string[static_cast<int>(mState)],
204 static_cast<int>(mState),
207 if (mStateChangedCallback.onStateChanged)
208 mStateChangedCallback.onStateChanged(mState, mStatePrev, mByPolicy, mStateChangedCallback.mUserData);
211 void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state) {
212 onStateChanged(state, false);
215 CAudioInfo::EAudioIOState CAudioIO::getState() noexcept {
219 void CAudioIO::prepare() {
221 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
224 void CAudioIO::unprepare() {
226 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
229 void CAudioIO::pause() {
230 if (!__mIsInit || !IsReady())
231 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); //LCOV_EXCL_LINE
235 AUDIO_IO_LOGD("pause");
236 mpPulseAudioClient->cork(true);
238 } catch (const CAudioError& e) {
244 void CAudioIO::resume() {
245 if (!__mIsInit || !IsReady())
246 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); //LCOV_EXCL_LINE
250 AUDIO_IO_LOGD("resume");
251 mpPulseAudioClient->cork(false);
253 } catch (const CAudioError& e) {
259 void CAudioIO::drain() {
260 if (!__mIsInit || !IsReady())
261 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); //LCOV_EXCL_LINE
264 if (mpPulseAudioClient->isInThread()) {
265 mpPulseAudioClient->drain();
268 mpPulseAudioClient->drain();
271 } catch (const CAudioError& e) {
272 if (!mpPulseAudioClient->isInThread())
278 void CAudioIO::flush() {
279 if (!__mIsInit || !IsReady())
280 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO"); //LCOV_EXCL_LINE
283 if (mpPulseAudioClient->isInThread()) {
284 mpPulseAudioClient->flush();
287 mpPulseAudioClient->flush();
290 } catch (const CAudioError& e) {
291 if (!mpPulseAudioClient->isInThread())
297 CAudioInfo& CAudioIO::getAudioInfo() {
299 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
304 void CAudioIO::setStreamCallback(SStreamCallback callback) {
306 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
308 mStreamCallback = callback;
311 CAudioIO::SStreamCallback CAudioIO::getStreamCallback() {
313 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
315 return mStreamCallback;
318 void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) {
320 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
322 mStateChangedCallback = callback;
325 CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() {
327 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
329 return mStateChangedCallback;
332 void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) {
334 THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_ARGUMENT, "stream_info is NULL"); //LCOV_EXCL_LINE
337 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO"); //LCOV_EXCL_LINE
339 if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE)
340 THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started"); //LCOV_EXCL_LINE
342 int errorCode = SOUND_MANAGER_ERROR_NONE;
343 char *type = nullptr;
347 if ((errorCode = sound_manager_is_available_stream_information(stream_info, NATIVE_API_AUDIO_IO, &avail)) != SOUND_MANAGER_ERROR_NONE)
348 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info is invalid [ret:%d]", errorCode); //LCOV_EXCL_LINE
350 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE, "Input stream is not supported"); //LCOV_EXCL_LINE
352 if ((errorCode = sound_manager_get_type_from_stream_information(stream_info, &type)) != SOUND_MANAGER_ERROR_NONE)
353 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode); //LCOV_EXCL_LINE
354 if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN)
355 getAudioInfo().setAudioTypeByInputStreamType(type);
357 getAudioInfo().setAudioTypeByOutputStreamType(type);
359 if ((errorCode = sound_manager_get_index_from_stream_information(stream_info, &index)) != SOUND_MANAGER_ERROR_NONE)
360 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->index is invalid [ret:%d]", errorCode); //LCOV_EXCL_LINE
361 getAudioInfo().setAudioIndex(index);