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.
22 #include "CAudioIODef.h"
23 #include <sound_manager_internal.h>
26 using namespace tizen_media_audio;
32 CAudioIO::CAudioIO() :
33 mpPulseAudioClient(NULL),
34 __mMutex(PTHREAD_MUTEX_INITIALIZER),
35 __mCondMutex(PTHREAD_MUTEX_INITIALIZER),
36 __mCond(PTHREAD_COND_INITIALIZER),
38 mDirection = CAudioInfo::EAudioDirection::AUDIO_DIRECTION_MAX;
39 mState = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
40 mStatePrev = CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE;
44 CAudioIO::CAudioIO(CAudioInfo& audioInfo) :
45 mpPulseAudioClient(NULL),
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 CAudioIO::~CAudioIO() {
60 void CAudioIO::setInit(bool flag) {
64 bool CAudioIO::isInit() {
68 bool CAudioIO::IsReady() {
69 return ((mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_RUNNING ||
70 mState == CAudioInfo::EAudioIOState::AUDIO_IO_STATE_PAUSED)? true : false);
73 void CAudioIO::internalLock() {
74 if (__mIsInit == false)
75 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
77 if (pthread_mutex_lock(&__mMutex) != 0)
78 THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
80 #ifdef _AUDIO_IO_DEBUG_TIMING_
81 AUDIO_IO_LOGD(COLOR_RED "%p LOCKED" COLOR_END, &__mMutex);
85 void CAudioIO::internalUnlock() {
86 if (__mIsInit == false)
87 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
89 if (pthread_mutex_unlock(&__mMutex) != 0)
90 THROW_ERROR_MSG(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
92 #ifdef _AUDIO_IO_DEBUG_TIMING_
93 AUDIO_IO_LOGD(COLOR_GREEN "%p UNLOCKED" COLOR_END, &__mMutex);
97 void CAudioIO::internalWait() {
98 if (__mIsInit == false)
99 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
101 #ifdef _AUDIO_IO_DEBUG_TIMING_
102 AUDIO_IO_LOGD(COLOR_RED "WAIT" COLOR_END);
105 pthread_mutex_lock(&__mCondMutex);
106 pthread_cond_wait(&__mCond, &__mCondMutex);
107 pthread_mutex_unlock(&__mCondMutex);
110 void CAudioIO::internalSignal() {
111 if (__mIsInit == false)
112 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
114 #ifdef _AUDIO_IO_DEBUG_TIMING_
115 AUDIO_IO_LOGD(COLOR_GREEN "SIGNAL" COLOR_END);
118 pthread_mutex_lock(&__mCondMutex);
119 pthread_cond_signal(&__mCond);
120 pthread_mutex_unlock(&__mCondMutex);
123 void CAudioIO::initialize() {
124 if (__mIsInit == true)
127 AUDIO_IO_LOGD("initialize");
129 int ret = pthread_mutex_init(&__mMutex, NULL);
131 THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_init()");
133 ret = pthread_cond_init(&__mCond, NULL);
135 THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_init()");
140 void CAudioIO::finalize() {
141 if (__mIsInit == false)
144 AUDIO_IO_LOGD("finalize");
146 bool error_occured = false;
147 int ret = pthread_mutex_destroy(&__mMutex);
149 AUDIO_IO_LOGE("Failed pthread_mutex_destroy(%p) errno:%d", &__mMutex, ret);
150 error_occured = true;
153 ret = pthread_mutex_destroy(&__mCondMutex);
155 AUDIO_IO_LOGE("Failed cond pthread_mutex_destroy(%p) errno:%d", &__mCondMutex, ret);
156 error_occured = true;
159 ret = pthread_cond_destroy(&__mCond);
161 AUDIO_IO_LOGE("Failed pthread_cond_destroy(%p) errno:%d", &__mCond, ret);
162 error_occured = true;
166 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "Finalize Failed");
171 void CAudioIO::onStream(CPulseAudioClient* pClient, size_t length) {
172 assert(__mIsInit == true);
173 assert(pClient != NULL);
176 #ifdef _AUDIO_IO_DEBUG_TIMING_
177 AUDIO_IO_LOGD("mStreamCallback.onStream(%p), pClient(%p), length(%zu)", mStreamCallback.onStream, pClient, length);
180 if (mStreamCallback.onStream != NULL)
181 mStreamCallback.onStream(length, mStreamCallback.mUserData);
184 void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) {
185 assert(__mIsInit == true);
186 assert(state >= CAudioInfo::EAudioIOState::AUDIO_IO_STATE_NONE && state < CAudioInfo::EAudioIOState::AUDIO_IO_STATE_MAX);
190 mByPolicy = byPolicy;
192 if (mState == mStatePrev)
195 const char* state_string[] = { "NONE", "IDLE", "RUNNING", "PAUSED" };
197 AUDIO_IO_LOGD("previous(%s,%d) ===> current(%s,%d), by_policy(%d)",
198 state_string[static_cast<int>(mStatePrev)],
199 static_cast<int>(mStatePrev),
200 state_string[static_cast<int>(mState)],
201 static_cast<int>(mState),
204 if (mStateChangedCallback.onStateChanged != NULL)
205 mStateChangedCallback.onStateChanged(mState, mStatePrev, mByPolicy, mStateChangedCallback.mUserData);
208 void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state) {
209 onStateChanged(state, false);
212 CAudioInfo::EAudioIOState CAudioIO::getState() {
216 void CAudioIO::prepare() {
217 if (__mIsInit == false)
218 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
221 void CAudioIO::unprepare() {
222 if (__mIsInit == false)
223 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
226 void CAudioIO::pause() {
227 if (__mIsInit == false || IsReady() == false)
228 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
232 AUDIO_IO_LOGD("pause");
233 mpPulseAudioClient->cork(true);
235 } catch (CAudioError& e) {
241 void CAudioIO::resume() {
242 if (__mIsInit == false || IsReady() == false)
243 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
247 AUDIO_IO_LOGD("resume");
248 mpPulseAudioClient->cork(false);
250 } catch (CAudioError& e) {
256 void CAudioIO::drain() {
257 if (__mIsInit == false || IsReady() == false)
258 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
261 if (mpPulseAudioClient->isInThread()) {
262 mpPulseAudioClient->drain();
265 mpPulseAudioClient->drain();
268 } catch (CAudioError& e) {
269 if (!mpPulseAudioClient->isInThread())
275 void CAudioIO::flush() {
276 if (__mIsInit == false || IsReady() == false)
277 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
280 if (mpPulseAudioClient->isInThread()) {
281 mpPulseAudioClient->flush();
284 mpPulseAudioClient->flush();
287 } catch (CAudioError& e) {
288 if (!mpPulseAudioClient->isInThread())
294 CAudioInfo& CAudioIO::getAudioInfo() {
295 if (__mIsInit == false)
296 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
301 void CAudioIO::setStreamCallback(SStreamCallback callback) {
302 if (__mIsInit == false)
303 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
305 mStreamCallback = callback;
308 CAudioIO::SStreamCallback CAudioIO::getStreamCallback() {
309 if (__mIsInit == false)
310 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
312 return mStreamCallback;
315 void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) {
316 if (__mIsInit == false)
317 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
319 mStateChangedCallback = callback;
322 CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() {
323 if (__mIsInit == false)
324 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
326 return mStateChangedCallback;
329 void CAudioIO::setStreamInfo(sound_stream_info_h stream_info) {
330 if (stream_info == NULL)
331 THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_ARGUMENT, "stream_info is NULL");
333 if (__mIsInit == false)
334 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
337 if (mState != CAudioInfo::EAudioIOState::AUDIO_IO_STATE_IDLE)
338 THROW_ERROR_MSG(CAudioError::EError::ERROR_INVALID_STATE, "it is not permitted while started");
340 int errorCode = SOUND_MANAGER_ERROR_NONE;
341 CAudioInfo::EAudioType audioType = CAudioInfo::EAudioType::AUDIO_IN_TYPE_MEDIA;
346 if ((errorCode = sound_manager_is_available_stream_information(stream_info, NATIVE_API_AUDIO_IO, &avail)) != SOUND_MANAGER_ERROR_NONE)
347 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info is invalid [ret:%d]", errorCode);
349 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_NOT_SUPPORTED_TYPE, "Input stream is not supported");
351 if ((errorCode = sound_manager_get_type_from_stream_information(stream_info, &type)) != SOUND_MANAGER_ERROR_NONE)
352 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode);
353 if (mDirection == CAudioInfo::EAudioDirection::AUDIO_DIRECTION_IN)
354 getAudioInfo().convertInputStreamType2AudioType(type, &audioType);
356 getAudioInfo().convertOutputStreamType2AudioType(type, &audioType);
357 getAudioInfo().setAudioType(audioType);
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);
361 getAudioInfo().setAudioIndex(index);
363 } catch (CAudioError& e) {