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.
19 #include "CAudioIODef.h"
23 using namespace tizen_media_audio;
27 * class CAudioSessionHandler
29 int CAudioSessionHandler::__sCaptureRef = 0;
31 int CAudioSessionHandler::__pcmCaptureCountInc() {
34 actual = __sCaptureRef;
35 } while (!__sync_bool_compare_and_swap(&__sCaptureRef, actual, actual + 1));
36 AUDIO_IO_LOGD("CaptureRefCount+1 > [%d]", __sCaptureRef);
40 int CAudioSessionHandler::__pcmCaptureCountDec() {
43 actual = __sCaptureRef;
44 } while (!__sync_bool_compare_and_swap(&__sCaptureRef, actual, actual - 1));
45 AUDIO_IO_LOGD("CaptureRefCount-1 > [%d]", __sCaptureRef);
46 if (__sCaptureRef < 0) {
47 AUDIO_IO_LOGE("A CaptureRef[%d] is not valid! Something is wrong!", __sCaptureRef);
53 int CAudioSessionHandler::__pcmCaptureCountGet() {
54 AUDIO_IO_LOGD("CaptureRefCount > [%d]", __sCaptureRef);
58 int CAudioSessionHandler::__sFocusRef = 0;
60 int CAudioSessionHandler::__focusIdCountInc() {
64 } while (!__sync_bool_compare_and_swap(&__sFocusRef, actual, actual + 1));
65 AUDIO_IO_LOGD("FocusRefCount+1 > [%d]", __sFocusRef);
69 int CAudioSessionHandler::__focusIdCountDec() {
73 } while (!__sync_bool_compare_and_swap(&__sFocusRef, actual, actual - 1));
74 AUDIO_IO_LOGD("FocusRefCount-1 > [%d]", __sFocusRef);
78 int CAudioSessionHandler::__focusIdCountGet() {
79 /* AUDIO_IO_LOGD("FocusRefCount > [%d]", __sFocusRef); */
83 CAudioSessionHandler::CAudioSessionHandler(EAudioSessionType sessionType, CAudioInfo& audioInfo, IAudioSessionEventListener* listener) :
86 __mAudioSession(sessionType),
87 __mMultimediaSession(MM_SESSION_TYPE_MEDIA),
88 __mpEventListener(listener),
92 __mAudioInfo = audioInfo;
95 CAudioSessionHandler::~CAudioSessionHandler() {
98 CAudioError CAudioSessionHandler::__convertStreamType(EAudioSessionType type1, MMSessionType type2, int *index) {
102 assert(index != NULL);
104 if (type1 == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE) {
105 for (i = 0 ; i < sizeof(__STREAM_TYPE_TABLE_IN) / sizeof(__STREAM_TYPE_TABLE_IN[0]) ; i++) {
106 if (__STREAM_TYPE_TABLE_IN[i].type == type2) {
112 for (i = 0 ; i < sizeof(__STREAM_TYPE_TABLE_OUT) / sizeof(__STREAM_TYPE_TABLE_OUT[0]) ; i++) {
113 if (__STREAM_TYPE_TABLE_OUT[i].type == type2) {
121 RET_ERROR_MSG(CAudioError::EError::ERROR_NOT_SUPPORTED, "Does not support session type.");
124 RET_ERROR(CAudioError::EError::ERROR_NONE);
127 CAudioError CAudioSessionHandler::__getAsmInformation(MMSessionType *type, int *options) {
128 assert(type != NULL);
129 assert(options != NULL);
131 MMSessionType currentSession = MM_SESSION_TYPE_MEDIA;
132 int sessionOptions = 0;
134 /* Read session information */
136 if ((ret = _mm_session_util_read_information(-1, (int*)¤tSession, &sessionOptions)) < 0) {
137 if (ret == (int) MM_ERROR_INVALID_HANDLE) {
138 RET_ERROR_MSG(CAudioError::EError::ERROR_INVALID_HANDLE, "Failed _mm_session_util_read_information(). Invalid handle");
140 RET_ERROR_MSG(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed _mm_session_util_read_information(). Not exist");
144 *type = currentSession;
145 *options = sessionOptions;
147 RET_ERROR(CAudioError::EError::ERROR_NONE);
150 bool CAudioSessionHandler::__isFocusRequired(MMSessionType type, int options) {
151 if ((options & ASM_SESSION_OPTION_PAUSE_OTHERS)
152 || ((type != MM_SESSION_TYPE_MEDIA) && (type != MM_SESSION_TYPE_MEDIA_RECORD)))
158 int CAudioSessionHandler::getId() {
162 int CAudioSessionHandler::getOptions() {
166 CAudioSessionHandler::EAudioSessionType CAudioSessionHandler::getAudioSession() {
167 return __mAudioSession;
170 MMSessionType CAudioSessionHandler::getMultimediaSession() {
171 return __mMultimediaSession;
174 int CAudioSessionHandler::getSubscribeId() {
175 return __mSubscribeId;
178 CAudioInfo CAudioSessionHandler::getAudioInfo() {
182 void CAudioSessionHandler::__sound_pcm_signal_cb(mm_sound_signal_name_t signal, int value, void *user_data) {
185 AUDIO_IO_LOGD("[signal:%d], [value:%d], [user_data:0x%x]", signal, value, user_data);
187 CAudioSessionHandler* pHandler = static_cast<CAudioSessionHandler*>(user_data);
188 if (pHandler->__mpEventListener != NULL) {
189 pHandler->__mpEventListener->onSignal(pHandler, signal, value);
193 void CAudioSessionHandler::initialize() throw (CAudioError) {
195 if (__mIsInit == true) {
199 MMSessionType currentSession = MM_SESSION_TYPE_MEDIA;
200 int sessionOptions = 0; // Mix with others by default
202 CAudioError err = __getAsmInformation(¤tSession, &sessionOptions);
203 if (err == CAudioError::EError::ERROR_NONE) {
204 // Session was configured before, use focus callback
206 AUDIO_IO_LOGD("Use audio focus concept internally!");
208 if (err == CAudioError::EError::ERROR_INVALID_HANDLE) {
210 unsigned int subscribe_id;
212 int errorCode = mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &value);
213 if (errorCode != MM_ERROR_NONE) {
214 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_get_signal_value() err:0x%x", errorCode);
218 // stream_info was created or focus watch callback was configured before
220 AUDIO_IO_LOGD("Skip audio focus concept!");
221 } else if (value == 0) {
222 // No session, No stream_info, No focus watch callback before
223 // Use focus watch callback with signal subscribe
224 errorCode = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &subscribe_id, __sound_pcm_signal_cb, static_cast<void*>(this));
225 if (errorCode != MM_ERROR_NONE) {
226 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_get_signal_value() err:0x%x", errorCode);
229 __mSubscribeId = (int)subscribe_id;
230 AUDIO_IO_LOGD("Subscribed mm_sound signal");
232 sessionOptions = 0; // Mix with others by default
234 AUDIO_IO_LOGD("Use audio focus(watch) concept internally!");
238 AUDIO_IO_LOGD("Skip audio focus concept!");
241 if (__mAudioSession == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE) {
242 AUDIO_IO_LOGD("Set default \"Media_Record\" type");
243 currentSession = MM_SESSION_TYPE_MEDIA_RECORD;
245 AUDIO_IO_LOGD("Set default \"Media\" type");
246 currentSession = MM_SESSION_TYPE_MEDIA;
250 // Updates session information
251 __mMultimediaSession = currentSession;
252 __mOptions = sessionOptions;
254 if (this->__mAudioSession == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE) {
255 __pcmCaptureCountInc();
261 void CAudioSessionHandler::finalize() {
263 if (__mIsInit == false) {
267 if (__mAudioSession == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE) {
268 __pcmCaptureCountDec();
271 if (__mSubscribeId >= 0) {
272 mm_sound_unsubscribe_signal(__mSubscribeId);
278 bool CAudioSessionHandler::isSkipSessionEvent() throw (CAudioError) {
283 /* Only Support below Event */
284 if (mEvent != ASM_EVENT_CALL && mEvent != ASM_EVENT_VOIP &&
285 mEvent != ASM_EVENT_VIDEOCALL && mEvent != ASM_EVENT_VOICE_RECOGNITION &&
286 mEvent != ASM_EVENT_MMCAMCORDER_AUDIO && mEvent != ASM_EVENT_MMCAMCORDER_VIDEO) {
289 switch (__mAudioInfo.getAudioType()) {
290 case CAudioInfo::AUDIO_IN_TYPE_MEDIA:
291 case CAudioInfo::AUDIO_IN_TYPE_VOICECONTROL:
295 case CAudioInfo::AUDIO_IN_TYPE_MIRRORING:
296 case CAudioInfo::AUDIO_IN_TYPE_LOOPBACK:
305 int captureCount = CAudioSessionHandler::__pcmCaptureCountGet();
306 if (captureCount == 1) {/* If this is last one */
307 /* Recover session information to MEDIA */
308 int sessionResult = _mm_session_util_write_information(-1, MM_SESSION_TYPE_MEDIA, __mOptions);
309 if (sessionResult != 0) {
310 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "Failed _mm_session_util_write_information() ret:%d", sessionResult);
320 void CAudioSessionHandler::__sound_pcm_focus_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data) {
323 AUDIO_IO_LOGD("[id:%d], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s], [user_data:0x%x]", id, focus_type, state, reason_for_change, additional_info, user_data);
325 CAudioSessionHandler* pHandler = static_cast<CAudioSessionHandler*>(user_data);
326 pHandler->__mFocusType = focus_type;
327 pHandler->__mState = state;
328 pHandler->__mReasonForChange = (char *)reason_for_change;
329 pHandler->__mAdditionalInfo = (char *)additional_info;
331 if (pHandler->__mpEventListener != NULL) {
332 pHandler->__mpEventListener->onInterrupt(pHandler, id, focus_type, state, reason_for_change, additional_info);
338 void CAudioSessionHandler::__sound_pcm_focus_watch_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data) {
339 AUDIO_IO_LOGD("[id:%d], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s], [user_data:0x%x]", id, focus_type, state, reason_for_change, additional_info, user_data);
341 CAudioSessionHandler::__sound_pcm_focus_cb(-1, focus_type, state, reason_for_change, additional_info, user_data);
346 void CAudioSessionHandler::registerSound() throw (CAudioError) {
347 if (__mIsInit == false) {
348 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
351 if (__mUseFocus == true) {
353 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Already registered [id:%d]", __mId);
358 if (__isFocusRequired(__mMultimediaSession, __mOptions)) {
360 CAudioError err = __convertStreamType(__mAudioSession, __mMultimediaSession, &index);
361 if (err != CAudioError::EError::ERROR_NONE) {
365 errorCode = mm_sound_focus_get_id(&__mId);
366 if (errorCode != MM_ERROR_NONE) {
367 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_focus_get_id() err:0x%x", errorCode);
370 // Register focus callback
371 errorCode = mm_sound_register_focus(__mId,
372 __mAudioSession == EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE ? __STREAM_TYPE_TABLE_IN[index].name : __STREAM_TYPE_TABLE_OUT[index].name,
373 __sound_pcm_focus_cb,
374 static_cast<void*>(this));
375 if (errorCode != MM_ERROR_NONE) {
376 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_register_focus() err:0x%x", errorCode);
381 AUDIO_IO_LOGD("Focus callback registered successfully [id:%d]", __mId);
382 } else if (!(__mOptions & ASM_SESSION_OPTION_UNINTERRUPTIBLE)) {
383 // Register focus watch callback
384 errorCode = mm_sound_set_focus_watch_callback(FOCUS_FOR_BOTH, __sound_pcm_focus_watch_cb, static_cast<void*>(this), &__mId);
386 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_set_focus_watch_callback() err:0x%x", errorCode);
391 AUDIO_IO_LOGD("Focus watch callback registered successfully [id:%d]", __mId);
396 void CAudioSessionHandler::unregisterSound() throw (CAudioError) {
397 if (__mIsInit == false) {
398 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
401 if (__mUseFocus == true) {
403 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Did not register [id:%d]", __mId);
408 if (__isFocusRequired(__mMultimediaSession, __mOptions)) {
409 // Unregister focus callback
410 errorCode = mm_sound_unregister_focus(__mId);
411 if (errorCode != MM_ERROR_NONE) {
412 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_unregister_focus() err:0x%x", errorCode);
417 AUDIO_IO_LOGD("Focus callback unregistered successfully [id:%d]", __mId);
419 } else if (!(__mOptions & ASM_SESSION_OPTION_UNINTERRUPTIBLE)) {
420 // Unregister focus watch callback.
421 errorCode = mm_sound_unset_focus_watch_callback(__mId);
423 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_unset_focus_watch_callback() err:0x%x", errorCode);
428 AUDIO_IO_LOGD("Focus watch callback unregistered successfully [id:%d]", __mId);
434 void CAudioSessionHandler::updatePlaying() throw (CAudioError) {
435 if (__mIsInit == false) {
436 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
439 if (__mUseFocus && __isFocusRequired(__mMultimediaSession, __mOptions)) {
441 int ret = mm_sound_acquire_focus(__mId, FOCUS_FOR_BOTH, "audio-io acquire focus");
442 if (ret != MM_ERROR_NONE) {
443 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_acquire_focus() err:0x%x", ret);
445 AUDIO_IO_LOGD("Focus acquired successfully [id:%d]", __mId);
450 void CAudioSessionHandler::updateStop() throw (CAudioError) {
451 if (__mIsInit == false) {
452 THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
455 if (__mUseFocus && __isFocusRequired(__mMultimediaSession, __mOptions)) {
457 int ret = mm_sound_release_focus(__mId, FOCUS_FOR_BOTH, "audio-io release focus");
458 if (ret != MM_ERROR_NONE) {
459 THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_POLICY_BLOCKED, "Failed mm_sound_release_focus() err:0x%x", ret);
461 AUDIO_IO_LOGD("Focus released successfully [id:%d]", __mId);
466 void CAudioSessionHandler::disableSessionHandler() throw (CAudioError) {
467 CAudioSessionHandler::updateStop();
468 CAudioSessionHandler::unregisterSound();
470 CAudioSessionHandler::__mUseFocus = false;
474 * class IAudioSessionEventListener
476 IAudioSessionEventListener::EInterruptCode IAudioSessionEventListener::convertInterruptedCode(int code, const char *reason_for_change) {
477 EInterruptCode e = EInterruptCode::INTERRUPT_COMPLETED;
481 case FOCUS_IS_ACQUIRED:
482 e = EInterruptCode::INTERRUPT_COMPLETED;
485 case FOCUS_IS_RELEASED:
486 if (!strcmp(reason_for_change, "media")) e = EInterruptCode::INTERRUPT_BY_MEDIA;
487 if (!strcmp(reason_for_change, "radio")) e = EInterruptCode::INTERRUPT_BY_MEDIA;
488 if (!strcmp(reason_for_change, "loopback")) e = EInterruptCode::INTERRUPT_BY_MEDIA;
489 if (!strcmp(reason_for_change, "system")) e = EInterruptCode::INTERRUPT_BY_MEDIA;
490 if (!strcmp(reason_for_change, "alarm")) e = EInterruptCode::INTERRUPT_BY_ALARM;
491 if (!strcmp(reason_for_change, "notification")) e = EInterruptCode::INTERRUPT_BY_NOTIFICATION;
492 if (!strcmp(reason_for_change, "emergency")) e = EInterruptCode::INTERRUPT_BY_EMERGENCY;
493 if (!strcmp(reason_for_change, "voice-information")) e = EInterruptCode::INTERRUPT_BY_MEDIA; //for what?
494 if (!strcmp(reason_for_change, "voice-recognition")) e = EInterruptCode::INTERRUPT_BY_MEDIA; //for what?
495 if (!strcmp(reason_for_change, "ringtone-voip")) e = EInterruptCode::INTERRUPT_BY_MEDIA; //for what?
496 if (!strcmp(reason_for_change, "ringtone-call")) e = EInterruptCode::INTERRUPT_BY_MEDIA; //for what?
497 if (!strcmp(reason_for_change, "voip")) e = EInterruptCode::INTERRUPT_BY_MEDIA; //for what?
498 if (!strcmp(reason_for_change, "call-voice")) e = EInterruptCode::INTERRUPT_BY_MEDIA; //for what?
499 if (!strcmp(reason_for_change, "call-video")) e = EInterruptCode::INTERRUPT_BY_MEDIA; //for what?